"""
UAT测试套件 - 用户验收测试场景

测试范围:
1. 用户注册登录验收场景
2. 用户管理业务验收场景
3. 角色权限配置验收场景
4. 系统配置管理验收场景
5. 审计日志查询验收场景

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

import pytest
import time
import uuid
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from api.role_api import RoleAPI
from api.menu_api import MenuAPI
from api.config_api import ConfigAPI
from api.audit_api import AuditAPI
from config.settings import settings


@pytest.mark.uat
@pytest.mark.asyncio
class TestUATUserScenarios:
    """UAT用户场景测试类"""
    
    async def test_uat_new_user_registration_and_login(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-USER-01: 新用户注册登录验收场景
        
        业务场景:
        作为新用户,我希望能够注册账号并登录系统
        
        验收标准:
        1. 用户能够成功注册
        2. 注册后能够立即登录
        3. 登录后能看到正确的用户信息
        4. 用户信息显示完整准确
        """
        user_api = UserAPI(authenticated_client)
        auth_api = AuthAPI(authenticated_client)
        
        unique_id = f"uat_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        user_data = {
            "username": f"newuser_{unique_id}",
            "password": "SecurePass123!@#",
            "email": f"newuser_{unique_id}@company.com",
            "phone": "13900139000",
            "nickname": "新员工张三",
            "status": 1
        }
        
        create_response = await user_api.create_user(user_data)
        assert create_response.status_code in [201, 200], \
            "❌ 用户注册失败"
        user_id = create_response.json().get("id")
        test_data_manager.add_user(user_id)
        
        login_response = await auth_api.login(
            user_data["username"],
            user_data["password"]
        )
        assert login_response.status_code == 200, \
            "❌ 注册后登录失败"
        
        token = login_response.json().get("token")
        assert token is not None, \
            "❌ 未获取到登录令牌"
        
        user_info_response = await user_api.get_user_by_id(user_id)
        assert user_info_response.status_code == 200, \
            "❌ 获取用户信息失败"
        
        user_info = user_info_response.json()
        assert user_info["username"] == user_data["username"], \
            "❌ 用户名不匹配"
        assert user_info["email"] == user_data["email"], \
            "❌ 邮箱不匹配"
        assert user_info["nickname"] == user_data["nickname"], \
            "❌ 昵称不匹配"
        
        print("✅ UAT-USER-01: 新用户注册登录验收通过")
    
    async def test_uat_user_profile_management(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-USER-02: 用户信息管理验收场景
        
        业务场景:
        作为已登录用户,我希望能够修改我的个人信息
        
        验收标准:
        1. 用户能够修改昵称
        2. 用户能够修改邮箱
        3. 用户能够修改手机号
        4. 修改后信息立即生效
        """
        user_api = UserAPI(authenticated_client)
        
        unique_id = f"uat_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        user_data = {
            "username": f"profileuser_{unique_id}",
            "password": "Test123!@#",
            "email": f"profile_{unique_id}@test.com",
            "phone": "13800138000",
            "nickname": "原始昵称",
            "status": 1
        }
        
        create_response = await user_api.create_user(user_data)
        user_id = create_response.json().get("id")
        test_data_manager.add_user(user_id)
        
        update_data = {
            "nickname": "更新后的昵称",
            "email": f"updated_{unique_id}@test.com",
            "phone": "13900139000"
        }
        
        update_response = await user_api.update_user(user_id, update_data)
        assert update_response.status_code == 200, \
            "❌ 更新用户信息失败"
        
        verify_response = await user_api.get_user_by_id(user_id)
        updated_user = verify_response.json()
        
        assert updated_user["nickname"] == update_data["nickname"], \
            "❌ 昵称未更新"
        assert updated_user["email"] == update_data["email"], \
            "❌ 邮箱未更新"
        assert updated_user["phone"] == update_data["phone"], \
            "❌ 手机号未更新"
        
        print("✅ UAT-USER-02: 用户信息管理验收通过")


@pytest.mark.uat
@pytest.mark.asyncio
class TestUATRolePermissionScenarios:
    """UAT角色权限场景测试类"""
    
    async def test_uat_role_creation_and_permission_assignment(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-ROLE-01: 角色创建与权限分配验收场景
        
        业务场景:
        作为系统管理员,我希望能够创建新角色并分配相应权限
        
        验收标准:
        1. 能够创建新角色
        2. 能够为角色分配菜单权限
        3. 分配给用户后权限立即生效
        4. 用户只能访问被授权的功能
        """
        role_api = RoleAPI(authenticated_client)
        user_api = UserAPI(authenticated_client)
        menu_api = MenuAPI(authenticated_client)
        
        unique_id = f"uat_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        role_data = {
            "roleName": f"部门经理_{unique_id}",
            "roleKey": f"dept_manager_{unique_id}",
            "roleSort": 10,
            "status": 1,
            "remark": "部门经理角色,具有用户管理权限"
        }
        
        create_response = await role_api.create_role(role_data)
        assert create_response.status_code in [201, 200], \
            "❌ 创建角色失败"
        role_id = create_response.json().get("id")
        test_data_manager.add_role(role_id)
        
        menus_response = await menu_api.get_menus()
        menus = menus_response.json() if isinstance(
            menus_response.json(), list
        ) else menus_response.json().get("data", [])
        
        if menus:
            menu_ids = [m["id"] for m in menus[:3]]
            
            perm_response = await role_api.assign_permissions(
                role_id,
                {"menuIds": menu_ids}
            )
            assert perm_response.status_code == 200, \
                "❌ 分配菜单权限失败"
        
        user_data = {
            "username": f"roleuser_{unique_id}",
            "password": "Test123!@#",
            "email": f"roleuser_{unique_id}@test.com",
            "phone": "13800138000",
            "status": 1,
            "roleId": role_id
        }
        
        user_response = await user_api.create_user(user_data)
        user_id = user_response.json().get("id")
        test_data_manager.add_user(user_id)
        
        user_info = await user_api.get_user_by_id(user_id)
        assert user_info.status_code == 200, \
            "❌ 用户角色分配失败"
        
        print("✅ UAT-ROLE-01: 角色创建与权限分配验收通过")
    
    async def test_uat_permission_inheritance(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-ROLE-02: 权限继承验证场景
        
        业务场景:
        作为系统管理员,我希望子角色能够继承父角色的权限
        
        验收标准:
        1. 子角色继承父角色权限
        2. 子角色可以扩展额外权限
        3. 子角色权限不超过父角色
        """
        role_api = RoleAPI(authenticated_client)
        
        roles_response = await role_api.get_roles_by_page()
        roles = roles_response.json().get("content", [])
        
        assert len(roles) > 0, \
            "❌ 系统中应至少有一个角色"
        
        admin_role = next(
            (r for r in roles if "admin" in r.get("roleKey", "").lower()),
            None
        )
        
        if admin_role:
            assert admin_role.get("status") == 1, \
                "❌ 管理员角色应处于激活状态"
        
        print("✅ UAT-ROLE-02: 权限继承验证通过")


@pytest.mark.uat
@pytest.mark.asyncio
class TestUATSystemManagementScenarios:
    """UAT系统管理场景测试类"""
    
    async def test_uat_system_configuration_management(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-SYS-01: 系统配置管理验收场景
        
        业务场景:
        作为系统管理员,我希望能够管理系统配置参数
        
        验收标准:
        1. 能够创建新配置项
        2. 能够修改配置值
        3. 配置修改立即生效
        4. 能够删除不需要的配置
        """
        config_api = ConfigAPI(authenticated_client)
        
        unique_id = f"uat_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        config_data = {
            "configKey": f"system.setting.{unique_id}",
            "configValue": "initial_value",
            "configName": f"测试配置_{unique_id}",
            "remark": "UAT测试配置项"
        }
        
        try:
            create_response = await config_api.create_config(config_data)
            
            if create_response.status_code in [201, 200]:
                config_id = create_response.json().get("id")
                
                update_data = {
                    "configValue": "updated_value"
                }
                update_response = await config_api.update_config(
                    config_id,
                    update_data
                )
                assert update_response.status_code == 200, \
                    "❌ 更新配置失败"
                
                get_response = await config_api.get_config_by_key(
                    config_data["configKey"]
                )
                assert get_response.status_code == 200, \
                    "❌ 查询配置失败"
                
                delete_response = await config_api.delete_config(config_id)
                assert delete_response.status_code in [200, 204], \
                    "❌ 删除配置失败"
                
                print("✅ UAT-SYS-01: 系统配置管理验收通过")
            else:
                pytest.skip("系统配置功能不可用")
        except Exception as e:
            pytest.skip(f"系统配置测试跳过: {str(e)}")
    
    async def test_uat_audit_log_query(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-SYS-02: 审计日志查询验收场景
        
        业务场景:
        作为系统管理员,我希望能够查询系统操作日志
        
        验收标准:
        1. 能够查询操作日志
        2. 能够按时间范围筛选
        3. 能够按用户筛选
        4. 日志信息完整准确
        """
        audit_api = AuditAPI(authenticated_client)
        user_api = UserAPI(authenticated_client)
        
        unique_id = f"uat_{int(time.time() * 1000)}"
        
        user_data = {
            "username": f"audituser_{unique_id}",
            "password": "Test123!@#",
            "email": f"audit_{unique_id}@test.com",
            "phone": "13800138000",
            "status": 1
        }
        
        create_response = await user_api.create_user(user_data)
        
        if create_response.status_code in [201, 200]:
            user_id = create_response.json().get("id")
            test_data_manager.add_user(user_id)
            
            await user_api.delete_user(user_id)
            
            operation_logs = await audit_api.get_operation_logs(
                page=0,
                size=10
            )
            assert operation_logs.status_code == 200, \
                "❌ 查询操作日志失败"
            
            logs_data = operation_logs.json()
            assert "content" in logs_data or "data" in logs_data, \
                "❌ 日志数据格式不正确"
            
            print("✅ UAT-SYS-02: 审计日志查询验收通过")
        else:
            pytest.skip("审计日志功能不可用")


@pytest.mark.uat
@pytest.mark.asyncio
class TestUATBusinessWorkflows:
    """UAT业务流程测试类"""
    
    async def test_uat_complete_user_onboarding_workflow(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-WF-01: 完整用户入职流程
        
        业务场景:
        模拟真实的企业员工入职流程
        
        流程步骤:
        1. HR创建新员工账号
        2. 分配相应角色
        3. 员工首次登录
        4. 员工修改个人信息
        5. 验证权限正确
        """
        user_api = UserAPI(authenticated_client)
        role_api = RoleAPI(authenticated_client)
        auth_api = AuthAPI(authenticated_client)
        
        unique_id = f"onboard_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        roles_response = await role_api.get_roles_by_page(size=1)
        roles = roles_response.json().get("content", [])
        role_id = roles[0]["id"] if roles else None
        
        employee_data = {
            "username": f"employee_{unique_id}",
            "password": "Welcome123!@#",
            "email": f"employee_{unique_id}@company.com",
            "phone": "13900139000",
            "nickname": "新员工李四",
            "status": 1,
            "roleId": role_id
        }
        
        create_response = await user_api.create_user(employee_data)
        assert create_response.status_code in [201, 200], \
            "❌ HR创建员工账号失败"
        user_id = create_response.json().get("id")
        test_data_manager.add_user(user_id)
        
        login_response = await auth_api.login(
            employee_data["username"],
            employee_data["password"]
        )
        assert login_response.status_code == 200, \
            "❌ 员工首次登录失败"
        
        update_data = {
            "nickname": "李四(已认证)",
            "phone": "13900139001"
        }
        update_response = await user_api.update_user(user_id, update_data)
        assert update_response.status_code == 200, \
            "❌ 员工修改个人信息失败"
        
        print("✅ UAT-WF-01: 完整用户入职流程验收通过")
    
    async def test_uat_role_permission_change_workflow(
        self, authenticated_client, test_data_manager
    ):
        """
        UAT-WF-02: 角色权限变更流程
        
        业务场景:
        模拟员工晋升后权限调整流程
        
        流程步骤:
        1. 创建普通员工账号
        2. 验证初始权限
        3. 员工晋升,调整角色
        4. 验证新权限生效
        """
        user_api = UserAPI(authenticated_client)
        role_api = RoleAPI(authenticated_client)
        
        unique_id = f"promo_{int(time.time() * 1000)}_{uuid.uuid4().hex[:8]}"
        
        roles_response = await role_api.get_roles_by_page()
        roles = roles_response.json().get("content", [])
        
        if len(roles) >= 2:
            initial_role = roles[0]
            promoted_role = roles[1]
            
            user_data = {
                "username": f"promoted_{unique_id}",
                "password": "Test123!@#",
                "email": f"promoted_{unique_id}@test.com",
                "phone": "13800138000",
                "status": 1,
                "roleId": initial_role["id"]
            }
            
            create_response = await user_api.create_user(user_data)
            user_id = create_response.json().get("id")
            test_data_manager.add_user(user_id)
            
            assign_response = await user_api.assign_roles(
                user_id,
                [promoted_role["id"]]
            )
            assert assign_response.status_code == 200, \
                "❌ 调整角色失败"
            
            print("✅ UAT-WF-02: 角色权限变更流程验收通过")
        else:
            pytest.skip("需要至少2个角色才能测试权限变更")
