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 TestMyPackageAPI_ListMyPackages(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	parentShop := env.CreateTestShop("一级店铺", 1, nil)
	childShop := env.CreateTestShop("二级店铺", 2, &parentShop.ID)
	agentAccount := env.CreateTestAccount("agent_my_pkg", "password123", constants.UserTypeAgent, &childShop.ID, nil)

	series := createTestPackageSeriesForMyPkg(t, env, "测试系列")
	pkg := createTestPackageForMyPkg(t, env, series.ID, "测试套餐")

	createTestAllocationForMyPkg(t, env, parentShop.ID, series.ID, 0)
	createTestAllocationForMyPkg(t, env, childShop.ID, series.ID, parentShop.ID)

	t.Run("代理查看可售套餐列表", func(t *testing.T) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/my-packages?page=1&page_size=20", nil)
		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.Logf("ListMyPackages response: %+v", result.Data)
	})

	t.Run("按系列ID筛选", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/my-packages?series_id=%d", series.ID)
		resp, err := env.AsUser(agentAccount).Request("GET", url, nil)
		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) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/my-packages?package_type=formal", nil)
		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)
	})

	_ = pkg
}

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

	parentShop := env.CreateTestShop("一级店铺", 1, nil)
	childShop := env.CreateTestShop("二级店铺", 2, &parentShop.ID)
	agentAccount := env.CreateTestAccount("agent_get_pkg", "password123", constants.UserTypeAgent, &childShop.ID, nil)

	series := createTestPackageSeriesForMyPkg(t, env, "测试系列")
	pkg := createTestPackageForMyPkg(t, env, series.ID, "测试套餐")

	createTestAllocationForMyPkg(t, env, parentShop.ID, series.ID, 0)
	createTestAllocationForMyPkg(t, env, childShop.ID, series.ID, parentShop.ID)

	t.Run("获取可售套餐详情", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/my-packages/%d", pkg.ID)
		resp, err := env.AsUser(agentAccount).Request("GET", url, nil)
		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)

		if result.Data != nil {
			dataMap := result.Data.(map[string]interface{})
			assert.Equal(t, float64(pkg.ID), dataMap["id"])
			t.Logf("套餐详情: %+v", dataMap)
		}
	})

	t.Run("获取不存在的套餐", func(t *testing.T) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/my-packages/999999", nil)
		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 TestMyPackageAPI_ListMySeriesAllocations(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	parentShop := env.CreateTestShop("一级店铺", 1, nil)
	childShop := env.CreateTestShop("二级店铺", 2, &parentShop.ID)
	agentAccount := env.CreateTestAccount("agent_series_alloc", "password123", constants.UserTypeAgent, &childShop.ID, nil)

	series1 := createTestPackageSeriesForMyPkg(t, env, "系列1")
	series2 := createTestPackageSeriesForMyPkg(t, env, "系列2")

	createTestAllocationForMyPkg(t, env, parentShop.ID, series1.ID, 0)
	createTestAllocationForMyPkg(t, env, childShop.ID, series1.ID, parentShop.ID)
	createTestAllocationForMyPkg(t, env, parentShop.ID, series2.ID, 0)
	createTestAllocationForMyPkg(t, env, childShop.ID, series2.ID, parentShop.ID)

	t.Run("获取被分配的系列列表", func(t *testing.T) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/my-series-allocations?page=1&page_size=20", nil)
		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.Logf("ListMySeriesAllocations response: %+v", result.Data)
	})

	t.Run("分页参数生效", func(t *testing.T) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/my-series-allocations?page=1&page_size=1", nil)
		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)
	})
}

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

	t.Run("未认证请求应返回错误", func(t *testing.T) {
		resp, err := env.ClearAuth().Request("GET", "/api/admin/my-packages", nil)
		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, "未认证请求应返回错误码")
	})

	t.Run("未认证访问系列分配列表", func(t *testing.T) {
		resp, err := env.ClearAuth().Request("GET", "/api/admin/my-series-allocations", nil)
		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 createTestPackageSeriesForMyPkg(t *testing.T, env *integ.IntegrationTestEnv, name string) *model.PackageSeries {
	t.Helper()

	timestamp := time.Now().UnixNano()
	series := &model.PackageSeries{
		SeriesCode: fmt.Sprintf("SERIES_MY_%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 createTestPackageForMyPkg(t *testing.T, env *integ.IntegrationTestEnv, seriesID uint, name string) *model.Package {
	t.Helper()

	timestamp := time.Now().UnixNano()
	pkg := &model.Package{
		PackageCode:          fmt.Sprintf("PKG_%d", timestamp),
		PackageName:          name,
		SeriesID:             seriesID,
		PackageType:          "formal",
		DurationMonths:       1,
		DataType:             "real",
		RealDataMB:           1024,
		DataAmountMB:         1024,
		Price:                9900,
		SuggestedRetailPrice: 12800,
		Status:               constants.StatusEnabled,
		ShelfStatus:          1,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}

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

	return pkg
}

func createTestAllocationForMyPkg(t *testing.T, env *integ.IntegrationTestEnv, shopID, seriesID, allocatorShopID uint) *model.ShopSeriesAllocation {
	t.Helper()

	allocation := &model.ShopSeriesAllocation{
		ShopID:              shopID,
		SeriesID:            seriesID,
		AllocatorShopID:     allocatorShopID,
		BaseCommissionMode:  "fixed",
		BaseCommissionValue: 500,
		Status:              constants.StatusEnabled,
		BaseModel: model.BaseModel{
			Creator: 1,
			Updater: 1,
		},
	}

	err := env.TX.Create(allocation).Error
	require.NoError(t, err, "创建测试分配失败")

	return allocation
}
