"""
用户生命周期UAT测试 - 模拟真实业务场景
"""

import pytest
import time
from playwright.async_api import async_playwright, Page
from httpx import AsyncClient

from config.settings import settings


@pytest.mark.uat
@pytest.mark.user_lifecycle
class TestUserLifecycleUAT:
    """用户生命周期UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        """浏览器fixture"""
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        """浏览器上下文fixture"""
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        """页面fixture"""
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        """已认证的HTTP客户端"""
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_user_registration_and_login(self, page, authenticated_client):
        """UAT: 用户注册和登录流程"""
        timestamp = int(time.time() * 1000)
        username = f"uat_user_{timestamp}"
        email = f"uat_{timestamp}@example.com"
        password = "Test123!@#"
        
        # 步骤1: 通过API创建用户
        response = await authenticated_client.post(
            "/api/users",
            json={
                "username": username,
                "password": password,
                "email": email,
                "phone": "13800138000",
                "status": 1
            }
        )
        assert response.status_code == 201, f"创建用户失败: {response.text}"
        user_id = response.json()["id"]
        
        try:
            # 步骤2: 通过前端登录
            await page.goto("http://localhost:3002/login")
            await page.wait_for_load_state("networkidle")
            
            await page.fill('input[placeholder="请输入用户名"]', username)
            await page.fill('input[placeholder="请输入密码"]', password)
            await page.click('button[type="submit"]')
            
            await page.wait_for_url("**/")
            await page.wait_for_load_state("networkidle")
            
            # 步骤3: 验证登录成功
            title = await page.title()
            assert "首页" in title or "Dashboard" in title, "登录后未跳转到首页"
            
            # 步骤4: 验证用户信息显示
            user_info = await page.query_selector('.user-info')
            assert user_info is not None, "用户信息元素未找到"
            
        finally:
            # 清理
            await authenticated_client.delete(f"/api/users/{user_id}")
    
    @pytest.mark.asyncio
    async def test_uat_user_profile_update(self, page, authenticated_client):
        """UAT: 用户资料更新流程"""
        timestamp = int(time.time() * 1000)
        username = f"uat_profile_{timestamp}"
        email = f"uat_profile_{timestamp}@example.com"
        
        # 步骤1: 创建测试用户
        response = await authenticated_client.post(
            "/api/users",
            json={
                "username": username,
                "password": "Test123!@#",
                "email": email,
                "phone": "13800138000",
                "status": 1
            }
        )
        assert response.status_code == 201
        user_id = response.json()["id"]
        
        try:
            # 步骤2: 登录
            await page.goto("http://localhost:3002/login")
            await page.fill('input[placeholder="请输入用户名"]', username)
            await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
            await page.click('button[type="submit"]')
            await page.wait_for_url("**/")
            
            # 步骤3: 访问用户资料页面
            await page.click('text=用户管理')
            await page.wait_for_url("**/users")
            
            # 步骤4: 编辑用户
            await page.click('text=编辑')
            await page.wait_for_load_state("networkidle")
            
            # 步骤5: 更新资料
            await page.fill('input[placeholder=""]', '测试用户昵称')
            await page.fill('input[placeholder=""]', '13900139000')
            
            await page.click('button:has-text("确定")')
            await page.wait_for_load_state("networkidle")
            
            # 步骤6: 验证更新
            page_content = await page.content()
            assert "测试用户昵称" in page_content
            
        finally:
            await authenticated_client.delete(f"/api/users/{user_id}")
    
    @pytest.mark.asyncio
    async def test_uat_user_status_change(self, page, authenticated_client):
        """UAT: 用户状态变更流程"""
        timestamp = int(time.time() * 1000)
        username = f"uat_status_{timestamp}"
        
        # 创建用户
        response = await authenticated_client.post(
            "/api/users",
            json={
                "username": username,
                "password": "Test123!@#",
                "email": f"uat_status_{timestamp}@example.com",
                "status": 1
            }
        )
        assert response.status_code == 201
        user_id = response.json()["id"]
        
        try:
            # 登录并禁用用户
            await page.goto("http://localhost:3002/login")
            await page.fill('input[placeholder="请输入用户名"]', username)
            await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
            await page.click('button[type="submit"]')
            await page.wait_for_url("**/")
            
            # 尝试禁用用户
            await page.click('text=用户管理')
            await page.wait_for_url("**/users")
            
            # 禁用用户
            await page.click('button:has-text("禁用")')
            await page.click('button:has-text("确定")')
            await page.wait_for_load_state("networkidle")
            
            # 验证状态变更
            page_content = await page.content()
            assert "禁用" in page_content
            
        finally:
            await authenticated_client.delete(f"/api/users/{user_id}")
    
    @pytest.mark.asyncio
    async def test_uat_user_delete(self, page, authenticated_client):
        """UAT: 用户删除流程"""
        timestamp = int(time.time() * 1000)
        username = f"uat_delete_{timestamp}"
        
        # 创建用户
        response = await authenticated_client.post(
            "/api/users",
            json={
                "username": username,
                "password": "Test123!@#",
                "email": f"uat_delete_{timestamp}@example.com",
                "status": 1
            }
        )
        assert response.status_code == 201
        user_id = response.json()["id"]
        
        # 登录并删除用户
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', username)
        await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=用户管理')
        await page.wait_for_url("**/users")
        
        await page.click('button:has-text("删除")')
        await page.click('button:has-text("确定")')
        await page.wait_for_load_state("networkidle")
        
        # 验证删除
        page_content = await page.content()
        assert username not in page_content


@pytest.mark.uat
@pytest.mark.role_workflow
class TestRoleWorkflowUAT:
    """角色工作流UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_role_assignment(self, page, authenticated_client):
        """UAT: 角色分配流程"""
        timestamp = int(time.time() * 1000)
        username = f"uat_role_user_{timestamp}"
        role_name = f"UAT_Role_{timestamp}"
        
        # 创建角色
        role_response = await authenticated_client.post(
            "/api/roles",
            json={
                "roleName": role_name,
                "roleKey": f"uat_role_{timestamp}",
                "roleSort": 1,
                "status": 1
            }
        )
        assert role_response.status_code == 201
        role_id = role_response.json()["id"]
        
        try:
            # 创建用户
            user_response = await authenticated_client.post(
                "/api/users",
                json={
                    "username": username,
                    "password": "Test123!@#",
                    "email": f"uat_role_user_{timestamp}@example.com",
                    "status": 1
                }
            )
            assert user_response.status_code == 201
            user_id = user_response.json()["id"]
            
            # 登录并分配角色
            await page.goto("http://localhost:3002/login")
            await page.fill('input[placeholder="请输入用户名"]', username)
            await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
            await page.click('button[type="submit"]')
            await page.wait_for_url("**/")
            
            await page.click('text=用户管理')
            await page.wait_for_url("**/users")
            
            # 分配角色
            await page.click('text=分配角色')
            await page.wait_for_load_state("networkidle")
            
            # 选择角色
            await page.click(f'text={role_name}')
            
            await page.click('button:has-text("确定")')
            await page.wait_for_load_state("networkidle")
            
            # 验证角色分配
            user_info = await authenticated_client.get(f"/api/users/{user_id}")
            assert user_info.status_code == 200
            user_data = user_info.json()
            assert user_data["roleId"] == role_id
            
        finally:
            await authenticated_client.delete(f"/api/users/{user_id}")
            await authenticated_client.delete(f"/api/roles/{role_id}")
    
    @pytest.mark.asyncio
    async def test_uat_role_permission_management(self, page, authenticated_client):
        """UAT: 角色权限管理流程"""
        timestamp = int(time.time() * 1000)
        role_name = f"UAT_Permission_Role_{timestamp}"
        
        # 创建角色
        role_response = await authenticated_client.post(
            "/api/roles",
            json={
                "roleName": role_name,
                "roleKey": f"uat_perm_role_{timestamp}",
                "roleSort": 1,
                "status": 1
            }
        )
        assert role_response.status_code == 201
        role_id = role_response.json()["id"]
        
        try:
            # 登录并访问角色管理
            await page.goto("http://localhost:3002/login")
            await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
            await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
            await page.click('button[type="submit"]')
            await page.wait_for_url("**/")
            
            await page.click('text=角色管理')
            await page.wait_for_url("**/roles")
            
            # 编辑角色权限
            await page.click('text=编辑')
            await page.wait_for_load_state("networkidle")
            
            # 更新角色信息
            await page.fill('input[placeholder=""]', f"{role_name}_updated")
            
            await page.click('button:has-text("确定")')
            await page.wait_for_load_state("networkidle")
            
            # 验证更新
            roles_response = await authenticated_client.get("/api/roles")
            roles = roles_response.json()
            role_exists = any(r['roleName'] == f"{role_name}_updated" for r in roles)
            assert role_exists
            
        finally:
            await authenticated_client.delete(f"/api/roles/{role_id}")


@pytest.mark.uat
@pytest.mark.config_workflow
class TestConfigWorkflowUAT:
    """配置工作流UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_system_config_update(self, page, authenticated_client):
        """UAT: 系统配置更新流程"""
        timestamp = int(time.time() * 1000)
        
        # 登录并访问系统配置
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
        await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=系统配置')
        await page.wait_for_url("**/config")
        await page.wait_for_load_state("networkidle")
        
        # 编辑配置
        await page.click('text=编辑')
        await page.wait_for_load_state("networkidle")
        
        # 更新配置
        await page.fill('input[placeholder=""]', f"Test_Config_{timestamp}")
        await page.fill('textarea[placeholder=""]', '测试配置内容')
        
        await page.click('button:has-text("确定")')
        await page.wait_for_load_state("networkidle")
        
        # 验证更新
        config_response = await authenticated_client.get("/api/config")
        assert config_response.status_code == 200


@pytest.mark.uat
@pytest.mark.data_dict_workflow
class TestDataDictWorkflowUAT:
    """数据字典工作流UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_dict_type_management(self, page, authenticated_client):
        """UAT: 字典类型管理流程"""
        timestamp = int(time.time() * 1000)
        dict_type = f"UAT_DICT_{timestamp}"
        
        # 登录并访问字典管理
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
        await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=字典管理')
        await page.wait_for_url("**/dicts")
        await page.wait_for_load_state("networkidle")
        
        # 创建字典类型
        await page.click('text=新增字典')
        await page.wait_for_load_state("networkidle")
        
        await page.fill('input[placeholder=""]', dict_type)
        await page.fill('input[placeholder=""]', f"uat_dict_{timestamp}")
        await page.fill('textarea[placeholder=""]', '测试字典类型')
        
        await page.click('button:has-text("确定")')
        await page.wait_for_load_state("networkidle")
        
        # 验证创建
        dicts_response = await authenticated_client.get("/api/dict/types")
        assert dicts_response.status_code == 200
        dicts = dicts_response.json()
        dict_exists = any(d['type'] == dict_type for d in dicts)
        assert dict_exists
    
    @pytest.mark.asyncio
    async def test_uat_dict_data_management(self, page, authenticated_client):
        """UAT: 字典数据管理流程"""
        timestamp = int(time.time() * 1000)
        
        # 登录并访问字典管理
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
        await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=字典管理')
        await page.wait_for_url("**/dicts")
        await page.wait_for_load_state("networkidle")
        
        # 查看字典数据
        await page.click('text=查看')
        await page.wait_for_load_state("networkidle")
        
        # 验证字典数据列表
        page_content = await page.content()
        assert "字典数据" in page_content or "code" in page_content.lower()


@pytest.mark.uat
@pytest.mark.audit_workflow
class TestAuditWorkflowUAT:
    """审计工作流UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_operation_log_audit(self, page, authenticated_client):
        """UAT: 操作日志审计流程"""
        timestamp = int(time.time() * 1000)
        
        # 登录并访问操作日志
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
        await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=操作日志')
        await page.wait_for_url("**/operation-logs")
        await page.wait_for_load_state("networkidle")
        
        # 验证操作日志列表
        await page.wait_for_selector('.el-card', timeout=10000)
        
        # 通过API验证
        logs_response = await authenticated_client.get("/api/audit/operation-logs")
        assert logs_response.status_code == 200
        logs = logs_response.json()
        assert len(logs) > 0, "操作日志为空"
    
    @pytest.mark.asyncio
    async def test_uat_login_log_audit(self, page, authenticated_client):
        """UAT: 登录日志审计流程"""
        # 登录并访问登录日志
        await page.goto("http://localhost:3002/login")
        await page.fill('input[placeholder="请输入用户名"]', settings.TEST_USERNAME)
        await page.fill('input[placeholder="请输入密码"]', settings.TEST_PASSWORD)
        await page.click('button[type="submit"]')
        await page.wait_for_url("**/")
        
        await page.click('text=登录日志')
        await page.wait_for_url("**/login-logs")
        await page.wait_for_load_state("networkidle")
        
        # 验证登录日志列表
        await page.wait_for_selector('.el-card', timeout=10000)
        
        # 通过API验证
        login_logs_response = await authenticated_client.get("/api/audit/login-logs")
        assert login_logs_response.status_code == 200
        login_logs = login_logs_response.json()
        assert len(login_logs) > 0, "登录日志为空"


@pytest.mark.uat
@pytest.mark.comprehensive_workflow
class TestComprehensiveWorkflowUAT:
    """综合业务流程UAT测试"""
    
    @pytest.fixture
    async def browser(self):
        async with async_playwright() as p:
            browser = await p.chromium.launch(headless=True)
            yield browser
            await browser.close()
    
    @pytest.fixture
    async def context(self, browser):
        context = await browser.new_context()
        yield context
        await context.close()
    
    @pytest.fixture
    async def page(self, context):
        page = await context.new_page()
        page.set_default_timeout(30000)
        yield page
        await page.close()
    
    @pytest.fixture
    async def authenticated_client(self):
        async with AsyncClient(base_url=settings.API_BASE_URL) as client:
            response = await client.post(
                "/api/auth/login",
                json={
                    "username": settings.TEST_USERNAME,
                    "password": settings.TEST_PASSWORD
                }
            )
            assert response.status_code == 200
            token = response.json().get("token")
            client.headers.update({"Authorization": f"Bearer {token}"})
            yield client
    
    @pytest.mark.asyncio
    async def test_uat_complete_business_workflow(self, page, authenticated_client):
        """UAT: 完整业务流程测试"""
        timestamp = int(time.time() * 1000)
        
        # 步骤1: 用户注册
        username = f"uat_complete_{timestamp}"
        response = await authenticated_client.post(
            "/api/users",
            json={
                "username": username,
                "password": "Test123!@#",
                "email": f"uat_complete_{timestamp}@example.com",
                "phone": "13800138000",
                "status": 1
            }
        )
        assert response.status_code == 201
        user_id = response.json()["id"]
        
        try:
            # 步骤2: 用户登录
            await page.goto("http://localhost:3002/login")
            await page.fill('input[placeholder="请输入用户名"]', username)
            await page.fill('input[placeholder="请输入密码"]', "Test123!@#")
            await page.click('button[type="submit"]')
            await page.wait_for_url("**/")
            
            # 步骤3: 浏览用户管理
            await page.click('text=用户管理')
            await page.wait_for_url("**/users")
            
            # 步骤4: 浏览角色管理
            await page.click('text=角色管理')
            await page.wait_for_url("**/roles")
            
            # 步骤5: 浏览系统配置
            await page.click('text=系统配置')
            await page.wait_for_url("**/config")
            
            # 步骤6: 浏览字典管理
            await page.click('text=字典管理')
            await page.wait_for_url("**/dicts")
            
            # 步骤7: 浏览通知管理
            await page.click('text=通知管理')
            await page.wait_for_url("**/notices")
            
            # 步骤8: 浏览文件管理
            await page.click('text=文件管理')
            await page.wait_for_url("**/files")
            
            # 步骤9: 浏览审计日志
            await page.click('text=操作日志')
            await page.wait_for_url("**/operation-logs")
            
            # 步骤10: 登出
            await page.click('text=退出登录')
            await page.wait_for_url("**/login")
            
        finally:
            await authenticated_client.delete(f"/api/users/{user_id}")