# =============================================================================
# 企微IT智能服务台 — API 基础验证测试
# =============================================================================
# 测试覆盖：
#   1. 健康检查端点
#   2. 统一响应格式（code/data/message）
#   3. CORS 配置
#   4. 404 路由
#   5. AppException 全局异常处理
#   6. success_response / error_response 工具函数
# =============================================================================

import pytest
import pytest_asyncio

from app.utils.response import success_response, error_response, AppException


class TestHealthCheck:
    """测试健康检查端点。"""

    @pytest.mark.asyncio
    async def test_health_check(self, client, db_session):
        """验证 /health 端点返回正常状态。"""
        response = await client.get("/health")

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "ok"
        assert "service" in data


class TestUnifiedResponseFormat:
    """测试统一响应格式。"""

    def test_success_response_format(self):
        """验证成功响应格式：{code: 0, data: {}, message: "success"}。"""
        result = success_response(data={"key": "value"})

        assert result["code"] == 0
        assert result["data"] == {"key": "value"}
        assert result["message"] == "success"

    def test_success_response_default_data(self):
        """验证成功响应默认 data 为 None。"""
        result = success_response()

        assert result["code"] == 0
        assert result["data"] is None

    def test_success_response_custom_message(self):
        """验证成功响应自定义消息。"""
        result = success_response(message="操作成功")

        assert result["message"] == "操作成功"

    def test_error_response_format(self):
        """验证错误响应格式：{code: N, data: null, message: "错误信息"}。"""
        result = error_response(1001, "参数错误")

        assert result["code"] == 1001
        assert result["data"] is None
        assert result["message"] == "参数错误"

    def test_error_response_with_data(self):
        """验证错误响应可附带额外数据。"""
        result = error_response(1001, "校验失败", data={"field": "email"})

        assert result["data"] == {"field": "email"}


class TestAppException:
    """测试业务异常类。"""

    def test_app_exception_attributes(self):
        """验证 AppException 包含 code/message/data 属性。"""
        exc = AppException(1002, "未授权")

        assert exc.code == 1002
        assert exc.message == "未授权"
        assert exc.data is None

    def test_app_exception_with_data(self):
        """验证 AppException 可附带数据。"""
        exc = AppException(1001, "参数错误", data={"field": "id"})

        assert exc.data == {"field": "id"}

    def test_app_exception_is_exception(self):
        """验证 AppException 是 Exception 的子类。"""
        exc = AppException(1001, "测试")
        assert isinstance(exc, Exception)

    def test_predefined_error_constants(self):
        """验证预定义错误常量。"""
        from app.utils.response import (
            ERR_PARAMS, ERR_UNAUTHORIZED, ERR_NOT_FOUND,
            ERR_FORBIDDEN, ERR_INTERNAL,
        )

        assert ERR_PARAMS.code == 1001
        assert ERR_UNAUTHORIZED.code == 1002
        assert ERR_NOT_FOUND.code == 1003
        assert ERR_FORBIDDEN.code == 1004
        assert ERR_INTERNAL.code == 1005


class TestAPIRoutes:
    """测试 API 路由基础。"""

    @pytest.mark.asyncio
    async def test_404_not_found(self, client, db_session):
        """验证访问不存在的路由返回 404。"""
        response = await client.get("/nonexistent-route")
        assert response.status_code == 404

    @pytest.mark.asyncio
    async def test_api_prefix(self, client, db_session):
        """验证 API 路径前缀为 /api。"""
        # /api/agents 是有效路由
        response = await client.get("/agents")
        assert response.status_code == 200

    @pytest.mark.asyncio
    async def test_conversations_list_response_format(self, client, db_session, mock_redis):
        """验证会话列表 API 返回统一响应格式。"""
        # 先登录坐席获取 token（/api/conversations 需要 get_current_agent 认证）
        login_resp = await client.post(
            "/agents/login",
            json={"user_id": "basic_test_agent", "name": "基础测试坐席"},
        )
        token = login_resp.json()["data"]["token"]

        response = await client.get(
            "/conversations",
            headers={"Authorization": f"Bearer {token}"},
        )

        data = response.json()
        assert "code" in data
        assert "data" in data
        assert "message" in data
        assert data["code"] == 0
