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

	ts := time.Now().Unix() % 100000
	shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)

	enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)

	card1 := &model.IotCard{
		ICCID:    fmt.Sprintf("AC1%d", ts),
		MSISDN:   "13800001001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	card2 := &model.IotCard{
		ICCID:    fmt.Sprintf("AC2%d", ts),
		MSISDN:   "13800001002",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	require.NoError(t, env.TX.Create(card1).Error)
	require.NoError(t, env.TX.Create(card2).Error)

	now := time.Now()
	auth1 := &model.EnterpriseCardAuthorization{
		EnterpriseID:   enterprise.ID,
		CardID:         card1.ID,
		AuthorizedBy:   1,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypePlatform,
		Remark:         "集成测试授权记录",
	}
	require.NoError(t, env.TX.Create(auth1).Error)

	t.Run("平台用户获取授权记录列表", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations?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)

		data, ok := result.Data.(map[string]interface{})
		require.True(t, ok)
		items, ok := data["items"].([]interface{})
		require.True(t, ok)
		assert.GreaterOrEqual(t, len(items), 1)
	})

	t.Run("按企业ID筛选授权记录", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&page=1&page_size=20", enterprise.ID)
		resp, err := env.AsSuperAdmin().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)

		data := result.Data.(map[string]interface{})
		total := int(data["total"].(float64))
		assert.Equal(t, 1, total)
	})

	t.Run("按ICCID筛选授权记录", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations?iccid=%s&page=1&page_size=20", card1.ICCID)
		resp, err := env.AsSuperAdmin().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)

		data := result.Data.(map[string]interface{})
		total := int(data["total"].(float64))
		assert.Equal(t, 1, total)
	})

	t.Run("按状态筛选-有效授权", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations?enterprise_id=%d&status=1&page=1&page_size=20", enterprise.ID)
		resp, err := env.AsSuperAdmin().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)
	})
}

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

	ts := time.Now().Unix() % 100000
	shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)

	enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)

	card1 := &model.IotCard{
		ICCID:    fmt.Sprintf("AC1%d", ts),
		MSISDN:   "13800001001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	require.NoError(t, env.TX.Create(card1).Error)

	now := time.Now()
	auth1 := &model.EnterpriseCardAuthorization{
		EnterpriseID:   enterprise.ID,
		CardID:         card1.ID,
		AuthorizedBy:   1,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypePlatform,
		Remark:         "集成测试授权记录",
	}
	require.NoError(t, env.TX.Create(auth1).Error)

	t.Run("获取授权记录详情", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d", auth1.ID)
		resp, err := env.AsSuperAdmin().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)

		data := result.Data.(map[string]interface{})
		assert.Equal(t, float64(auth1.ID), data["id"])
		assert.Equal(t, float64(enterprise.ID), data["enterprise_id"])
		assert.Equal(t, enterprise.EnterpriseName, data["enterprise_name"])
		assert.Equal(t, card1.ICCID, data["iccid"])
		assert.Equal(t, "集成测试授权记录", data["remark"])
		assert.Equal(t, float64(1), data["status"])
	})

	t.Run("获取不存在的授权记录", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations/999999", nil)
		require.NoError(t, err)
		defer resp.Body.Close()

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

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

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

	ts := time.Now().Unix() % 100000
	shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)

	enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)

	card1 := &model.IotCard{
		ICCID:    fmt.Sprintf("AC1%d", ts),
		MSISDN:   "13800001001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	require.NoError(t, env.TX.Create(card1).Error)

	now := time.Now()
	auth1 := &model.EnterpriseCardAuthorization{
		EnterpriseID:   enterprise.ID,
		CardID:         card1.ID,
		AuthorizedBy:   1,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypePlatform,
		Remark:         "集成测试授权记录",
	}
	require.NoError(t, env.TX.Create(auth1).Error)

	t.Run("更新授权记录备注", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d/remark", auth1.ID)
		body := map[string]string{"remark": "更新后的备注内容"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("PUT", url, bodyBytes)
		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)

		data := result.Data.(map[string]interface{})
		assert.Equal(t, "更新后的备注内容", data["remark"])
	})

	t.Run("更新不存在的授权记录备注", func(t *testing.T) {
		body := map[string]string{"remark": "不会更新"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("PUT", "/api/admin/authorizations/999999/remark", bodyBytes)
		require.NoError(t, err)
		defer resp.Body.Close()

		assert.Equal(t, 404, resp.StatusCode)
	})
}

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

	ts := time.Now().Unix() % 100000
	shop := env.CreateTestShop("AUTH_TEST_SHOP", 1, nil)

	enterprise := env.CreateTestEnterprise("AUTH_TEST_ENTERPRISE", &shop.ID)

	card1 := &model.IotCard{
		ICCID:    fmt.Sprintf("AC1%d", ts),
		MSISDN:   "13800001001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	require.NoError(t, env.TX.Create(card1).Error)

	now := time.Now()
	auth1 := &model.EnterpriseCardAuthorization{
		EnterpriseID:   enterprise.ID,
		CardID:         card1.ID,
		AuthorizedBy:   1,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypePlatform,
		Remark:         "集成测试授权记录",
	}
	require.NoError(t, env.TX.Create(auth1).Error)

	agentAccount := env.CreateTestAccount("agent", "password123", constants.UserTypeAgent, &shop.ID, nil)

	ts2 := time.Now().Unix() % 100000
	otherShop := env.CreateTestShop("OTHER_TEST_SHOP", 1, nil)

	otherEnterprise := env.CreateTestEnterprise("OTHER_TEST_ENTERPRISE", &otherShop.ID)

	otherCard := &model.IotCard{
		ICCID:    fmt.Sprintf("OC%d", ts2),
		MSISDN:   "13800002001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &otherShop.ID,
	}
	require.NoError(t, env.TX.Create(otherCard).Error)

	otherAuth := &model.EnterpriseCardAuthorization{
		EnterpriseID:   otherEnterprise.ID,
		CardID:         otherCard.ID,
		AuthorizedBy:   1,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypePlatform,
		Remark:         "其他店铺的授权记录",
	}
	require.NoError(t, env.TX.Create(otherAuth).Error)

	t.Run("代理用户只能看到自己店铺的授权记录", func(t *testing.T) {
		resp, err := env.AsUser(agentAccount).Request("GET", "/api/admin/authorizations?page=1&page_size=100", 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)

		data := result.Data.(map[string]interface{})
		items := data["items"].([]interface{})

		sawOtherAuth := false
		sawOwnAuth := false
		for _, item := range items {
			itemMap := item.(map[string]interface{})
			authID := uint(itemMap["id"].(float64))
			if authID == otherAuth.ID {
				sawOtherAuth = true
			}
			if authID == auth1.ID {
				sawOwnAuth = true
			}
		}
		assert.False(t, sawOtherAuth, "代理用户不应该看到其他店铺的授权记录 (otherAuth.ID=%d)", otherAuth.ID)
		assert.True(t, sawOwnAuth, "代理用户应该能看到自己店铺的授权记录 (auth1.ID=%d)", auth1.ID)
	})

	t.Run("平台用户可以看到所有授权记录", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/authorizations?page=1&page_size=100", 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)

		data := result.Data.(map[string]interface{})
		total := int(data["total"].(float64))
		assert.GreaterOrEqual(t, total, 2, "平台用户应该能看到所有授权记录")
	})
}

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

	t.Run("无Token访问被拒绝", func(t *testing.T) {
		resp, err := env.ClearAuth().Request("GET", "/api/admin/authorizations", nil)
		require.NoError(t, err)
		defer resp.Body.Close()

		assert.Equal(t, 401, resp.StatusCode)
	})

	t.Run("无效Token访问被拒绝", func(t *testing.T) {
		resp, err := env.RequestWithHeaders("GET", "/api/admin/authorizations", nil, map[string]string{
			"Authorization": "Bearer invalid_token",
		})
		require.NoError(t, err)
		defer resp.Body.Close()

		assert.Equal(t, 401, resp.StatusCode)
	})
}

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

	ts := time.Now().Unix() % 100000
	shop := env.CreateTestShop("AUTH_PERM_SHOP", 1, nil)
	enterprise := env.CreateTestEnterprise("AUTH_PERM_ENTERPRISE", &shop.ID)

	card := &model.IotCard{
		ICCID:    fmt.Sprintf("PERM%d", ts),
		MSISDN:   "13800003001",
		CardType: "data_card",
		Status:   1,
		ShopID:   &shop.ID,
	}
	require.NoError(t, env.TX.Create(card).Error)

	agentAccount1 := env.CreateTestAccount("agent1", "password123", constants.UserTypeAgent, &shop.ID, nil)
	agentAccount2 := env.CreateTestAccount("agent2", "password456", constants.UserTypeAgent, &shop.ID, nil)
	enterpriseAccount := env.CreateTestAccount("enterprise1", "password789", constants.UserTypeEnterprise, nil, &enterprise.ID)

	now := time.Now()
	authByAgent1 := &model.EnterpriseCardAuthorization{
		EnterpriseID:   enterprise.ID,
		CardID:         card.ID,
		AuthorizedBy:   agentAccount1.ID,
		AuthorizedAt:   now,
		AuthorizerType: constants.UserTypeAgent,
		Remark:         "代理1创建的授权记录",
	}
	require.NoError(t, env.TX.Create(authByAgent1).Error)

	t.Run("平台用户可修改任意授权记录备注", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d/remark", authByAgent1.ID)
		body := map[string]string{"remark": "平台修改的备注"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsSuperAdmin().Request("PUT", url, bodyBytes)
		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)

		data := result.Data.(map[string]interface{})
		assert.Equal(t, "平台修改的备注", data["remark"])
	})

	t.Run("代理用户可修改本人创建的授权记录备注", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d/remark", authByAgent1.ID)
		body := map[string]string{"remark": "代理1自己修改的备注"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsUser(agentAccount1).Request("PUT", url, bodyBytes)
		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)

		data := result.Data.(map[string]interface{})
		assert.Equal(t, "代理1自己修改的备注", data["remark"])
	})

	t.Run("代理用户不可修改他人创建的授权记录备注", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d/remark", authByAgent1.ID)
		body := map[string]string{"remark": "代理2试图修改的备注"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsUser(agentAccount2).Request("PUT", url, bodyBytes)
		require.NoError(t, err)
		defer resp.Body.Close()

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

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.NotEqual(t, 0, result.Code)
		assert.Contains(t, result.Message, "只能修改自己创建的授权记录备注")
	})

	t.Run("企业用户不允许修改授权记录备注", func(t *testing.T) {
		url := fmt.Sprintf("/api/admin/authorizations/%d/remark", authByAgent1.ID)
		body := map[string]string{"remark": "企业试图修改的备注"}
		bodyBytes, _ := json.Marshal(body)

		resp, err := env.AsUser(enterpriseAccount).Request("PUT", url, bodyBytes)
		require.NoError(t, err)
		defer resp.Body.Close()

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

		var result response.Response
		err = json.NewDecoder(resp.Body).Decode(&result)
		require.NoError(t, err)
		assert.NotEqual(t, 0, result.Code)
		assert.Contains(t, result.Message, "权限不足")
	})
}
