"""
单元测试套件 - API客户端测试

测试范围:
1. API客户端基础功能
2. 认证API测试
3. 用户API测试
4. 角色API测试

作者: 张翔
日期: 2026-04-01
"""

import pytest
from unittest.mock import Mock, AsyncMock, patch
from api.base_api import BaseAPIClient, AsyncAPIClient
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from api.role_api import RoleAPI


@pytest.mark.unit
class TestBaseAPI:
    """API客户端基础功能测试"""
    
    def test_base_api_initialization(self):
        """
        UNIT-API-01: API客户端初始化测试
        
        验证点:
        1. 正确初始化客户端
        2. 设置基础URL
        3. 设置超时时间
        """
        base_url = "http://localhost:8084"
        
        api = BaseAPIClient(base_url=base_url, timeout=30)
        
        assert api.base_url == base_url
        assert api.timeout == 30
        assert api.session is not None
    
    def test_api_headers_generation(self):
        """
        UNIT-API-02: API请求头生成测试
        
        验证点:
        1. 正确生成基础请求头
        2. 包含认证Token时添加Authorization
        """
        api = BaseAPIClient()
        api.token = "test_token_123"
        
        headers = api._get_headers(include_auth=True)
        
        assert "Content-Type" in headers
        assert "Authorization" in headers
        assert headers["Authorization"] == "Bearer test_token_123"
        
        headers_no_auth = api._get_headers(include_auth=False)
        assert "Authorization" not in headers_no_auth


@pytest.mark.unit
class TestAuthAPI:
    """认证API测试"""
    
    @pytest.mark.asyncio
    async def test_login_success(self):
        """
        UNIT-AUTH-01: 登录成功测试
        
        验证点:
        1. 正确发送登录请求
        2. 返回Token
        3. 返回用户信息
        """
        mock_client = Mock()
        mock_client.post = AsyncMock(
            return_value=Mock(
                status_code=200,
                json=Mock(return_value={
                    "token": "test_token_123",
                    "userId": 1,
                    "username": "admin"
                })
            )
        )
        
        auth_api = AuthAPI(mock_client)
        
        response = await auth_api.login("admin", "admin123")
        
        assert response.status_code == 200
        assert response.json()["token"] == "test_token_123"
    
    @pytest.mark.asyncio
    async def test_login_failure(self):
        """
        UNIT-AUTH-02: 登录失败测试
        
        验证点:
        1. 错误密码返回401
        2. 错误信息不泄露敏感信息
        """
        mock_client = Mock()
        mock_client.post = AsyncMock(
            return_value=Mock(
                status_code=401,
                json=Mock(return_value={
                    "error": "Invalid credentials"
                })
            )
        )
        
        auth_api = AuthAPI(mock_client)
        
        response = await auth_api.login("admin", "wrong_password")
        
        assert response.status_code == 401
    
    @pytest.mark.asyncio
    async def test_logout(self):
        """
        UNIT-AUTH-03: 登出测试
        
        验证点:
        1. 正确发送登出请求
        2. 返回成功状态
        """
        mock_client = Mock()
        mock_client.post = AsyncMock(
            return_value=Mock(status_code=200)
        )
        
        auth_api = AuthAPI(mock_client)
        
        response = await auth_api.logout()
        
        assert response.status_code == 200


@pytest.mark.unit
class TestUserAPI:
    """用户API测试"""
    
    @pytest.mark.asyncio
    async def test_get_users_by_page(self):
        """
        UNIT-USER-01: 分页获取用户列表测试
        
        验证点:
        1. 正确发送分页参数
        2. 返回分页数据
        3. 包含总数信息
        """
        mock_client = Mock()
        mock_client.get = AsyncMock(
            return_value=Mock(
                status_code=200,
                json=Mock(return_value={
                    "content": [
                        {"id": 1, "username": "admin"},
                        {"id": 2, "username": "user"}
                    ],
                    "totalElements": 2,
                    "totalPages": 1,
                    "size": 10,
                    "number": 0
                })
            )
        )
        
        user_api = UserAPI(mock_client)
        
        response = await user_api.get_users_by_page(page=0, size=10)
        
        assert response.status_code == 200
        assert len(response.json()["content"]) == 2
        assert response.json()["totalElements"] == 2
    
    @pytest.mark.asyncio
    async def test_create_user(self):
        """
        UNIT-USER-02: 创建用户测试
        
        验证点:
        1. 正确发送用户数据
        2. 返回创建的用户ID
        3. 验证必填字段
        """
        mock_client = Mock()
        mock_client.post = AsyncMock(
            return_value=Mock(
                status_code=201,
                json=Mock(return_value={
                    "id": 3,
                    "username": "new_user",
                    "email": "new_user@test.com"
                })
            )
        )
        
        user_api = UserAPI(mock_client)
        
        user_data = {
            "username": "new_user",
            "password": "Test123!@#",
            "email": "new_user@test.com",
            "phone": "13800138000"
        }
        
        response = await user_api.create_user(user_data)
        
        assert response.status_code == 201
        assert response.json()["id"] == 3
    
    @pytest.mark.asyncio
    async def test_update_user(self):
        """
        UNIT-USER-03: 更新用户测试
        
        验证点:
        1. 正确发送更新数据
        2. 返回更新后的用户信息
        3. 部分更新支持
        """
        mock_client = Mock()
        mock_client.put = AsyncMock(
            return_value=Mock(
                status_code=200,
                json=Mock(return_value={
                    "id": 1,
                    "email": "updated@test.com"
                })
            )
        )
        
        user_api = UserAPI(mock_client)
        
        update_data = {"email": "updated@test.com"}
        
        response = await user_api.update_user(1, update_data)
        
        assert response.status_code == 200
        assert response.json()["email"] == "updated@test.com"
    
    @pytest.mark.asyncio
    async def test_delete_user(self):
        """
        UNIT-USER-04: 删除用户测试
        
        验证点:
        1. 正确发送删除请求
        2. 返回成功状态
        """
        mock_client = Mock()
        mock_client.delete = AsyncMock(
            return_value=Mock(status_code=204)
        )
        
        user_api = UserAPI(mock_client)
        
        response = await user_api.delete_user(1)
        
        assert response.status_code == 204
    
    @pytest.mark.asyncio
    async def test_search_users(self):
        """
        UNIT-USER-05: 搜索用户测试
        
        验证点:
        1. 正确发送搜索关键词
        2. 返回匹配结果
        """
        mock_client = Mock()
        mock_client.get = AsyncMock(
            return_value=Mock(
                status_code=200,
                json=Mock(return_value={
                    "content": [
                        {"id": 1, "username": "admin"}
                    ],
                    "totalElements": 1
                })
            )
        )
        
        user_api = UserAPI(mock_client)
        
        response = await user_api.get_users_by_page(username="admin")
        
        assert response.status_code == 200
        assert len(response.json()["content"]) == 1


@pytest.mark.unit
class TestRoleAPI:
    """角色API测试"""
    
    @pytest.mark.asyncio
    async def test_get_roles(self):
        """
        UNIT-ROLE-01: 获取角色列表测试
        
        验证点:
        1. 正确返回角色列表
        2. 包含角色权限信息
        """
        mock_client = Mock()
        mock_client.get = AsyncMock(
            return_value=Mock(
                status_code=200,
                json=Mock(return_value=[
                    {"id": 1, "roleName": "管理员", "roleKey": "admin"},
                    {"id": 2, "roleName": "普通用户", "roleKey": "user"}
                ])
            )
        )
        
        role_api = RoleAPI(mock_client)
        
        response = await role_api.get_role_list()
        
        assert response.status_code == 200
        assert len(response.json()) == 2
    
    @pytest.mark.asyncio
    async def test_assign_permissions(self):
        """
        UNIT-ROLE-02: 分配权限测试
        
        验证点:
        1. 正确发送权限数据
        2. 返回成功状态
        """
        mock_client = Mock()
        mock_client.post = AsyncMock(
            return_value=Mock(status_code=200)
        )
        
        role_api = RoleAPI(mock_client)
        
        permission_ids = [1, 2, 3]
        
        response = await role_api.assign_permissions(1, permission_ids)
        
        assert response.status_code == 200
