package integration

import (
	"fmt"
	"net/http/httptest"
	"testing"

	"github.com/gofiber/fiber/v2"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/tests/testutils/integ"
)

// TestAPIRegression_AllEndpointsAccessible 测试所有 API 端点在重构后仍可访问
func TestAPIRegression_AllEndpointsAccessible(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	// 定义所有需要测试的端点（检测端点是否存在，不检测业务逻辑）
	endpoints := []struct {
		method       string
		path         string
		name         string
		requiresAuth bool
	}{
		// Health endpoints（无需认证）
		{"GET", "/health", "Health check", false},

		// Account endpoints（需要认证）
		{"GET", "/api/admin/accounts", "List accounts", true},
		{"GET", "/api/admin/accounts/1", "Get account", true},

		// Role endpoints（需要认证）
		{"GET", "/api/admin/roles", "List roles", true},
		{"GET", "/api/admin/roles/1", "Get role", true},

		// Permission endpoints（需要认证）
		{"GET", "/api/admin/permissions", "List permissions", true},
		{"GET", "/api/admin/permissions/1", "Get permission", true},
		{"GET", "/api/admin/permissions/tree", "Get permission tree", true},
	}

	for _, ep := range endpoints {
		t.Run(ep.name, func(t *testing.T) {
			var resp *httptest.ResponseRecorder
			var err error

			if ep.requiresAuth {
				httpResp, httpErr := env.AsSuperAdmin().Request(ep.method, ep.path, nil)
				require.NoError(t, httpErr)
				resp = &httptest.ResponseRecorder{Code: httpResp.StatusCode}
				err = nil
			} else {
				req := httptest.NewRequest(ep.method, ep.path, nil)
				httpResp, httpErr := env.App.Test(req)
				require.NoError(t, httpErr)
				resp = &httptest.ResponseRecorder{Code: httpResp.StatusCode}
				err = httpErr
			}
			_ = err

			// 验证端点可访问（状态码不是 404 或 500）
			assert.NotEqual(t, fiber.StatusNotFound, resp.Code,
				"端点 %s %s 应该存在", ep.method, ep.path)
			assert.NotEqual(t, fiber.StatusInternalServerError, resp.Code,
				"端点 %s %s 不应该返回 500 错误", ep.method, ep.path)
		})
	}
}

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

	t.Run("账号模块路由正常", func(t *testing.T) {
		account := &model.Account{
			Username: "regression_test",
			Phone:    "13800000300",
			Password: "hashedpassword",
			UserType: constants.UserTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(account)

		resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d", account.ID), nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)

		resp, err = env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/accounts/%d/roles", account.ID), nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})

	t.Run("角色模块路由正常", func(t *testing.T) {
		role := &model.Role{
			RoleName: "回归测试角色",
			RoleType: constants.RoleTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(role)

		resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/roles/%d", role.ID), nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)

		resp, err = env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/roles/%d/permissions", role.ID), nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})

	t.Run("权限模块路由正常", func(t *testing.T) {
		perm := &model.Permission{
			PermName: "回归测试权限",
			PermCode: "regression:perm",
			PermType: constants.PermissionTypeMenu,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(perm)

		resp, err := env.AsSuperAdmin().Request("GET", fmt.Sprintf("/api/admin/permissions/%d", perm.ID), nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)

		resp, err = env.AsSuperAdmin().Request("GET", "/api/admin/permissions/tree", nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})
}

// TestAPIRegression_ErrorHandling 测试错误处理在重构后仍正常
func TestAPIRegression_ErrorHandling(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	t.Run("资源不存在返回正确错误码", func(t *testing.T) {
		// 账号不存在
		req := httptest.NewRequest("GET", "/api/admin/accounts/99999", nil)
		resp, err := env.App.Test(req)
		require.NoError(t, err)
		// 应该返回业务错误，不是 404
		assert.NotEqual(t, fiber.StatusNotFound, resp.StatusCode)

		// 角色不存在
		req = httptest.NewRequest("GET", "/api/admin/roles/99999", nil)
		resp, err = env.App.Test(req)
		require.NoError(t, err)
		assert.NotEqual(t, fiber.StatusNotFound, resp.StatusCode)

		// 权限不存在
		req = httptest.NewRequest("GET", "/api/admin/permissions/99999", nil)
		resp, err = env.App.Test(req)
		require.NoError(t, err)
		assert.NotEqual(t, fiber.StatusNotFound, resp.StatusCode)
	})

	t.Run("无效参数返回正确错误码", func(t *testing.T) {
		// 无效账号 ID
		req := httptest.NewRequest("GET", "/api/admin/accounts/invalid", nil)
		resp, err := env.App.Test(req)
		require.NoError(t, err)
		assert.NotEqual(t, fiber.StatusInternalServerError, resp.StatusCode)
	})
}

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

	for i := 1; i <= 25; i++ {
		account := &model.Account{
			Username: fmt.Sprintf("pagination_test_%d", i),
			Phone:    fmt.Sprintf("138000004%02d", i),
			Password: "hashedpassword",
			UserType: constants.UserTypePlatform,
			Status:   constants.StatusEnabled,
		}
		env.TX.Create(account)
	}

	t.Run("分页参数正常工作", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=1&page_size=10", nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)

		resp, err = env.AsSuperAdmin().Request("GET", "/api/admin/accounts?page=2&page_size=10", nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})

	t.Run("默认分页参数工作", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts", nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})
}

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

	t.Run("成功响应包含正确字段", func(t *testing.T) {
		resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/accounts", nil)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
		assert.Contains(t, resp.Header.Get("Content-Type"), "application/json")
	})

	t.Run("健康检查端点响应正常", func(t *testing.T) {
		req := httptest.NewRequest("GET", "/health", nil)
		resp, err := env.App.Test(req)
		require.NoError(t, err)
		assert.Equal(t, fiber.StatusOK, resp.StatusCode)
	})
}

// TestAPIRegression_ServicesIntegration 测试服务集成在重构后仍正常
func TestAPIRegression_ServicesIntegration(t *testing.T) {
	env := integ.NewIntegrationTestEnv(t)

	t.Run("Services 容器正确初始化", func(t *testing.T) {
		// 验证所有模块路由都已注册
		endpoints := []string{
			"/health",
			"/api/admin/accounts",
			"/api/admin/roles",
			"/api/admin/permissions",
		}

		for _, ep := range endpoints {
			req := httptest.NewRequest("GET", ep, nil)
			resp, err := env.App.Test(req)
			require.NoError(t, err)
			assert.NotEqual(t, fiber.StatusNotFound, resp.StatusCode,
				"端点 %s 应该已注册", ep)
		}
	})
}
