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"
)

// TestEnterpriseStore_Create 测试创建企业
func TestEnterpriseStore_Create(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	tests := []struct {
		name       string
		enterprise *model.Enterprise
		wantErr    bool
	}{
		{
			name: "创建平台直属企业",
			enterprise: &model.Enterprise{
				EnterpriseName:  "测试企业A",
				EnterpriseCode:  "ENT001",
				OwnerShopID:     nil, // 平台直属
				LegalPerson:     "张三",
				ContactName:     "李四",
				ContactPhone:    "13800000001",
				BusinessLicense: "91110000MA001234",
				Province:        "北京市",
				City:            "北京市",
				District:        "朝阳区",
				Address:         "朝阳路100号",
				Status:          constants.StatusEnabled,
			},
			wantErr: false,
		},
		{
			name: "创建归属店铺的企业",
			enterprise: &model.Enterprise{
				EnterpriseName:  "测试企业B",
				EnterpriseCode:  "ENT002",
				LegalPerson:     "王五",
				ContactName:     "赵六",
				ContactPhone:    "13800000002",
				BusinessLicense: "91110000MA005678",
				Status:          constants.StatusEnabled,
			},
			wantErr: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tt.enterprise.BaseModel.Creator = 1
			tt.enterprise.BaseModel.Updater = 1

			err := store.Create(ctx, tt.enterprise)
			if tt.wantErr {
				assert.Error(t, err)
			} else {
				require.NoError(t, err)
				assert.NotZero(t, tt.enterprise.ID)
				assert.NotZero(t, tt.enterprise.CreatedAt)
				assert.NotZero(t, tt.enterprise.UpdatedAt)
			}
		})
	}
}

// TestEnterpriseStore_GetByID 测试根据 ID 查询企业
func TestEnterpriseStore_GetByID(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建测试企业
	enterprise := &model.Enterprise{
		EnterpriseName:  "测试企业",
		EnterpriseCode:  "TEST001",
		LegalPerson:     "测试法人",
		ContactName:     "测试联系人",
		ContactPhone:    "13800000001",
		BusinessLicense: "91110000MA001234",
		Status:          constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := store.Create(ctx, enterprise)
	require.NoError(t, err)

	t.Run("查询存在的企业", func(t *testing.T) {
		found, err := store.GetByID(ctx, enterprise.ID)
		require.NoError(t, err)
		assert.Equal(t, enterprise.EnterpriseName, found.EnterpriseName)
		assert.Equal(t, enterprise.EnterpriseCode, found.EnterpriseCode)
		assert.Equal(t, enterprise.LegalPerson, found.LegalPerson)
	})

	t.Run("查询不存在的企业", func(t *testing.T) {
		_, err := store.GetByID(ctx, 99999)
		assert.Error(t, err)
	})
}

// TestEnterpriseStore_GetByCode 测试根据企业编号查询
func TestEnterpriseStore_GetByCode(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建测试企业
	enterprise := &model.Enterprise{
		EnterpriseName:  "测试企业",
		EnterpriseCode:  "UNIQUE001",
		LegalPerson:     "测试法人",
		ContactName:     "测试联系人",
		ContactPhone:    "13800000001",
		BusinessLicense: "91110000MA001234",
		Status:          constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := store.Create(ctx, enterprise)
	require.NoError(t, err)

	t.Run("根据企业编号查询", func(t *testing.T) {
		found, err := store.GetByCode(ctx, "UNIQUE001")
		require.NoError(t, err)
		assert.Equal(t, enterprise.ID, found.ID)
		assert.Equal(t, enterprise.EnterpriseName, found.EnterpriseName)
	})

	t.Run("查询不存在的企业编号", func(t *testing.T) {
		_, err := store.GetByCode(ctx, "NONEXISTENT")
		assert.Error(t, err)
	})
}

// TestEnterpriseStore_Update 测试更新企业
func TestEnterpriseStore_Update(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建测试企业
	enterprise := &model.Enterprise{
		EnterpriseName:  "原始企业名称",
		EnterpriseCode:  "UPDATE001",
		LegalPerson:     "原法人",
		ContactName:     "原联系人",
		ContactPhone:    "13800000001",
		BusinessLicense: "91110000MA001234",
		Status:          constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := store.Create(ctx, enterprise)
	require.NoError(t, err)

	t.Run("更新企业信息", func(t *testing.T) {
		enterprise.EnterpriseName = "更新后的企业名称"
		enterprise.LegalPerson = "新法人"
		enterprise.ContactName = "新联系人"
		enterprise.ContactPhone = "13900000001"
		enterprise.Updater = 2

		err := store.Update(ctx, enterprise)
		require.NoError(t, err)

		// 验证更新
		found, err := store.GetByID(ctx, enterprise.ID)
		require.NoError(t, err)
		assert.Equal(t, "更新后的企业名称", found.EnterpriseName)
		assert.Equal(t, "新法人", found.LegalPerson)
		assert.Equal(t, "新联系人", found.ContactName)
		assert.Equal(t, "13900000001", found.ContactPhone)
		assert.Equal(t, uint(2), found.Updater)
	})

	t.Run("更新企业状态", func(t *testing.T) {
		enterprise.Status = constants.StatusDisabled
		err := store.Update(ctx, enterprise)
		require.NoError(t, err)

		found, err := store.GetByID(ctx, enterprise.ID)
		require.NoError(t, err)
		assert.Equal(t, constants.StatusDisabled, found.Status)
	})
}

// TestEnterpriseStore_Delete 测试软删除企业
func TestEnterpriseStore_Delete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建测试企业
	enterprise := &model.Enterprise{
		EnterpriseName:  "待删除企业",
		EnterpriseCode:  "DELETE001",
		LegalPerson:     "测试",
		ContactName:     "测试",
		ContactPhone:    "13800000001",
		BusinessLicense: "91110000MA001234",
		Status:          constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := store.Create(ctx, enterprise)
	require.NoError(t, err)

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

		// 验证已被软删除
		_, err = store.GetByID(ctx, enterprise.ID)
		assert.Error(t, err)
	})
}

// TestEnterpriseStore_List 测试查询企业列表
func TestEnterpriseStore_List(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建多个测试企业
	for i := 1; i <= 5; i++ {
		enterprise := &model.Enterprise{
			EnterpriseName:  testutils.GenerateUsername("测试企业", i),
			EnterpriseCode:  testutils.GenerateUsername("ENT", i),
			LegalPerson:     "测试法人",
			ContactName:     "测试联系人",
			ContactPhone:    testutils.GeneratePhone("138", i),
			BusinessLicense: testutils.GenerateUsername("LICENSE", i),
			Status:          constants.StatusEnabled,
			BaseModel: model.BaseModel{
				Creator: 1,
				Updater: 1,
			},
		}
		err := store.Create(ctx, enterprise)
		require.NoError(t, err)
	}

	t.Run("分页查询", func(t *testing.T) {
		enterprises, total, err := store.List(ctx, nil, nil)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, len(enterprises), 5)
		assert.GreaterOrEqual(t, total, int64(5))
	})

	t.Run("带过滤条件查询", func(t *testing.T) {
		filters := map[string]interface{}{
			"status": constants.StatusEnabled,
		}
		enterprises, _, err := store.List(ctx, nil, filters)
		require.NoError(t, err)
		for _, ent := range enterprises {
			assert.Equal(t, constants.StatusEnabled, ent.Status)
		}
	})
}

// TestEnterpriseStore_GetByOwnerShopID 测试根据归属店铺查询企业
func TestEnterpriseStore_GetByOwnerShopID(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	shopID1 := uint(100)
	shopID2 := uint(200)

	// 创建归属不同店铺的企业
	for i := 1; i <= 3; i++ {
		enterprise := &model.Enterprise{
			EnterpriseName:  testutils.GenerateUsername("店铺100企业", i),
			EnterpriseCode:  testutils.GenerateUsername("SHOP100_ENT", i),
			OwnerShopID:     &shopID1,
			LegalPerson:     "测试法人",
			ContactName:     "测试联系人",
			ContactPhone:    testutils.GeneratePhone("138", i),
			BusinessLicense: testutils.GenerateUsername("LICENSE", i),
			Status:          constants.StatusEnabled,
			BaseModel: model.BaseModel{
				Creator: 1,
				Updater: 1,
			},
		}
		err := store.Create(ctx, enterprise)
		require.NoError(t, err)
	}

	for i := 1; i <= 2; i++ {
		enterprise := &model.Enterprise{
			EnterpriseName:  testutils.GenerateUsername("店铺200企业", i),
			EnterpriseCode:  testutils.GenerateUsername("SHOP200_ENT", i),
			OwnerShopID:     &shopID2,
			LegalPerson:     "测试法人",
			ContactName:     "测试联系人",
			ContactPhone:    testutils.GeneratePhone("139", i),
			BusinessLicense: testutils.GenerateUsername("LICENSE2", i),
			Status:          constants.StatusEnabled,
			BaseModel: model.BaseModel{
				Creator: 1,
				Updater: 1,
			},
		}
		err := store.Create(ctx, enterprise)
		require.NoError(t, err)
	}

	t.Run("查询店铺100的企业", func(t *testing.T) {
		enterprises, err := store.GetByOwnerShopID(ctx, shopID1)
		require.NoError(t, err)
		assert.Len(t, enterprises, 3)
		for _, ent := range enterprises {
			assert.NotNil(t, ent.OwnerShopID)
			assert.Equal(t, shopID1, *ent.OwnerShopID)
		}
	})

	t.Run("查询店铺200的企业", func(t *testing.T) {
		enterprises, err := store.GetByOwnerShopID(ctx, shopID2)
		require.NoError(t, err)
		assert.Len(t, enterprises, 2)
		for _, ent := range enterprises {
			assert.NotNil(t, ent.OwnerShopID)
			assert.Equal(t, shopID2, *ent.OwnerShopID)
		}
	})
}

// TestEnterpriseStore_UniqueConstraints 测试唯一约束
func TestEnterpriseStore_UniqueConstraints(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	rdb := testutils.GetTestRedis(t)
	testutils.CleanTestRedisKeys(t, rdb)

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

	// 创建测试企业
	enterprise := &model.Enterprise{
		EnterpriseName:  "唯一测试企业",
		EnterpriseCode:  "UNIQUE_CODE",
		LegalPerson:     "测试",
		ContactName:     "测试",
		ContactPhone:    "13800000001",
		BusinessLicense: "91110000MA001234",
		Status:          constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}
	err := store.Create(ctx, enterprise)
	require.NoError(t, err)

	t.Run("重复企业编号应失败", func(t *testing.T) {
		duplicate := &model.Enterprise{
			EnterpriseName:  "另一个企业",
			EnterpriseCode:  "UNIQUE_CODE", // 重复
			LegalPerson:     "测试",
			ContactName:     "测试",
			ContactPhone:    "13800000002",
			BusinessLicense: "91110000MA005678",
			Status:          constants.StatusEnabled,
			BaseModel: model.BaseModel{
				Creator: 1,
				Updater: 1,
			},
		}
		err := store.Create(ctx, duplicate)
		assert.Error(t, err)
	})
}
