package unit

import (
	"context"
	"testing"

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

	"github.com/break/junhong_cmp_fiber/internal/model"
	"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"
)

// TestAccountSoftDelete 测试账号软删除功能
func TestAccountSoftDelete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	store := postgres.NewAccountStore(tx, rdb)
	ctx := context.Background()

	// 创建测试账号
	account := &model.Account{
		Username: "soft_delete_user",
		Phone:    "13800000001",
		Password: "hashed_password",
		UserType: constants.UserTypePlatform,
		Status:   constants.StatusEnabled,
	}
	err := store.Create(ctx, account)
	require.NoError(t, err)

	t.Run("软删除账号", func(t *testing.T) {
		err := store.Delete(ctx, account.ID)
		require.NoError(t, err)

		// 正常查询应该找不到
		_, err = store.GetByID(ctx, account.ID)
		assert.Error(t, err)
		assert.Equal(t, gorm.ErrRecordNotFound, err)
	})

	t.Run("使用 Unscoped 可以查到已删除账号", func(t *testing.T) {
		var found model.Account
		err := tx.Unscoped().First(&found, account.ID).Error
		require.NoError(t, err)
		assert.Equal(t, account.Username, found.Username)
		assert.NotNil(t, found.DeletedAt)
	})

	t.Run("软删除后可以重用用户名和手机号", func(t *testing.T) {
		// 创建同名账号（因为原账号已软删除）
		newAccount := &model.Account{
			Username: "soft_delete_user", // 重用已删除账号的用户名
			Phone:    "13800000001",      // 重用已删除账号的手机号
			Password: "hashed_password",
			UserType: constants.UserTypePlatform,
			Status:   constants.StatusEnabled,
		}
		err := store.Create(ctx, newAccount)
		require.NoError(t, err)
		assert.NotEqual(t, account.ID, newAccount.ID)
	})
}

// TestRoleSoftDelete 测试角色软删除功能
func TestRoleSoftDelete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	roleStore := postgres.NewRoleStore(tx)
	ctx := context.Background()

	// 创建测试角色
	role := &model.Role{
		RoleName: "test_role",
		RoleDesc: "测试角色",
		RoleType: constants.RoleTypePlatform,
		Status:   constants.StatusEnabled,
	}
	err := roleStore.Create(ctx, role)
	require.NoError(t, err)

	t.Run("软删除角色", func(t *testing.T) {
		err := roleStore.Delete(ctx, role.ID)
		require.NoError(t, err)

		// 正常查询应该找不到
		_, err = roleStore.GetByID(ctx, role.ID)
		assert.Error(t, err)
		assert.Equal(t, gorm.ErrRecordNotFound, err)
	})

	t.Run("使用 Unscoped 可以查到已删除角色", func(t *testing.T) {
		var found model.Role
		err := tx.Unscoped().First(&found, role.ID).Error
		require.NoError(t, err)
		assert.Equal(t, role.RoleName, found.RoleName)
		assert.NotNil(t, found.DeletedAt)
	})
}

// TestPermissionSoftDelete 测试权限软删除功能
func TestPermissionSoftDelete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	permissionStore := postgres.NewPermissionStore(tx)
	ctx := context.Background()

	// 创建测试权限
	permission := &model.Permission{
		PermName: "测试权限",
		PermCode: "test:permission",
		PermType: constants.PermissionTypeMenu,
		Status:   constants.StatusEnabled,
	}
	err := permissionStore.Create(ctx, permission)
	require.NoError(t, err)

	t.Run("软删除权限", func(t *testing.T) {
		err := permissionStore.Delete(ctx, permission.ID)
		require.NoError(t, err)

		// 正常查询应该找不到
		_, err = permissionStore.GetByID(ctx, permission.ID)
		assert.Error(t, err)
		assert.Equal(t, gorm.ErrRecordNotFound, err)
	})

	t.Run("软删除后可以重用权限码", func(t *testing.T) {
		newPermission := &model.Permission{
			PermName: "新测试权限",
			PermCode: "test:permission", // 重用已删除权限的 perm_code
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		err := permissionStore.Create(ctx, newPermission)
		require.NoError(t, err)
		assert.NotEqual(t, permission.ID, newPermission.ID)
	})
}

// TestAccountRoleSoftDelete 测试账号-角色关联软删除功能
func TestAccountRoleSoftDelete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	accountStore := postgres.NewAccountStore(tx, rdb)
	roleStore := postgres.NewRoleStore(tx)
	accountRoleStore := postgres.NewAccountRoleStore(tx, rdb)
	ctx := context.Background()

	// 创建测试账号
	account := &model.Account{
		Username: "ar_user",
		Phone:    "13800000001",
		Password: "hashed_password",
		UserType: constants.UserTypePlatform,
		Status:   constants.StatusEnabled,
	}
	err := accountStore.Create(ctx, account)
	require.NoError(t, err)

	// 创建测试角色
	role := &model.Role{
		RoleName: "ar_role",
		RoleDesc: "测试角色",
		RoleType: constants.RoleTypePlatform,
		Status:   constants.StatusEnabled,
	}
	err = roleStore.Create(ctx, role)
	require.NoError(t, err)

	// 创建关联
	accountRole := &model.AccountRole{
		AccountID: account.ID,
		RoleID:    role.ID,
		Status:    constants.StatusEnabled,
		Creator:   1,
		Updater:   1,
	}
	err = accountRoleStore.Create(ctx, accountRole)
	require.NoError(t, err)

	t.Run("软删除账号-角色关联", func(t *testing.T) {
		err := accountRoleStore.Delete(ctx, account.ID, role.ID)
		require.NoError(t, err)

		// 查询应该找不到
		roles, err := accountRoleStore.GetByAccountID(ctx, account.ID)
		require.NoError(t, err)
		assert.Len(t, roles, 0)
	})

	t.Run("软删除后可以重新关联", func(t *testing.T) {
		newAccountRole := &model.AccountRole{
			AccountID: account.ID,
			RoleID:    role.ID,
			Status:    constants.StatusEnabled,
			Creator:   1,
			Updater:   1,
		}
		err := accountRoleStore.Create(ctx, newAccountRole)
		require.NoError(t, err)

		// 验证可以查询到
		roles, err := accountRoleStore.GetByAccountID(ctx, account.ID)
		require.NoError(t, err)
		assert.Len(t, roles, 1)
	})
}

// TestRolePermissionSoftDelete 测试角色-权限关联软删除功能
func TestRolePermissionSoftDelete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	roleStore := postgres.NewRoleStore(tx)
	permissionStore := postgres.NewPermissionStore(tx)
	rolePermissionStore := postgres.NewRolePermissionStore(tx, rdb)
	ctx := context.Background()

	// 创建测试角色
	role := &model.Role{
		RoleName: "rp_role",
		RoleDesc: "测试角色",
		RoleType: constants.RoleTypePlatform,
		Status:   constants.StatusEnabled,
	}
	err := roleStore.Create(ctx, role)
	require.NoError(t, err)

	// 创建测试权限
	permission := &model.Permission{
		PermName: "rp_permission",
		PermCode: "rp:permission",
		PermType: constants.PermissionTypeMenu,
		Status:   constants.StatusEnabled,
	}
	err = permissionStore.Create(ctx, permission)
	require.NoError(t, err)

	// 创建关联
	rolePermission := &model.RolePermission{
		RoleID: role.ID,
		PermID: permission.ID,
		Status: constants.StatusEnabled,
	}
	err = rolePermissionStore.Create(ctx, rolePermission)
	require.NoError(t, err)

	t.Run("软删除角色-权限关联", func(t *testing.T) {
		err := rolePermissionStore.Delete(ctx, role.ID, permission.ID)
		require.NoError(t, err)

		// 查询应该找不到
		permissions, err := rolePermissionStore.GetByRoleID(ctx, role.ID)
		require.NoError(t, err)
		assert.Len(t, permissions, 0)
	})

	t.Run("软删除后可以重新关联", func(t *testing.T) {
		newRolePermission := &model.RolePermission{
			RoleID: role.ID,
			PermID: permission.ID,
			Status: constants.StatusEnabled,
		}
		err := rolePermissionStore.Create(ctx, newRolePermission)
		require.NoError(t, err)

		// 验证可以查询到
		permissions, err := rolePermissionStore.GetByRoleID(ctx, role.ID)
		require.NoError(t, err)
		assert.Len(t, permissions, 1)
	})
}
