package unit

import (
	"context"
	"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/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/tests/testutils"
)

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

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

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

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

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

	t.Run("过滤平台角色可用权限", func(t *testing.T) {
		filters := map[string]interface{}{
			"available_for_role_type": 1,
		}
		perms, _, err := store.List(ctx, nil, filters)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "platform:only")
		assert.Contains(t, codes, "common:perm")
		assert.NotContains(t, codes, "customer:only")
	})

	t.Run("过滤客户角色可用权限", func(t *testing.T) {
		filters := map[string]interface{}{
			"available_for_role_type": 2,
		}
		perms, _, err := store.List(ctx, nil, filters)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "customer:only")
		assert.Contains(t, codes, "common:perm")
		assert.NotContains(t, codes, "platform:only")
	})

	t.Run("不过滤时返回所有权限", func(t *testing.T) {
		perms, _, err := store.List(ctx, nil, nil)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "platform:only")
		assert.Contains(t, codes, "customer:only")
		assert.Contains(t, codes, "common:perm")
	})
}

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

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

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

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

	t.Run("GetAll按平台角色类型过滤", func(t *testing.T) {
		roleType := 1
		perms, err := store.GetAll(ctx, &roleType, nil)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "platform:menu")
		assert.NotContains(t, codes, "customer:menu")
	})

	t.Run("GetAll按客户角色类型过滤", func(t *testing.T) {
		roleType := 2
		perms, err := store.GetAll(ctx, &roleType, nil)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "customer:menu")
		assert.NotContains(t, codes, "platform:menu")
	})

	t.Run("GetAll不过滤时返回所有", func(t *testing.T) {
		perms, err := store.GetAll(ctx, nil, nil)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "platform:menu")
		assert.Contains(t, codes, "customer:menu")
	})
}

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

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

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

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

	t.Run("同时按平台和角色类型过滤", func(t *testing.T) {
		roleType := 1
		perms, err := store.GetByPlatform(ctx, "web", &roleType)
		require.NoError(t, err)

		var codes []string
		for _, p := range perms {
			codes = append(codes, p.PermCode)
		}
		assert.Contains(t, codes, "web:platform")
		assert.NotContains(t, codes, "h5:customer")
	})
}
