package gorm

import (
	"context"
	"testing"
	"time"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/stretchr/testify/assert"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// mockShopStore 模拟店铺 Store
type mockShopStore struct {
	subordinateShopIDs []uint
	err                error
}

func (m *mockShopStore) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) {
	if m.err != nil {
		return nil, m.err
	}
	return m.subordinateShopIDs, nil
}

// TestSkipDataPermission 测试跳过数据权限过滤
func TestSkipDataPermission(t *testing.T) {
	ctx := context.Background()

	// 设置跳过标记
	ctx = SkipDataPermission(ctx)

	// 验证标记已设置
	skip, ok := ctx.Value(SkipDataPermissionKey).(bool)
	assert.True(t, ok)
	assert.True(t, skip)
}

// TestRegisterDataPermissionCallback 测试注册数据权限 Callback
func TestRegisterDataPermissionCallback(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{1, 2, 3},
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)
}

// TestDataPermissionCallback_SkipForSuperAdmin 测试超级管理员跳过过滤
func TestDataPermissionCallback_SkipForSuperAdmin(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	type TestModel struct {
		ID      uint
		ShopID  uint
		Creator uint
		Name    string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, ShopID: 100, Creator: 1, Name: "test1"})
	db.Create(&TestModel{ID: 2, ShopID: 200, Creator: 2, Name: "test2"})

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100}, // 只有店铺 100
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置超级管理员 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeSuperAdmin,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 超级管理员应该看到所有数据
	assert.Equal(t, 2, len(results))
}

// TestDataPermissionCallback_SkipForPlatform 测试平台用户跳过过滤
func TestDataPermissionCallback_SkipForPlatform(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	type TestModel struct {
		ID      uint
		ShopID  uint
		Creator uint
		Name    string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, ShopID: 100, Creator: 1, Name: "test1"})
	db.Create(&TestModel{ID: 2, ShopID: 200, Creator: 2, Name: "test2"})

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100}, // 只有店铺 100
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置平台用户 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypePlatform,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 平台用户应该看到所有数据
	assert.Equal(t, 2, len(results))
}

// TestDataPermissionCallback_FilterForAgent 测试代理用户过滤
func TestDataPermissionCallback_FilterForAgent(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表（包含 shop_id 字段以触发店铺层级过滤）
	type TestModel struct {
		ID     uint
		ShopID uint
		Name   string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, ShopID: 100, Name: "test1"})
	db.Create(&TestModel{ID: 2, ShopID: 200, Name: "test2"})
	db.Create(&TestModel{ID: 3, ShopID: 300, Name: "test3"})

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100, 200}, // 只能看到店铺 100 和 200
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context (shop_id = 100)
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 代理用户只能看到自己店铺和下级店铺的数据
	assert.Equal(t, 2, len(results))
	assert.Equal(t, uint(100), results[0].ShopID)
	assert.Equal(t, uint(200), results[1].ShopID)
}

// TestDataPermissionCallback_SkipWithContext 测试通过 Context 跳过过滤
func TestDataPermissionCallback_SkipWithContext(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	type TestModel struct {
		ID      uint
		ShopID  uint
		Creator uint
		Name    string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, ShopID: 100, Creator: 1, Name: "test1"})
	db.Create(&TestModel{ID: 2, ShopID: 200, Creator: 2, Name: "test2"})

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100}, // 只有店铺 100
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context 并跳过过滤
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})
	ctx = SkipDataPermission(ctx)

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 跳过过滤后应该看到所有数据
	assert.Equal(t, 2, len(results))
}

// TestDataPermissionCallback_WithShopID 测试带 shop_id 的过滤
func TestDataPermissionCallback_WithShopID(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	type TestModel struct {
		ID      uint
		Creator uint
		ShopID  uint
		Name    string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, Creator: 1, ShopID: 100, Name: "test1"})
	db.Create(&TestModel{ID: 2, Creator: 2, ShopID: 100, Name: "test2"})
	db.Create(&TestModel{ID: 3, Creator: 2, ShopID: 200, Name: "test3"}) // 不同 shop_id

	// 创建 mock ShopStore
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100, 200}, // 可以看到店铺 100 和 200
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context (shop_id = 100)
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 应该看到 shop_id = 100 和 200 的所有数据（因为 mockStore 返回了这两个店铺 ID）
	assert.Equal(t, 3, len(results))
}

// TestDataPermissionCallback_FilterForEnterprise 测试企业用户过滤
func TestDataPermissionCallback_FilterForEnterprise(t *testing.T) {
	// 创建内存数据库
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表（包含 enterprise_id 字段）
	type TestModel struct {
		ID           uint
		EnterpriseID uint
		Name         string
	}

	err = db.AutoMigrate(&TestModel{})
	assert.NoError(t, err)

	// 插入测试数据
	db.Create(&TestModel{ID: 1, EnterpriseID: 1001, Name: "test1"})
	db.Create(&TestModel{ID: 2, EnterpriseID: 1001, Name: "test2"})
	db.Create(&TestModel{ID: 3, EnterpriseID: 1002, Name: "test3"})

	// 创建 mock ShopStore（企业用户不需要，但注册时需要）
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{},
	}

	// 注册 Callback
	err = RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置企业用户 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeEnterprise,
		ShopID:       0,
		EnterpriseID: 1001,
		CustomerID:   0,
	})

	// 查询数据
	var results []TestModel
	err = db.WithContext(ctx).Find(&results).Error
	assert.NoError(t, err)

	// 企业用户只能看到自己企业的数据
	assert.Equal(t, 2, len(results))
	for _, r := range results {
		assert.Equal(t, uint(1001), r.EnterpriseID)
	}
}

// ============================================================
// 标签表数据权限过滤测试（tb_tag / tb_resource_tag 表）
// ============================================================

// TagModel 模拟标签表（tb_tag）结构
// 注意：必须指定 TableName 为 "tb_tag" 才能触发特殊过滤逻辑
type TagModel struct {
	ID           uint  `gorm:"primaryKey"`
	EnterpriseID *uint `gorm:"column:enterprise_id"`
	ShopID       *uint `gorm:"column:shop_id"`
	Name         string
}

func (TagModel) TableName() string {
	return "tb_tag"
}

// ResourceTagModel 模拟资源标签表（tb_resource_tag）结构
type ResourceTagModel struct {
	ID           uint  `gorm:"primaryKey"`
	EnterpriseID *uint `gorm:"column:enterprise_id"`
	ShopID       *uint `gorm:"column:shop_id"`
	ResourceType string
	ResourceID   uint
	TagID        uint
}

func (ResourceTagModel) TableName() string {
	return "tb_resource_tag"
}

// uintPtr 辅助函数，将 uint 转换为 *uint
func uintPtr(v uint) *uint {
	return &v
}

// setupTagTestDB 创建标签测试数据库和数据
// 返回：db 实例和 mock ShopStore
func setupTagTestDB(t *testing.T) (*gorm.DB, *mockShopStore) {
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	err = db.AutoMigrate(&TagModel{}, &ResourceTagModel{})
	assert.NoError(t, err)

	// 插入测试数据
	// 1. 全局标签（enterprise_id = NULL, shop_id = NULL）
	db.Create(&TagModel{ID: 1, EnterpriseID: nil, ShopID: nil, Name: "全局标签-VIP"})
	db.Create(&TagModel{ID: 2, EnterpriseID: nil, ShopID: nil, Name: "全局标签-重要客户"})

	// 2. 企业标签（enterprise_id = 1001, shop_id = NULL）
	db.Create(&TagModel{ID: 3, EnterpriseID: uintPtr(1001), ShopID: nil, Name: "企业A-测试标签"})
	db.Create(&TagModel{ID: 4, EnterpriseID: uintPtr(1001), ShopID: nil, Name: "企业A-内部标签"})

	// 3. 另一个企业的标签（enterprise_id = 1002, shop_id = NULL）
	db.Create(&TagModel{ID: 5, EnterpriseID: uintPtr(1002), ShopID: nil, Name: "企业B-测试标签"})

	// 4. 店铺标签（enterprise_id = NULL, shop_id = 100）
	db.Create(&TagModel{ID: 6, EnterpriseID: nil, ShopID: uintPtr(100), Name: "店铺100-华东区"})
	db.Create(&TagModel{ID: 7, EnterpriseID: nil, ShopID: uintPtr(100), Name: "店铺100-大客户"})

	// 5. 下级店铺标签（enterprise_id = NULL, shop_id = 200）
	db.Create(&TagModel{ID: 8, EnterpriseID: nil, ShopID: uintPtr(200), Name: "店铺200-华南区"})

	// 6. 其他店铺标签（enterprise_id = NULL, shop_id = 300）
	db.Create(&TagModel{ID: 9, EnterpriseID: nil, ShopID: uintPtr(300), Name: "店铺300-华北区"})

	// 创建 mock ShopStore
	// 假设店铺 100 的下级店铺包括 100 和 200
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100, 200},
	}

	return db, mockStore
}

// TestTagPermission_SuperAdmin 测试超级管理员查询标签（应看到所有标签）
func TestTagPermission_SuperAdmin(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置超级管理员 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeSuperAdmin,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 超级管理员应该看到所有 9 个标签
	assert.Equal(t, 9, len(tags), "超级管理员应该看到所有标签")
}

// TestTagPermission_Platform 测试平台用户查询标签（应看到所有标签）
func TestTagPermission_Platform(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置平台用户 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypePlatform,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 平台用户应该看到所有 9 个标签
	assert.Equal(t, 9, len(tags), "平台用户应该看到所有标签")
}

// TestTagPermission_Agent 测试代理用户查询标签
// 预期：看到自己店铺标签 + 下级店铺标签 + 全局标签
func TestTagPermission_Agent(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（店铺 ID = 100）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 代理用户应该看到：
	// - 2 个全局标签（ID: 1, 2）
	// - 2 个店铺 100 的标签（ID: 6, 7）
	// - 1 个店铺 200（下级）的标签（ID: 8）
	// 总共 5 个标签
	assert.Equal(t, 5, len(tags), "代理用户应该看到自己店铺、下级店铺和全局标签")

	// 验证标签 ID
	expectedIDs := map[uint]bool{1: true, 2: true, 6: true, 7: true, 8: true}
	for _, tag := range tags {
		assert.True(t, expectedIDs[tag.ID], "标签 ID %d 不应该被代理用户看到", tag.ID)
	}

	// 验证看不到的标签
	// - 企业标签（ID: 3, 4, 5）
	// - 其他店铺标签（ID: 9）
	for _, tag := range tags {
		assert.NotEqual(t, uint(3), tag.ID, "代理用户不应该看到企业标签")
		assert.NotEqual(t, uint(4), tag.ID, "代理用户不应该看到企业标签")
		assert.NotEqual(t, uint(5), tag.ID, "代理用户不应该看到企业标签")
		assert.NotEqual(t, uint(9), tag.ID, "代理用户不应该看到其他店铺标签")
	}
}

// TestTagPermission_Agent_NoShopID 测试没有 ShopID 的代理用户
// 预期：只能看到全局标签
func TestTagPermission_Agent_NoShopID(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（没有店铺 ID）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       0, // 没有店铺
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 没有店铺的代理用户只能看到全局标签
	assert.Equal(t, 2, len(tags), "没有店铺的代理用户只能看到全局标签")

	// 验证都是全局标签
	for _, tag := range tags {
		assert.Nil(t, tag.EnterpriseID, "应该是全局标签，enterprise_id 为 NULL")
		assert.Nil(t, tag.ShopID, "应该是全局标签，shop_id 为 NULL")
	}
}

// TestTagPermission_Enterprise 测试企业用户查询标签
// 预期：看到自己企业标签 + 全局标签
func TestTagPermission_Enterprise(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置企业用户 context（企业 ID = 1001）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeEnterprise,
		ShopID:       0,
		EnterpriseID: 1001,
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 企业用户应该看到：
	// - 2 个全局标签（ID: 1, 2）
	// - 2 个企业 1001 的标签（ID: 3, 4）
	// 总共 4 个标签
	assert.Equal(t, 4, len(tags), "企业用户应该看到自己企业和全局标签")

	// 验证标签 ID
	expectedIDs := map[uint]bool{1: true, 2: true, 3: true, 4: true}
	for _, tag := range tags {
		assert.True(t, expectedIDs[tag.ID], "标签 ID %d 不应该被企业用户看到", tag.ID)
	}

	// 验证看不到其他企业的标签
	for _, tag := range tags {
		assert.NotEqual(t, uint(5), tag.ID, "企业用户不应该看到其他企业的标签")
	}

	// 验证看不到店铺标签
	for _, tag := range tags {
		assert.NotEqual(t, uint(6), tag.ID, "企业用户不应该看到店铺标签")
		assert.NotEqual(t, uint(7), tag.ID, "企业用户不应该看到店铺标签")
		assert.NotEqual(t, uint(8), tag.ID, "企业用户不应该看到店铺标签")
		assert.NotEqual(t, uint(9), tag.ID, "企业用户不应该看到店铺标签")
	}
}

// TestTagPermission_Enterprise_NoEnterpriseID 测试没有 EnterpriseID 的企业用户
// 预期：只能看到全局标签
func TestTagPermission_Enterprise_NoEnterpriseID(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置企业用户 context（没有企业 ID）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeEnterprise,
		ShopID:       0,
		EnterpriseID: 0, // 没有企业
		CustomerID:   0,
	})

	// 查询标签
	var tags []TagModel
	err = db.WithContext(ctx).Find(&tags).Error
	assert.NoError(t, err)

	// 没有企业的企业用户只能看到全局标签
	assert.Equal(t, 2, len(tags), "没有企业的企业用户只能看到全局标签")

	// 验证都是全局标签
	for _, tag := range tags {
		assert.Nil(t, tag.EnterpriseID, "应该是全局标签，enterprise_id 为 NULL")
		assert.Nil(t, tag.ShopID, "应该是全局标签，shop_id 为 NULL")
	}
}

// TestTagPermission_ResourceTag_Agent 测试代理用户查询资源标签表
// 预期：与 tb_tag 表相同的过滤规则
func TestTagPermission_ResourceTag_Agent(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 创建资源标签测试数据
	// 1. 全局资源标签
	db.Create(&ResourceTagModel{ID: 1, EnterpriseID: nil, ShopID: nil, ResourceType: "iot_card", ResourceID: 101, TagID: 1})
	// 2. 店铺 100 的资源标签
	db.Create(&ResourceTagModel{ID: 2, EnterpriseID: nil, ShopID: uintPtr(100), ResourceType: "iot_card", ResourceID: 102, TagID: 6})
	// 3. 店铺 200（下级）的资源标签
	db.Create(&ResourceTagModel{ID: 3, EnterpriseID: nil, ShopID: uintPtr(200), ResourceType: "device", ResourceID: 201, TagID: 8})
	// 4. 店铺 300（其他）的资源标签
	db.Create(&ResourceTagModel{ID: 4, EnterpriseID: nil, ShopID: uintPtr(300), ResourceType: "device", ResourceID: 301, TagID: 9})
	// 5. 企业的资源标签
	db.Create(&ResourceTagModel{ID: 5, EnterpriseID: uintPtr(1001), ShopID: nil, ResourceType: "iot_card", ResourceID: 103, TagID: 3})

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（店铺 ID = 100）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询资源标签
	var resourceTags []ResourceTagModel
	err = db.WithContext(ctx).Find(&resourceTags).Error
	assert.NoError(t, err)

	// 代理用户应该看到：
	// - 1 个全局资源标签（ID: 1）
	// - 1 个店铺 100 的资源标签（ID: 2）
	// - 1 个店铺 200（下级）的资源标签（ID: 3）
	// 总共 3 个
	assert.Equal(t, 3, len(resourceTags), "代理用户应该看到自己店铺、下级店铺和全局的资源标签")

	// 验证看不到的资源标签
	for _, rt := range resourceTags {
		assert.NotEqual(t, uint(4), rt.ID, "代理用户不应该看到其他店铺的资源标签")
		assert.NotEqual(t, uint(5), rt.ID, "代理用户不应该看到企业的资源标签")
	}
}

// TestTagPermission_CrossIsolation 测试跨租户隔离
// 验证企业 A 看不到企业 B 的标签
func TestTagPermission_CrossIsolation(t *testing.T) {
	db, mockStore := setupTagTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 企业 A 用户（enterprise_id = 1001）
	ctxA := context.Background()
	ctxA = middleware.SetUserContext(ctxA, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeEnterprise,
		ShopID:       0,
		EnterpriseID: 1001,
		CustomerID:   0,
	})

	// 企业 B 用户（enterprise_id = 1002）
	ctxB := context.Background()
	ctxB = middleware.SetUserContext(ctxB, &middleware.UserContextInfo{
		UserID:       2,
		UserType:     constants.UserTypeEnterprise,
		ShopID:       0,
		EnterpriseID: 1002,
		CustomerID:   0,
	})

	// 企业 A 查询标签
	var tagsA []TagModel
	err = db.WithContext(ctxA).Find(&tagsA).Error
	assert.NoError(t, err)

	// 企业 B 查询标签
	var tagsB []TagModel
	err = db.WithContext(ctxB).Find(&tagsB).Error
	assert.NoError(t, err)

	// 企业 A 应该看到 4 个标签（2 全局 + 2 企业 A）
	assert.Equal(t, 4, len(tagsA), "企业 A 应该看到 4 个标签")

	// 企业 B 应该看到 3 个标签（2 全局 + 1 企业 B）
	assert.Equal(t, 3, len(tagsB), "企业 B 应该看到 3 个标签")

	// 验证企业 A 看不到企业 B 的标签
	for _, tag := range tagsA {
		if tag.EnterpriseID != nil {
			assert.Equal(t, uint(1001), *tag.EnterpriseID, "企业 A 不应该看到企业 B 的标签")
		}
	}

	// 验证企业 B 看不到企业 A 的标签
	for _, tag := range tagsB {
		if tag.EnterpriseID != nil {
			assert.Equal(t, uint(1002), *tag.EnterpriseID, "企业 B 不应该看到企业 A 的标签")
		}
	}
}

// ============================================================
// 企业卡授权表数据权限过滤测试（tb_enterprise_card_authorization 表）
// ============================================================

// EnterpriseModel 模拟企业表，用于授权表过滤测试
type EnterpriseModel struct {
	ID          uint       `gorm:"primaryKey"`
	OwnerShopID *uint      `gorm:"column:owner_shop_id"`
	DeletedAt   *time.Time `gorm:"column:deleted_at"`
	Name        string
}

func (EnterpriseModel) TableName() string {
	return "tb_enterprise"
}

// AuthorizationModel 模拟企业卡授权表结构
type AuthorizationModel struct {
	ID             uint       `gorm:"primaryKey"`
	EnterpriseID   uint       `gorm:"column:enterprise_id"`
	CardID         uint       `gorm:"column:card_id"`
	AuthorizedBy   uint       `gorm:"column:authorized_by"`
	AuthorizedAt   time.Time  `gorm:"column:authorized_at"`
	AuthorizerType int        `gorm:"column:authorizer_type"`
	RevokedBy      *uint      `gorm:"column:revoked_by"`
	RevokedAt      *time.Time `gorm:"column:revoked_at"`
	Remark         string     `gorm:"column:remark"`
}

func (AuthorizationModel) TableName() string {
	return "tb_enterprise_card_authorization"
}

// setupAuthorizationTestDB 创建授权表测试数据库和数据
func setupAuthorizationTestDB(t *testing.T) (*gorm.DB, *mockShopStore) {
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	assert.NoError(t, err)

	// 创建测试表
	err = db.AutoMigrate(&EnterpriseModel{}, &AuthorizationModel{})
	assert.NoError(t, err)

	// 插入企业测试数据
	// 1. 店铺 100 下的企业
	db.Create(&EnterpriseModel{ID: 1, OwnerShopID: uintPtr(100), Name: "企业A-店铺100"})
	db.Create(&EnterpriseModel{ID: 2, OwnerShopID: uintPtr(100), Name: "企业B-店铺100"})
	// 2. 店铺 200（店铺100的下级）下的企业
	db.Create(&EnterpriseModel{ID: 3, OwnerShopID: uintPtr(200), Name: "企业C-店铺200"})
	// 3. 店铺 300（其他店铺）下的企业
	db.Create(&EnterpriseModel{ID: 4, OwnerShopID: uintPtr(300), Name: "企业D-店铺300"})
	// 4. 平台直属企业（无店铺归属）
	db.Create(&EnterpriseModel{ID: 5, OwnerShopID: nil, Name: "企业E-平台直属"})

	now := time.Now()
	// 插入授权记录测试数据
	// 1. 企业1的授权记录（店铺100）
	db.Create(&AuthorizationModel{ID: 1, EnterpriseID: 1, CardID: 101, AuthorizedBy: 1, AuthorizedAt: now, AuthorizerType: 3})
	db.Create(&AuthorizationModel{ID: 2, EnterpriseID: 1, CardID: 102, AuthorizedBy: 1, AuthorizedAt: now, AuthorizerType: 3})
	// 2. 企业2的授权记录（店铺100）
	db.Create(&AuthorizationModel{ID: 3, EnterpriseID: 2, CardID: 201, AuthorizedBy: 1, AuthorizedAt: now, AuthorizerType: 3})
	// 3. 企业3的授权记录（店铺200 - 下级店铺）
	db.Create(&AuthorizationModel{ID: 4, EnterpriseID: 3, CardID: 301, AuthorizedBy: 2, AuthorizedAt: now, AuthorizerType: 3})
	// 4. 企业4的授权记录（店铺300 - 其他店铺）
	db.Create(&AuthorizationModel{ID: 5, EnterpriseID: 4, CardID: 401, AuthorizedBy: 3, AuthorizedAt: now, AuthorizerType: 3})
	db.Create(&AuthorizationModel{ID: 6, EnterpriseID: 4, CardID: 402, AuthorizedBy: 3, AuthorizedAt: now, AuthorizerType: 3})
	// 5. 企业5的授权记录（平台直属）
	db.Create(&AuthorizationModel{ID: 7, EnterpriseID: 5, CardID: 501, AuthorizedBy: 1, AuthorizedAt: now, AuthorizerType: 2})

	// 创建 mock ShopStore
	// 店铺 100 的下级店铺包括 100 和 200（不含 300）
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{100, 200},
	}

	return db, mockStore
}

// TestAuthorizationPermission_SuperAdmin 测试超级管理员查询授权记录（应看到所有记录）
func TestAuthorizationPermission_SuperAdmin(t *testing.T) {
	db, mockStore := setupAuthorizationTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置超级管理员 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeSuperAdmin,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询授权记录
	var auths []AuthorizationModel
	err = db.WithContext(ctx).Find(&auths).Error
	assert.NoError(t, err)

	// 超级管理员应该看到所有 7 条记录
	assert.Equal(t, 7, len(auths), "超级管理员应该看到所有授权记录")
}

// TestAuthorizationPermission_Platform 测试平台用户查询授权记录（应看到所有记录）
func TestAuthorizationPermission_Platform(t *testing.T) {
	db, mockStore := setupAuthorizationTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置平台用户 context
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypePlatform,
		ShopID:       0,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询授权记录
	var auths []AuthorizationModel
	err = db.WithContext(ctx).Find(&auths).Error
	assert.NoError(t, err)

	// 平台用户应该看到所有 7 条记录
	assert.Equal(t, 7, len(auths), "平台用户应该看到所有授权记录")
}

// TestAuthorizationPermission_Agent_OwnShopOnly 测试代理用户查询授权记录
// 关键业务规则：代理只能看到自己店铺下企业的授权记录，不含下级店铺
func TestAuthorizationPermission_Agent_OwnShopOnly(t *testing.T) {
	db, mockStore := setupAuthorizationTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（店铺 ID = 100）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询授权记录
	var auths []AuthorizationModel
	err = db.WithContext(ctx).Find(&auths).Error
	assert.NoError(t, err)

	// 代理用户（店铺100）应该只看到：
	// - 企业1的2条授权记录（ID: 1, 2）
	// - 企业2的1条授权记录（ID: 3）
	// 总共 3 条记录
	// 注意：不含下级店铺200的记录（ID: 4），这是关键业务规则
	assert.Equal(t, 3, len(auths), "代理用户应该只看到自己店铺下企业的授权记录（不含下级店铺）")

	// 验证授权记录 ID
	expectedIDs := map[uint]bool{1: true, 2: true, 3: true}
	for _, auth := range auths {
		assert.True(t, expectedIDs[auth.ID], "授权记录 ID %d 不应该被代理用户看到", auth.ID)
	}

	// 验证看不到下级店铺的记录
	for _, auth := range auths {
		assert.NotEqual(t, uint(4), auth.ID, "代理用户不应该看到下级店铺的授权记录")
	}

	// 验证看不到其他店铺的记录
	for _, auth := range auths {
		assert.NotEqual(t, uint(5), auth.ID, "代理用户不应该看到其他店铺的授权记录")
		assert.NotEqual(t, uint(6), auth.ID, "代理用户不应该看到其他店铺的授权记录")
	}

	// 验证看不到平台直属企业的记录
	for _, auth := range auths {
		assert.NotEqual(t, uint(7), auth.ID, "代理用户不应该看到平台直属企业的授权记录")
	}
}

// TestAuthorizationPermission_Agent_SubordinateShop 测试下级店铺代理查询授权记录
// 验证下级店铺代理只能看到自己店铺下企业的授权记录
func TestAuthorizationPermission_Agent_SubordinateShop(t *testing.T) {
	db, _ := setupAuthorizationTestDB(t)

	// 创建 mock ShopStore，店铺 200 只能看到自己
	mockStore := &mockShopStore{
		subordinateShopIDs: []uint{200},
	}

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（店铺 ID = 200，是店铺100的下级）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       2,
		UserType:     constants.UserTypeAgent,
		ShopID:       200,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询授权记录
	var auths []AuthorizationModel
	err = db.WithContext(ctx).Find(&auths).Error
	assert.NoError(t, err)

	// 店铺200的代理用户应该只看到：
	// - 企业3的1条授权记录（ID: 4）
	// 总共 1 条记录
	assert.Equal(t, 1, len(auths), "下级店铺代理应该只看到自己店铺下企业的授权记录")

	// 验证授权记录 ID
	assert.Equal(t, uint(4), auths[0].ID, "应该是企业3的授权记录")
}

// TestAuthorizationPermission_Agent_NoShopID 测试没有 ShopID 的代理用户
// 预期：返回空结果
func TestAuthorizationPermission_Agent_NoShopID(t *testing.T) {
	db, mockStore := setupAuthorizationTestDB(t)

	// 注册 Callback
	err := RegisterDataPermissionCallback(db, mockStore)
	assert.NoError(t, err)

	// 设置代理用户 context（没有店铺 ID）
	ctx := context.Background()
	ctx = middleware.SetUserContext(ctx, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       0, // 没有店铺
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询授权记录
	var auths []AuthorizationModel
	err = db.WithContext(ctx).Find(&auths).Error
	assert.NoError(t, err)

	// 没有店铺的代理用户应该看不到任何记录
	assert.Equal(t, 0, len(auths), "没有店铺的代理用户应该看不到任何授权记录")
}

// TestAuthorizationPermission_Agent_CrossShopIsolation 测试跨店铺隔离
// 验证店铺 A 看不到店铺 B 的授权记录
func TestAuthorizationPermission_Agent_CrossShopIsolation(t *testing.T) {
	db, _ := setupAuthorizationTestDB(t)

	// 店铺 100 的 mock
	mockStore100 := &mockShopStore{
		subordinateShopIDs: []uint{100},
	}

	// 店铺 300 的 mock
	mockStore300 := &mockShopStore{
		subordinateShopIDs: []uint{300},
	}

	// 注册 Callback（使用店铺100的mock）
	err := RegisterDataPermissionCallback(db, mockStore100)
	assert.NoError(t, err)

	// 店铺 100 代理用户
	ctx100 := context.Background()
	ctx100 = middleware.SetUserContext(ctx100, &middleware.UserContextInfo{
		UserID:       1,
		UserType:     constants.UserTypeAgent,
		ShopID:       100,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询店铺100的授权记录
	var auths100 []AuthorizationModel
	err = db.WithContext(ctx100).Find(&auths100).Error
	assert.NoError(t, err)

	// 店铺100应该看到3条记录（企业1和企业2的）
	assert.Equal(t, 3, len(auths100), "店铺100应该看到自己店铺下企业的授权记录")

	// 重新创建数据库并注册店铺300的 Callback
	db2, _ := setupAuthorizationTestDB(t)
	err = RegisterDataPermissionCallback(db2, mockStore300)
	assert.NoError(t, err)

	// 店铺 300 代理用户
	ctx300 := context.Background()
	ctx300 = middleware.SetUserContext(ctx300, &middleware.UserContextInfo{
		UserID:       3,
		UserType:     constants.UserTypeAgent,
		ShopID:       300,
		EnterpriseID: 0,
		CustomerID:   0,
	})

	// 查询店铺300的授权记录
	var auths300 []AuthorizationModel
	err = db2.WithContext(ctx300).Find(&auths300).Error
	assert.NoError(t, err)

	// 店铺300应该看到2条记录（企业4的）
	assert.Equal(t, 2, len(auths300), "店铺300应该看到自己店铺下企业的授权记录")

	// 验证店铺100看不到店铺300的记录
	for _, auth := range auths100 {
		assert.NotEqual(t, uint(5), auth.ID, "店铺100不应该看到店铺300的授权记录")
		assert.NotEqual(t, uint(6), auth.ID, "店铺100不应该看到店铺300的授权记录")
	}

	// 验证店铺300看不到店铺100的记录
	for _, auth := range auths300 {
		assert.NotEqual(t, uint(1), auth.ID, "店铺300不应该看到店铺100的授权记录")
		assert.NotEqual(t, uint(2), auth.ID, "店铺300不应该看到店铺100的授权记录")
		assert.NotEqual(t, uint(3), auth.ID, "店铺300不应该看到店铺100的授权记录")
	}
}
