package integration

import (
	"encoding/json"
	"fmt"
	"testing"
	"time"

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

func TestBatchAllocationAPI_Create(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	parentShop := env.CreateTestShop("父级店铺", 1, nil)
	childShop := env.CreateTestShop("子级店铺", 2, &parentShop.ID)
	series := createBatchTestPackageSeries(t, env, "批量分配测试系列")

	createBatchTestPackages(t, env, series.ID, 3)

	t.Run("批量分配套餐_固定金额返佣", func(t *testing.T) {
		body := map[string]interface{}{
			"shop_id":   childShop.ID,
			"series_id": series.ID,
			"base_commission": map[string]interface{}{
				"mode":  "fixed",
				"value": 1000,
			},
			"enable_tier_commission": false,
		}
		jsonBody, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shop-package-batch-allocations", jsonBody)
		require.NoError(t, err)
		defer resp.Body.Close()

		assert.Equal(t, 200, resp.StatusCode)

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.Equal(t, 0, result.Code, "应返回成功: %s", result.Message)
	})

	t.Run("批量分配套餐_百分比返佣", func(t *testing.T) {
		series2 := createBatchTestPackageSeries(t, env, "系列2")
		createBatchTestPackages(t, env, series2.ID, 2)
		shop2 := env.CreateTestShop("测试店铺2", 1, nil)

		body := map[string]interface{}{
			"shop_id":   shop2.ID,
			"series_id": series2.ID,
			"base_commission": map[string]interface{}{
				"mode":  "percent",
				"value": 200,
			},
			"enable_tier_commission": false,
		}
		jsonBody, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shop-package-batch-allocations", jsonBody)
		require.NoError(t, err)
		defer resp.Body.Close()

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.Equal(t, 0, result.Code)
	})

	t.Run("批量分配_带可选加价", func(t *testing.T) {
		series3 := createBatchTestPackageSeries(t, env, "系列3")
		createBatchTestPackages(t, env, series3.ID, 2)
		shop3 := env.CreateTestShop("测试店铺3", 1, nil)

		body := map[string]interface{}{
			"shop_id":   shop3.ID,
			"series_id": series3.ID,
			"price_adjustment": map[string]interface{}{
				"type":  "fixed",
				"value": 500,
			},
			"base_commission": map[string]interface{}{
				"mode":  "fixed",
				"value": 800,
			},
			"enable_tier_commission": false,
		}
		jsonBody, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shop-package-batch-allocations", jsonBody)
		require.NoError(t, err)
		defer resp.Body.Close()

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.Equal(t, 0, result.Code)
	})

	t.Run("批量分配_启用梯度返佣", func(t *testing.T) {
		series4 := createBatchTestPackageSeries(t, env, "系列4")
		createBatchTestPackages(t, env, series4.ID, 2)
		shop4 := env.CreateTestShop("测试店铺4", 1, nil)

		body := map[string]interface{}{
			"shop_id":   shop4.ID,
			"series_id": series4.ID,
			"base_commission": map[string]interface{}{
				"mode":  "percent",
				"value": 150,
			},
			"enable_tier_commission": true,
			"tier_config": map[string]interface{}{
				"period_type": "monthly",
				"tier_type":   "sales_count",
				"tiers": []map[string]interface{}{
					{"threshold": 100, "mode": "percent", "value": 200},
					{"threshold": 200, "mode": "percent", "value": 250},
					{"threshold": 500, "mode": "percent", "value": 300},
				},
			},
		}
		jsonBody, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shop-package-batch-allocations", jsonBody)
		require.NoError(t, err)
		defer resp.Body.Close()

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.Equal(t, 0, result.Code, "启用梯度返佣应成功: %s", result.Message)
	})

	t.Run("批量分配_系列无套餐应失败", func(t *testing.T) {
		emptySeries := createBatchTestPackageSeries(t, env, "空系列")
		shop5 := env.CreateTestShop("测试店铺5", 1, nil)

		body := map[string]interface{}{
			"shop_id":   shop5.ID,
			"series_id": emptySeries.ID,
			"base_commission": map[string]interface{}{
				"mode":  "fixed",
				"value": 1000,
			},
			"enable_tier_commission": false,
		}
		jsonBody, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shop-package-batch-allocations", jsonBody)
		require.NoError(t, err)
		defer resp.Body.Close()

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.NotEqual(t, 0, result.Code, "空系列应返回错误")
	})
}

func createBatchTestPackageSeries(t *testing.T, env *integ.IntegrationTestEnv, name string) *model.PackageSeries {
	t.Helper()

	timestamp := time.Now().UnixNano()
	series := &model.PackageSeries{
		SeriesCode: fmt.Sprintf("BATCH_SERIES_%d", timestamp),
		SeriesName: name,
		Status:     constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}

	err := env.TX.Create(series).Error
	require.NoError(t, err, "创建测试套餐系列失败")

	return series
}

func createBatchTestPackages(t *testing.T, env *integ.IntegrationTestEnv, seriesID uint, count int) []*model.Package {
	t.Helper()

	packages := make([]*model.Package, 0, count)
	timestamp := time.Now().UnixNano()

	for i := 0; i < count; i++ {
		pkg := &model.Package{
			PackageCode:        fmt.Sprintf("BATCH_PKG_%d_%d", timestamp, i),
			PackageName:        fmt.Sprintf("批量测试套餐%d", i+1),
			SeriesID:           seriesID,
			PackageType:        "formal",
			DurationMonths:     1,
			Price:              9900 + int64(i*1000),
			SuggestedCostPrice: 5000 + int64(i*500),
			Status:             constants.StatusEnabled,
			ShelfStatus:        1,
			BaseModel: model.BaseModel{
				Creator: 1,
				Updater: 1,
			},
		}

		err := env.TX.Create(pkg).Error
		require.NoError(t, err, "创建测试套餐失败")

		packages = append(packages, pkg)
	}

	return packages
}
