package integration

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/break/junhong_cmp_fiber/internal/model"
	roleService "github.com/break/junhong_cmp_fiber/internal/service/role"
	postgresStore "github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/tests/testutils/integ"
)

// TestRolePermissionAssociation_AssignPermissions 测试角色权限分配功能
func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	env.TX.AutoMigrate(
		&model.Role{},
		&model.Permission{},
		&model.RolePermission{},
	)

	roleStore := postgresStore.NewRoleStore(env.TX)
	permStore := postgresStore.NewPermissionStore(env.TX)
	rolePermStore := postgresStore.NewRolePermissionStore(env.TX, env.Redis)
	roleSvc := roleService.New(roleStore, permStore, rolePermStore)

	// 创建测试用户上下文
	userCtx := env.GetSuperAdminContext()

	t.Run("成功分配单个权限", func(t *testing.T) {
		// 创建测试角色
		role := &model.Role{
			RoleName: "单权限测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		// 创建测试权限
		perm := &model.Permission{
			PermName: "单权限测试",
			PermCode: "single:perm:test",
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(perm)

		// 分配权限
		rps, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
		require.NoError(t, err)
		assert.Len(t, rps, 1)
		assert.Equal(t, role.ID, rps[0].RoleID)
		assert.Equal(t, perm.ID, rps[0].PermID)
	})

	t.Run("成功分配多个权限", func(t *testing.T) {
		// 创建测试角色
		role := &model.Role{
			RoleName: "多权限测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		// 创建多个测试权限
		permIDs := make([]uint, 3)
		for i := 0; i < 3; i++ {
			perm := &model.Permission{
				PermName: "多权限测试_" + string(rune('A'+i)),
				PermCode: "multi:perm:test:" + string(rune('a'+i)),
				PermType: constants.PermissionTypeMenu,
				Status:   constants.StatusEnabled,
			}
			env.TX.Create(perm)
			permIDs[i] = perm.ID
		}

		// 分配权限
		rps, err := roleSvc.AssignPermissions(userCtx, role.ID, permIDs)
		require.NoError(t, err)
		assert.Len(t, rps, 3)
	})

	t.Run("获取角色的权限列表", func(t *testing.T) {
		// 创建测试角色
		role := &model.Role{
			RoleName: "获取权限列表测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		// 创建并分配权限
		perm := &model.Permission{
			PermName: "获取权限列表测试",
			PermCode: "get:perm:list:test",
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(perm)

		_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
		require.NoError(t, err)

		// 获取权限列表
		perms, err := roleSvc.GetPermissions(userCtx, role.ID)
		require.NoError(t, err)
		assert.Len(t, perms, 1)
		assert.Equal(t, perm.ID, perms[0].ID)
	})

	t.Run("移除角色的权限", func(t *testing.T) {
		// 创建测试角色
		role := &model.Role{
			RoleName: "移除权限测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		// 创建并分配权限
		perm := &model.Permission{
			PermName: "移除权限测试",
			PermCode: "remove:perm:test",
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(perm)

		_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
		require.NoError(t, err)

		// 移除权限
		err = roleSvc.RemovePermission(userCtx, role.ID, perm.ID)
		require.NoError(t, err)

		// 验证权限已被软删除
		var rp model.RolePermission
		err = env.RawDB().Unscoped().Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rp).Error
		require.NoError(t, err)
		assert.NotNil(t, rp.DeletedAt)
	})

	t.Run("重复分配权限不会创建重复记录", func(t *testing.T) {
		// 创建测试角色
		role := &model.Role{
			RoleName: "重复权限测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		// 创建测试权限
		perm := &model.Permission{
			PermName: "重复权限测试",
			PermCode: "duplicate:perm:test",
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(perm)

		// 第一次分配
		_, err := roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
		require.NoError(t, err)

		// 第二次分配相同权限
		_, err = roleSvc.AssignPermissions(userCtx, role.ID, []uint{perm.ID})
		require.NoError(t, err)

		// 验证只有一条记录
		var count int64
		env.RawDB().Model(&model.RolePermission{}).Where("role_id = ?", role.ID).Count(&count)
		assert.Equal(t, int64(1), count, "关联记录应该仍然存在，因为没有外键约束")

		// 验证可以独立查询关联记录
		var rpRecord model.RolePermission
		err = env.RawDB().Where("role_id = ? AND perm_id = ?", role.ID, perm.ID).First(&rpRecord).Error
		assert.NoError(t, err, "应该能查询到关联记录")
	})
}
