"""
性能测试模块
测试网站性能指标
"""

import pytest
import time
from typing import Dict, Any
from datetime import datetime

from pages.home_page import HomePage
from pages.contact_page import ContactPage
from config.settings import get_settings


class TestPerformance:
    """性能测试类"""
    
    @pytest.mark.performance
    @pytest.mark.smoke
    def test_home_page_load_time(self, home_page: HomePage):
        """测试首页加载时间"""
        home_page.navigate()
        
        start_time = time.time()
        home_page.wait_for_load()
        end_time = time.time()
        
        load_time = (end_time - start_time) * 1000  # 毫秒
        
        # 阈值：5秒
        assert load_time < 5000, f"首页加载时间 {load_time:.2f}ms 超过5秒阈值"
    
    @pytest.mark.performance
    @pytest.mark.smoke
    def test_contact_page_load_time(self, contact_page: ContactPage):
        """测试联系页面加载时间"""
        contact_page.navigate()
        
        start_time = time.time()
        contact_page.wait_for_load()
        end_time = time.time()
        
        load_time = (end_time - start_time) * 1000
        
        # 阈值：5秒
        assert load_time < 5000, f"联系页面加载时间 {load_time:.2f}ms 超过5秒阈值"
    
    @pytest.mark.performance
    def test_dom_content_loaded_time(self, home_page: HomePage):
        """测试DOM内容加载时间"""
        home_page.navigate()
        
        performance_data = home_page.execute_js("""
            () => {
                const timing = performance.timing;
                return {
                    domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,
                    domInteractive: timing.domInteractive - timing.domLoading
                };
            }
        """)
        
        dom_loaded = performance_data.get("domContentLoaded", 0)
        assert dom_loaded < 3000, f"DOM内容加载时间 {dom_loaded}ms 超过3秒阈值"
    
    @pytest.mark.performance
    def test_first_paint_time(self, home_page: HomePage):
        """测试首次绘制时间"""
        home_page.navigate()
        
        first_paint = home_page.execute_js("""
            () => {
                const entries = performance.getEntriesByType('paint');
                const firstPaint = entries.find(e => e.name === 'first-paint');
                return firstPaint ? firstPaint.startTime : 0;
            }
        """)
        
        if first_paint:
            assert first_paint < 2000, f"首次绘制时间 {first_paint:.2f}ms 超过2秒阈值"
    
    @pytest.mark.performance
    def test_first_contentful_paint(self, home_page: HomePage):
        """测试首次内容绘制（FCP）"""
        home_page.navigate()
        
        fcp = home_page.execute_js("""
            () => {
                const navigation = performance.getEntriesByType('navigation')[0];
                return navigation ? navigation.firstContentfulPaint : 0;
            }
        """)
        
        if fcp:
            # 阈值：1.5秒
            assert fcp < 1500, f"首次内容绘制时间 {fcp:.2f}ms 超过1.5秒阈值"
    
    @pytest.mark.performance
    def test_largest_contentful_paint(self, home_page: HomePage):
        """测试最大内容绘制（LCP）"""
        home_page.navigate()
        
        lcp = home_page.execute_js("""
            () => {
                try {
                    const navigation = performance.getEntriesByType('navigation')[0];
                    return navigation ? navigation.largestContentfulPaint : 0;
                } catch (e) {
                    return 0;
                }
            }
        """)
        
        if lcp:
            # 阈值：2.5秒
            assert lcp < 2500, f"最大内容绘制时间 {lcp:.2f}ms 超过2.5秒阈值"
    
    @pytest.mark.performance
    def test_time_to_interactive(self, home_page: HomePage):
        """测试可交互时间（TTI）"""
        home_page.navigate()
        
        tti = home_page.execute_js("""
            () => {
                try {
                    const navigation = performance.getEntriesByType('navigation')[0];
                    return navigation ? navigation.interactive : 0;
                } catch (e) {
                    return 0;
                }
            }
        """)
        
        if tti:
            # 阈值：3秒
            assert tti < 3000, f"可交互时间 {tti:.2f}ms 超过3秒阈值"
    
    @pytest.mark.performance
    def test_page_load_performance_metrics(self, home_page: HomePage):
        """测试页面加载性能指标"""
        home_page.navigate()
        performance = home_page.verify_page_performance()
        
        # 验证关键指标
        if performance.get("pageLoadTime"):
            assert performance["pageLoadTime"] < 5000
        if performance.get("domContentLoaded"):
            assert performance["domContentLoaded"] < 3000
    
    @pytest.mark.performance
    def test_network_timing(self, home_page: HomePage):
        """测试网络时序"""
        home_page.navigate()
        
        timing = home_page.execute_js("""
            () => {
                const timing = performance.timing;
                return {
                    dnsLookup: timing.domainLookupEnd - timing.domainLookupStart,
                    tcpConnection: timing.connectEnd - timing.connectStart,
                    serverResponse: timing.responseEnd - timing.requestStart,
                    domProcessing: timing.domLoading - timing.responseEnd
                };
            }
        """)
        
        # DNS查询时间
        assert timing.get("dnsLookup", 0) < 500, \
            f"DNS查询时间 {timing.get('dnsLookup')}ms 超过500ms阈值"
        
        # TCP连接时间
        assert timing.get("tcpConnection", 0) < 500, \
            f"TCP连接时间 {timing.get('tcpConnection')}ms 超过500ms阈值"
        
        # 服务器响应时间
        assert timing.get("serverResponse", 0) < 1000, \
            f"服务器响应时间 {timing.get('serverResponse')}ms 超过1秒阈值"
    
    @pytest.mark.performance
    def test_resource_timing(self, home_page: HomePage):
        """测试资源加载时序"""
        home_page.navigate()
        
        resources = home_page.execute_js("""
            () => {
                const entries = performance.getEntriesByType('resource');
                const scripts = entries.filter(e => e.initiatorType === 'script');
                const styles = entries.filter(e => e.initiatorType === 'css');
                
                return {
                    totalResources: entries.length,
                    scriptCount: scripts.length,
                    styleCount: styles.length,
                    totalDuration: entries.reduce((sum, e) => sum + e.duration, 0)
                };
            }
        """)
        
        assert resources.get("totalResources", 0) > 0, "未检测到资源加载"
        
        home_page.logger.info(
            f"资源统计: 共{resources.get('totalResources')}个资源，"
            f"脚本{resources.get('scriptCount')}个，"
            f"样式{resources.get('styleCount')}个"
        )
    
    @pytest.mark.performance
    def test_form_submission_time(self, contact_page: ContactPage, test_data_generator):
        """测试表单提交时间"""
        contact_page.navigate()
        
        data = test_data_generator.generate_contact_form_data(use_valid=True)
        
        start_time = time.time()
        
        contact_page.fill_contact_form(data)
        contact_page.submit_form()
        
        try:
            contact_page.verify_form_submission_success()
        except Exception:
            pass
        
        end_time = time.time()
        duration = (end_time - start_time) * 1000
        
        # 阈值：5秒
        assert duration < 5000, f"表单提交耗时 {duration:.2f}ms 超过5秒阈值"
    
    @pytest.mark.performance
    def test_scroll_performance(self, home_page: HomePage):
        """测试滚动性能"""
        home_page.navigate()
        
        # 执行多次滚动
        scroll_times = []
        for i in range(5):
            start_time = time.time()
            home_page.scroll_to_bottom()
            home_page.scroll_to_top()
            end_time = time.time()
            scroll_times.append((end_time - start_time) * 1000)
        
        avg_scroll_time = sum(scroll_times) / len(scroll_times)
        
        # 平均滚动时间应该在1秒内
        assert avg_scroll_time < 1000, f"平均滚动时间 {avg_scroll_time:.2f}ms 超过1秒阈值"
    
    @pytest.mark.performance
    def test_element_visibility_performance(self, home_page: HomePage):
        """测试元素可见性检查性能"""
        home_page.navigate()
        
        elements = [
            "header",
            "#home",
            "#about",
            "#services",
            "#products",
            "#news",
            "#contact",
            "footer"
        ]
        
        check_times = []
        for element in elements:
            start_time = time.time()
            try:
                home_page._is_visible(element)
            except Exception:
                pass
            end_time = time.time()
            check_times.append((end_time - start_time) * 1000)
        
        avg_check_time = sum(check_times) / len(check_times)
        
        # 单个元素检查时间应该在500ms内
        assert avg_check_time < 500, f"平均元素检查时间 {avg_check_time:.2f}ms 超过500ms阈值"
    
    @pytest.mark.performance
    def test_navigation_performance(self, home_page: HomePage, contact_page: ContactPage):
        """测试导航性能"""
        # 测量导航到联系页面的时间
        start_time = time.time()
        contact_page.navigate()
        contact_page.wait_for_load()
        end_time = time.time()
        
        nav_time = (end_time - start_time) * 1000
        
        # 阈值：3秒
        assert nav_time < 3000, f"导航时间 {nav_time:.2f}ms 超过3秒阈值"
    
    @pytest.mark.performance
    @pytest.mark.responsive
    def test_performance_across_viewports(self, home_page: HomePage):
        """测试不同视口下的性能"""
        viewports = [
            (375, 667, "移动端"),
            (768, 1024, "平板端"),
            (1920, 1080, "桌面端")
        ]
        
        results = []
        for width, height, name in viewports:
            home_page.page.set_viewport_size({"width": width, "height": height})
            
            start_time = time.time()
            home_page.navigate()
            home_page.wait_for_load()
            end_time = time.time()
            
            load_time = (end_time - start_time) * 1000
            results.append((name, load_time))
            
            home_page.logger.info(f"{name} ({width}x{height}): {load_time:.2f}ms")
        
        # 验证所有视口加载时间在阈值内
        for name, load_time in results:
            assert load_time < 5000, f"{name}加载时间 {load_time:.2f}ms 超过5秒阈值"
