package unit

import (
	"testing"

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

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

func TestRoleService_AssignPermissions_ValidateAvailableForRoleTypes(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	roleStore := postgres.NewRoleStore(tx)
	permStore := postgres.NewPermissionStore(tx)
	rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
	service := role.New(roleStore, permStore, rolePermStore)

	ctx := createContextWithUserID(1)

	platformRole := &model.Role{
		RoleName: "平台管理员",
		RoleDesc: "平台角色",
		RoleType: 1,
		Status:   constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := roleStore.Create(ctx, platformRole)
	require.NoError(t, err)

	customerRole := &model.Role{
		RoleName: "客户管理员",
		RoleDesc: "客户角色",
		RoleType: 2,
		Status:   constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err = roleStore.Create(ctx, customerRole)
	require.NoError(t, err)

	platformPerm := &model.Permission{
		PermName:              "平台权限",
		PermCode:              "platform:manage",
		PermType:              1,
		Platform:              "all",
		AvailableForRoleTypes: "1",
		Status:                constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err = permStore.Create(ctx, platformPerm)
	require.NoError(t, err)

	customerPerm := &model.Permission{
		PermName:              "客户权限",
		PermCode:              "customer:manage",
		PermType:              1,
		Platform:              "all",
		AvailableForRoleTypes: "2",
		Status:                constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err = permStore.Create(ctx, customerPerm)
	require.NoError(t, err)

	commonPerm := &model.Permission{
		PermName:              "通用权限",
		PermCode:              "common:view",
		PermType:              1,
		Platform:              "all",
		AvailableForRoleTypes: "1,2",
		Status:                constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err = permStore.Create(ctx, commonPerm)
	require.NoError(t, err)

	t.Run("为平台角色分配平台权限-成功", func(t *testing.T) {
		rps, err := service.AssignPermissions(ctx, platformRole.ID, []uint{platformPerm.ID})
		require.NoError(t, err)
		assert.NotEmpty(t, rps)
	})

	t.Run("为平台角色分配通用权限-成功", func(t *testing.T) {
		rps, err := service.AssignPermissions(ctx, platformRole.ID, []uint{commonPerm.ID})
		require.NoError(t, err)
		assert.NotEmpty(t, rps)
	})

	t.Run("为平台角色分配客户专用权限-失败", func(t *testing.T) {
		_, err := service.AssignPermissions(ctx, platformRole.ID, []uint{customerPerm.ID})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "不适用于此角色类型")
	})

	t.Run("为客户角色分配客户权限-成功", func(t *testing.T) {
		rps, err := service.AssignPermissions(ctx, customerRole.ID, []uint{customerPerm.ID})
		require.NoError(t, err)
		assert.NotEmpty(t, rps)
	})

	t.Run("为客户角色分配平台专用权限-失败", func(t *testing.T) {
		_, err := service.AssignPermissions(ctx, customerRole.ID, []uint{platformPerm.ID})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "不适用于此角色类型")
	})

	t.Run("批量分配权限时部分不匹配-失败", func(t *testing.T) {
		_, err := service.AssignPermissions(ctx, platformRole.ID, []uint{platformPerm.ID, customerPerm.ID})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "不适用于此角色类型")
	})
}

func TestRoleService_UpdateStatus(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

	roleStore := postgres.NewRoleStore(tx)
	permStore := postgres.NewPermissionStore(tx)
	rolePermStore := postgres.NewRolePermissionStore(tx, rdb)
	service := role.New(roleStore, permStore, rolePermStore)

	ctx := createContextWithUserID(1)

	testRole := &model.Role{
		RoleName: "测试角色",
		RoleDesc: "用于测试状态切换",
		RoleType: 1,
		Status:   constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := roleStore.Create(ctx, testRole)
	require.NoError(t, err)

	t.Run("禁用角色", func(t *testing.T) {
		err := service.UpdateStatus(ctx, testRole.ID, constants.StatusDisabled)
		require.NoError(t, err)

		role, err := roleStore.GetByID(ctx, testRole.ID)
		require.NoError(t, err)
		assert.Equal(t, constants.StatusDisabled, role.Status)
	})

	t.Run("启用角色", func(t *testing.T) {
		err := service.UpdateStatus(ctx, testRole.ID, constants.StatusEnabled)
		require.NoError(t, err)

		role, err := roleStore.GetByID(ctx, testRole.ID)
		require.NoError(t, err)
		assert.Equal(t, constants.StatusEnabled, role.Status)
	})

	t.Run("更新不存在的角色-失败", func(t *testing.T) {
		err := service.UpdateStatus(ctx, 99999, constants.StatusEnabled)
		require.Error(t, err)
		assert.Contains(t, err.Error(), "角色不存在")
	})
}
