"""
UAT用户体验验收测试

测试范围:
1. 界面友好性验证
2. 操作便捷性验证
3. 错误提示友好性验证
4. 响应时间验收
5. 可访问性验证
"""

import pytest
import time
import asyncio
from typing import Dict, Any
from playwright.async_api import async_playwright, Page, expect
from api.auth_api import AuthAPI
from api.user_api import UserAPI
from api.role_api import RoleAPI
from config.settings import settings


@pytest.mark.uat
@pytest.mark.user_experience
@pytest.mark.asyncio
class TestUserExperienceUAT:
    """用户体验验收测试类"""
    
    @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(
            viewport={"width": 1920, "height": 1080},
            locale="zh-CN"
        )
        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_page(self, page):
        """已认证的页面fixture"""
        await page.goto(f"{settings.FRONTEND_URL}/login")
        await page.wait_for_load_state("networkidle")
        
        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.wait_for_load_state("networkidle")
        
        yield page
    
    async def test_ue_interface_friendly_login(self, page):
        """
        UE-01: 登录界面友好性验证
        
        验证点:
        - 登录页面布局合理
        - 输入框提示清晰
        - 按钮位置合理
        - 错误提示友好
        """
        await page.goto(f"{settings.FRONTEND_URL}/login")
        await page.wait_for_load_state("networkidle")
        
        username_input = await page.query_selector('input[placeholder="请输入用户名"]')
        assert username_input is not None, "用户名输入框应存在"
        
        password_input = await page.query_selector('input[placeholder="请输入密码"]')
        assert password_input is not None, "密码输入框应存在"
        
        submit_button = await page.query_selector('button[type="submit"]')
        assert submit_button is not None, "登录按钮应存在"
        
        await page.fill('input[placeholder="请输入用户名"]', "wrong_user")
        await page.fill('input[placeholder="请输入密码"]', "wrong_pass")
        await page.click('button[type="submit"]')
        
        await asyncio.sleep(1)
        
        error_message = await page.query_selector('.el-message--error')
        assert error_message is not None, "应显示错误提示"
        
        error_text = await error_message.text_content()
        assert len(error_text) > 0, "错误提示应有内容"
    
    async def test_ue_interface_friendly_dashboard(self, authenticated_page):
        """
        UE-02: 仪表盘界面友好性验证
        
        验证点:
        - 页面布局清晰
        - 导航菜单易用
        - 数据展示直观
        - 响应式设计
        """
        page = authenticated_page
        
        sidebar = await page.query_selector('.sidebar-container')
        assert sidebar is not None, "侧边栏应存在"
        
        navbar = await page.query_selector('.navbar')
        assert navbar is not None, "导航栏应存在"
        
        main_content = await page.query_selector('.app-main')
        assert main_content is not None, "主内容区应存在"
        
        await page.set_viewport_size({"width": 768, "height": 1024})
        await asyncio.sleep(0.5)
        
        mobile_menu = await page.query_selector('.mobile-menu')
        assert mobile_menu is not None or sidebar is not None, "移动端应显示菜单按钮或侧边栏"
    
    async def test_ue_operation_convenience_user_management(self, authenticated_page):
        """
        UE-03: 用户管理操作便捷性验证
        
        验证点:
        - 列表加载快速
        - 搜索功能便捷
        - 操作按钮明显
        - 表单填写简单
        """
        page = authenticated_page
        
        start_time = time.time()
        await page.click('text=用户管理')
        await page.wait_for_load_state("networkidle")
        load_time = time.time() - start_time
        
        assert load_time < 3.0, f"用户管理页面加载时间应小于3秒，实际: {load_time:.2f}秒"
        
        search_input = await page.query_selector('input[placeholder*="搜索"]')
        if search_input:
            await search_input.fill("admin")
            await asyncio.sleep(0.5)
            
            table_rows = await page.query_selector_all('.el-table__row')
            assert len(table_rows) > 0, "搜索应返回结果"
        
        create_button = await page.query_selector('button:has-text("新增")')
        assert create_button is not None, "新增按钮应存在且明显"
        
        await create_button.click()
        await page.wait_for_load_state("networkidle")
        
        dialog = await page.query_selector('.el-dialog')
        assert dialog is not None, "新增用户对话框应弹出"
        
        form_items = await dialog.query_selector_all('.el-form-item')
        assert len(form_items) > 0, "表单应包含必填项"
    
    async def test_ue_operation_convenience_role_management(self, authenticated_page):
        """
        UE-04: 角色管理操作便捷性验证
        
        验证点:
        - 角色列表清晰
        - 权限树易操作
        - 批量操作支持
        """
        page = authenticated_page
        
        await page.click('text=角色管理')
        await page.wait_for_load_state("networkidle")
        
        role_table = await page.query_selector('.el-table')
        assert role_table is not None, "角色表格应存在"
        
        edit_button = await page.query_selector('button:has-text("编辑")')
        if edit_button:
            await edit_button.click()
            await page.wait_for_load_state("networkidle")
            
            permission_tree = await page.query_selector('.el-tree')
            assert permission_tree is not None, "权限树应存在"
            
            tree_checkboxes = await permission_tree.query_selector_all('.el-checkbox')
            assert len(tree_checkboxes) > 0, "权限树应包含可选项"
    
    async def test_ue_error_message_friendly(self, page):
        """
        UE-05: 错误提示友好性验证
        
        验证点:
        - 错误信息清晰
        - 错误位置明确
        - 解决建议提供
        """
        await page.goto(f"{settings.FRONTEND_URL}/login")
        await page.wait_for_load_state("networkidle")
        
        await page.click('button[type="submit"]')
        await asyncio.sleep(1)
        
        validation_errors = await page.query_selector_all('.el-form-item__error')
        assert len(validation_errors) > 0, "应显示表单验证错误"
        
        for error in validation_errors:
            error_text = await error.text_content()
            assert len(error_text) > 0, "错误信息应有内容"
            assert "请" in error_text or "不能为空" in error_text, "错误信息应友好"
    
    async def test_ue_response_time_acceptance(self, authenticated_page):
        """
        UE-06: 响应时间验收
        
        验证点:
        - 页面加载时间 < 3秒
        - API响应时间 < 1秒
        - 列表查询时间 < 2秒
        """
        page = authenticated_page
        
        pages_to_test = [
            ("用户管理", "用户管理页面"),
            ("角色管理", "角色管理页面"),
            ("菜单管理", "菜单管理页面")
        ]
        
        for menu_text, page_name in pages_to_test:
            start_time = time.time()
            await page.click(f'text={menu_text}')
            await page.wait_for_load_state("networkidle")
            load_time = time.time() - start_time
            
            assert load_time < 3.0, f"{page_name}加载时间应小于3秒，实际: {load_time:.2f}秒"
    
    async def test_ue_accessibility_verification(self, authenticated_page):
        """
        UE-07: 可访问性验证
        
        验证点:
        - 键盘导航支持
        - ARIA标签存在
        - 对比度合理
        - 字体大小合适
        """
        page = authenticated_page
        
        await page.keyboard.press('Tab')
        await asyncio.sleep(0.2)
        
        focused_element = await page.query_selector(':focus')
        assert focused_element is not None, "应支持键盘导航"
        
        buttons = await page.query_selector_all('button')
        for button in buttons[:5]:
            aria_label = await button.get_attribute('aria-label')
            text_content = await button.text_content()
            assert aria_label or text_content, "按钮应有ARIA标签或文本内容"
        
        body = await page.query_selector('body')
        font_size = await body.evaluate('el => window.getComputedStyle(el).fontSize')
        font_size_value = float(font_size.replace('px', ''))
        assert font_size_value >= 14, f"字体大小应不小于14px，实际: {font_size_value}px"
    
    async def test_ue_form_validation_feedback(self, authenticated_page):
        """
        UE-08: 表单验证反馈验证
        
        验证点:
        - 实时验证反馈
        - 验证规则清晰
        - 错误位置标记
        """
        page = authenticated_page
        
        await page.click('text=用户管理')
        await page.wait_for_load_state("networkidle")
        
        create_button = await page.query_selector('button:has-text("新增")')
        await create_button.click()
        await page.wait_for_load_state("networkidle")
        
        username_input = await page.query_selector('input[placeholder*="用户名"]')
        if username_input:
            await username_input.fill("a")
            await username_input.blur()
            await asyncio.sleep(0.5)
            
            error_message = await page.query_selector('.el-form-item__error')
            if error_message:
                error_text = await error_message.text_content()
                assert len(error_text) > 0, "应显示验证错误信息"
    
    async def test_ue_loading_state_feedback(self, authenticated_page):
        """
        UE-09: 加载状态反馈验证
        
        验证点:
        - 加载动画显示
        - 加载提示清晰
        - 禁用重复提交
        """
        page = authenticated_page
        
        await page.click('text=用户管理')
        await page.wait_for_load_state("networkidle")
        
        loading_overlay = await page.query_selector('.el-loading-mask')
        
        create_button = await page.query_selector('button:has-text("新增")')
        if create_button:
            is_disabled = await create_button.is_disabled()
            assert not is_disabled, "按钮应可点击"
    
    async def test_ue_confirmation_dialog(self, authenticated_page):
        """
        UE-10: 确认对话框验证
        
        验证点:
        - 危险操作有确认
        - 确认信息清晰
        - 取消操作支持
        """
        page = authenticated_page
        
        await page.click('text=用户管理')
        await page.wait_for_load_state("networkidle")
        
        delete_buttons = await page.query_selector_all('button:has-text("删除")')
        
        if len(delete_buttons) > 0:
            await delete_buttons[0].click()
            await asyncio.sleep(0.5)
            
            confirm_dialog = await page.query_selector('.el-message-box')
            assert confirm_dialog is not None, "删除操作应弹出确认对话框"
            
            cancel_button = await confirm_dialog.query_selector('button:has-text("取消")')
            assert cancel_button is not None, "确认对话框应有取消按钮"
            
            await cancel_button.click()
            await asyncio.sleep(0.5)
            
            dialog_closed = await page.query_selector('.el-message-box')
            assert dialog_closed is None, "点击取消应关闭对话框"


@pytest.mark.uat
@pytest.mark.user_experience
@pytest.mark.regression
class TestUserExperienceRegression:
    """用户体验回归测试"""
    
    @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(viewport={"width": 1920, "height": 1080})
        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.mark.asyncio
    async def test_ue_browser_compatibility(self, page):
        """
        UE-REG-01: 浏览器兼容性验证
        
        验证点:
        - Chrome浏览器兼容
        - 主要功能正常
        """
        await page.goto(f"{settings.FRONTEND_URL}/login")
        await page.wait_for_load_state("networkidle")
        
        login_form = await page.query_selector('.login-form')
        assert login_form is not None, "登录表单应正常显示"
    
    @pytest.mark.asyncio
    async def test_ue_responsive_design(self, page):
        """
        UE-REG-02: 响应式设计验证
        
        验证点:
        - 桌面端显示正常
        - 平板端显示正常
        - 移动端显示正常
        """
        viewports = [
            {"width": 1920, "height": 1080, "name": "桌面端"},
            {"width": 768, "height": 1024, "name": "平板端"},
            {"width": 375, "height": 667, "name": "移动端"}
        ]
        
        for viewport in viewports:
            await page.set_viewport_size({"width": viewport["width"], "height": viewport["height"]})
            await page.goto(f"{settings.FRONTEND_URL}/login")
            await page.wait_for_load_state("networkidle")
            
            login_form = await page.query_selector('.login-form')
            assert login_form is not None, f"{viewport['name']}登录表单应正常显示"
