package postgres

import (
	"context"
	"testing"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/tests/testutils"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestPackageStore_Create(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "PKG_TEST_001",
		PackageName:    "测试套餐",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     1024,
		DataAmountMB:   1024,
		Price:          9900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}

	err := s.Create(ctx, pkg)
	require.NoError(t, err)
	assert.NotZero(t, pkg.ID)
}

func TestPackageStore_GetByID(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "PKG_TEST_002",
		PackageName:    "测试套餐2",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     2048,
		DataAmountMB:   2048,
		Price:          19900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	t.Run("查询存在的套餐", func(t *testing.T) {
		result, err := s.GetByID(ctx, pkg.ID)
		require.NoError(t, err)
		assert.Equal(t, pkg.PackageCode, result.PackageCode)
	})

	t.Run("查询不存在的套餐", func(t *testing.T) {
		_, err := s.GetByID(ctx, 99999)
		require.Error(t, err)
	})
}

func TestPackageStore_GetByCode(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "PKG_TEST_003",
		PackageName:    "测试套餐3",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     3072,
		DataAmountMB:   3072,
		Price:          29900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	t.Run("查询存在的编码", func(t *testing.T) {
		result, err := s.GetByCode(ctx, "PKG_TEST_003")
		require.NoError(t, err)
		assert.Equal(t, pkg.ID, result.ID)
	})

	t.Run("查询不存在的编码", func(t *testing.T) {
		_, err := s.GetByCode(ctx, "NOT_EXISTS")
		require.Error(t, err)
	})
}

func TestPackageStore_Update(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "PKG_TEST_004",
		PackageName:    "测试套餐4",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     4096,
		DataAmountMB:   4096,
		Price:          39900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	pkg.PackageName = "测试套餐4-更新"
	pkg.Price = 49900
	err := s.Update(ctx, pkg)
	require.NoError(t, err)

	updated, err := s.GetByID(ctx, pkg.ID)
	require.NoError(t, err)
	assert.Equal(t, "测试套餐4-更新", updated.PackageName)
	assert.Equal(t, int64(49900), updated.Price)
}

func TestPackageStore_Delete(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "PKG_DEL_001",
		PackageName:    "待删除套餐",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     1024,
		DataAmountMB:   1024,
		Price:          9900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	err := s.Delete(ctx, pkg.ID)
	require.NoError(t, err)

	_, err = s.GetByID(ctx, pkg.ID)
	require.Error(t, err)
}

func TestPackageStore_List(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkgList := []*model.Package{
		{
			PackageCode:    "LIST_P_001",
			PackageName:    "基础套餐",
			SeriesID:       1,
			PackageType:    "formal",
			DurationMonths: 1,
			DataType:       "real",
			RealDataMB:     1024,
			DataAmountMB:   1024,
			Price:          9900,
			Status:         constants.StatusEnabled,
			ShelfStatus:    1,
		},
		{
			PackageCode:    "LIST_P_002",
			PackageName:    "高级套餐",
			SeriesID:       2,
			PackageType:    "formal",
			DurationMonths: 12,
			DataType:       "real",
			RealDataMB:     10240,
			DataAmountMB:   10240,
			Price:          99900,
			Status:         constants.StatusEnabled,
			ShelfStatus:    1,
		},
		{
			PackageCode:    "LIST_P_003",
			PackageName:    "企业套餐",
			SeriesID:       3,
			PackageType:    "addon",
			DurationMonths: 1,
			DataType:       "virtual",
			VirtualDataMB:  5120,
			DataAmountMB:   5120,
			Price:          4900,
			Status:         constants.StatusEnabled,
			ShelfStatus:    2,
		},
	}
	for _, pkg := range pkgList {
		require.NoError(t, s.Create(ctx, pkg))
	}
	pkgList[2].Status = constants.StatusDisabled
	require.NoError(t, s.Update(ctx, pkgList[2]))

	t.Run("查询所有套餐", func(t *testing.T) {
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, nil)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(3))
		assert.GreaterOrEqual(t, len(result), 3)
	})

	t.Run("按名称模糊搜索", func(t *testing.T) {
		filters := map[string]interface{}{"package_name": "高级"}
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, filters)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(1))
		for _, pkg := range result {
			assert.Contains(t, pkg.PackageName, "高级")
		}
	})

	t.Run("按系列筛选", func(t *testing.T) {
		filters := map[string]interface{}{"series_id": uint(2)}
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, filters)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(1))
		for _, pkg := range result {
			assert.Equal(t, uint(2), pkg.SeriesID)
		}
	})

	t.Run("按状态过滤", func(t *testing.T) {
		filters := map[string]interface{}{"status": constants.StatusDisabled}
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, filters)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(1))
		for _, pkg := range result {
			assert.Equal(t, constants.StatusDisabled, pkg.Status)
		}
	})

	t.Run("按上架状态过滤", func(t *testing.T) {
		filters := map[string]interface{}{"shelf_status": 2}
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, filters)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(1))
		for _, pkg := range result {
			assert.Equal(t, 2, pkg.ShelfStatus)
		}
	})

	t.Run("按类型过滤", func(t *testing.T) {
		filters := map[string]interface{}{"package_type": "addon"}
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 20}, filters)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(1))
		for _, pkg := range result {
			assert.Equal(t, "addon", pkg.PackageType)
		}
	})

	t.Run("分页查询", func(t *testing.T) {
		result, total, err := s.List(ctx, &store.QueryOptions{Page: 1, PageSize: 2}, nil)
		require.NoError(t, err)
		assert.GreaterOrEqual(t, total, int64(3))
		assert.LessOrEqual(t, len(result), 2)
	})
}

func TestPackageStore_UpdateStatus(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "STATUS_TEST_001",
		PackageName:    "状态测试套餐",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     1024,
		DataAmountMB:   1024,
		Price:          9900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	err := s.UpdateStatus(ctx, pkg.ID, constants.StatusDisabled)
	require.NoError(t, err)

	updated, err := s.GetByID(ctx, pkg.ID)
	require.NoError(t, err)
	assert.Equal(t, constants.StatusDisabled, updated.Status)
}

func TestPackageStore_UpdateShelfStatus(t *testing.T) {
	tx := testutils.NewTestTransaction(t)
	s := NewPackageStore(tx)
	ctx := context.Background()

	pkg := &model.Package{
		PackageCode:    "SHELF_TEST_001",
		PackageName:    "上架测试套餐",
		SeriesID:       1,
		PackageType:    "formal",
		DurationMonths: 1,
		DataType:       "real",
		RealDataMB:     1024,
		DataAmountMB:   1024,
		Price:          9900,
		Status:         constants.StatusEnabled,
		ShelfStatus:    1,
	}
	require.NoError(t, s.Create(ctx, pkg))

	err := s.UpdateShelfStatus(ctx, pkg.ID, 2)
	require.NoError(t, err)

	updated, err := s.GetByID(ctx, pkg.ID)
	require.NoError(t, err)
	assert.Equal(t, 2, updated.ShelfStatus)
}
