package unit

import (
	"context"
	"testing"

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

	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/service/commission_withdrawal_setting"
	"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 createWithdrawalSettingTestContext(userID uint) context.Context {
	ctx := context.Background()
	ctx = context.WithValue(ctx, constants.ContextKeyUserID, userID)
	ctx = context.WithValue(ctx, constants.ContextKeyUserType, constants.UserTypePlatform)
	return ctx
}

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

	accountStore := postgres.NewAccountStore(tx, rdb)
	settingStore := postgres.NewCommissionWithdrawalSettingStore(tx, rdb)

	service := commission_withdrawal_setting.New(tx, accountStore, settingStore)

	t.Run("新增提现配置", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		req := &dto.CreateWithdrawalSettingReq{
			DailyWithdrawalLimit: 5,
			MinWithdrawalAmount:  10000,
			FeeRate:              100,
		}

		result, err := service.Create(ctx, req)
		require.NoError(t, err)
		assert.NotNil(t, result)
		assert.Equal(t, 5, result.DailyWithdrawalLimit)
		assert.Equal(t, int64(10000), result.MinWithdrawalAmount)
		assert.Equal(t, int64(100), result.FeeRate)
		assert.True(t, result.IsActive)
	})

	t.Run("未授权用户创建配置应失败", func(t *testing.T) {
		ctx := context.Background()

		req := &dto.CreateWithdrawalSettingReq{
			DailyWithdrawalLimit: 5,
			MinWithdrawalAmount:  10000,
			FeeRate:              100,
		}

		_, err := service.Create(ctx, req)
		assert.Error(t, err)
	})
}

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

	accountStore := postgres.NewAccountStore(tx, rdb)
	settingStore := postgres.NewCommissionWithdrawalSettingStore(tx, rdb)

	service := commission_withdrawal_setting.New(tx, accountStore, settingStore)

	t.Run("配置切换-旧配置自动失效", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		req1 := &dto.CreateWithdrawalSettingReq{
			DailyWithdrawalLimit: 3,
			MinWithdrawalAmount:  5000,
			FeeRate:              50,
		}
		result1, err := service.Create(ctx, req1)
		require.NoError(t, err)
		assert.True(t, result1.IsActive)

		req2 := &dto.CreateWithdrawalSettingReq{
			DailyWithdrawalLimit: 10,
			MinWithdrawalAmount:  20000,
			FeeRate:              200,
		}
		result2, err := service.Create(ctx, req2)
		require.NoError(t, err)
		assert.True(t, result2.IsActive)

		current, err := service.GetCurrent(ctx)
		require.NoError(t, err)
		assert.Equal(t, result2.ID, current.ID)
		assert.Equal(t, 10, current.DailyWithdrawalLimit)
		assert.Equal(t, int64(20000), current.MinWithdrawalAmount)
		assert.Equal(t, int64(200), current.FeeRate)
		assert.True(t, current.IsActive)
	})
}

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

	accountStore := postgres.NewAccountStore(tx, rdb)
	settingStore := postgres.NewCommissionWithdrawalSettingStore(tx, rdb)

	service := commission_withdrawal_setting.New(tx, accountStore, settingStore)

	t.Run("查询配置列表-空结果", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		req := &dto.WithdrawalSettingListReq{
			Page:     1,
			PageSize: 20,
		}

		result, err := service.List(ctx, req)
		require.NoError(t, err)
		assert.NotNil(t, result)
		assert.GreaterOrEqual(t, result.Total, int64(0))
	})

	t.Run("查询配置列表-有数据", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		for i := 0; i < 3; i++ {
			req := &dto.CreateWithdrawalSettingReq{
				DailyWithdrawalLimit: i + 1,
				MinWithdrawalAmount:  int64((i + 1) * 1000),
				FeeRate:              int64((i + 1) * 10),
			}
			_, err := service.Create(ctx, req)
			require.NoError(t, err)
		}

		listReq := &dto.WithdrawalSettingListReq{
			Page:     1,
			PageSize: 20,
		}

		result, err := service.List(ctx, listReq)
		require.NoError(t, err)
		assert.NotNil(t, result)
		assert.GreaterOrEqual(t, result.Total, int64(3))
		assert.NotEmpty(t, result.Items)
	})
}

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

	// 清理已有的活跃配置，确保测试隔离
	tx.Exec("UPDATE tb_commission_withdrawal_setting SET is_active = false WHERE is_active = true")

	accountStore := postgres.NewAccountStore(tx, rdb)
	settingStore := postgres.NewCommissionWithdrawalSettingStore(tx, rdb)

	service := commission_withdrawal_setting.New(tx, accountStore, settingStore)

	t.Run("获取当前配置-无配置时应返回错误", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		_, err := service.GetCurrent(ctx)
		assert.Error(t, err)
	})

	t.Run("获取当前配置-有配置时正常返回", func(t *testing.T) {
		ctx := createWithdrawalSettingTestContext(1)

		req := &dto.CreateWithdrawalSettingReq{
			DailyWithdrawalLimit: 5,
			MinWithdrawalAmount:  10000,
			FeeRate:              100,
		}
		_, err := service.Create(ctx, req)
		require.NoError(t, err)

		current, err := service.GetCurrent(ctx)
		require.NoError(t, err)
		assert.NotNil(t, current)
		assert.Equal(t, 5, current.DailyWithdrawalLimit)
		assert.Equal(t, int64(10000), current.MinWithdrawalAmount)
		assert.Equal(t, int64(100), current.FeeRate)
		assert.True(t, current.IsActive)
	})
}
