"""
性能监控和基准测试
"""
import asyncio
import time
from typing import Dict, Any, List, Callable
from datetime import datetime
from loguru import logger


class PerformanceMonitor:
    """
    性能监控器
    监控页面性能指标
    """

    def __init__(self):
        self.metrics: List[Dict[str, Any]] = []

    async def monitor_page(self, page, interval: float = 1.0, duration: float = 60):
        """
        监控页面性能

        Args:
            page: 页面对象
            interval: 监控间隔
            duration: 监控时长
        """
        start_time = time.time()

        while time.time() - start_time < duration:
            try:
                # 获取性能指标
                metrics = await page.evaluate("""
                    () => ({
                        timestamp: Date.now(),
                        memory: performance.memory ? {
                            usedJSHeapSize: performance.memory.usedJSHeapSize,
                            totalJSHeapSize: performance.memory.totalJSHeapSize,
                        } : null,
                        timing: {
                            domContentLoaded: performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart,
                            load: performance.timing.loadEventEnd - performance.timing.navigationStart,
                        },
                        resources: performance.getEntriesByType('resource').length,
                    })
                """)

                self.metrics.append(metrics)

            except Exception as e:
                logger.warning(f"获取性能指标失败: {e}")

            await asyncio.sleep(interval)

    def get_summary(self) -> Dict[str, Any]:
        """获取性能摘要"""
        if not self.metrics:
            return {}

        memory_samples = [m["memory"]["usedJSHeapSize"] for m in self.metrics if m.get("memory")]

        return {
            "samples": len(self.metrics),
            "avg_memory_mb": sum(memory_samples) / len(memory_samples) / 1048576 if memory_samples else 0,
            "max_memory_mb": max(memory_samples) / 1048576 if memory_samples else 0,
            "min_memory_mb": min(memory_samples) / 1048576 if memory_samples else 0,
        }

    def export_report(self, filepath: str):
        """导出报告"""
        import json

        report = {
            "metrics": self.metrics,
            "summary": self.get_summary(),
            "exported_at": datetime.now().isoformat(),
        }

        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)

        logger.info(f"性能报告已导出: {filepath}")

    def get_memory_trend(self) -> List[float]:
        """获取内存趋势"""
        return [
            m["memory"]["usedJSHeapSize"] / 1048576
            for m in self.metrics
            if m.get("memory")
        ]

    def clear(self):
        """清空监控数据"""
        self.metrics.clear()


class Benchmark:
    """
    基准测试
    对比不同实现或配置的性能
    """

    def __init__(self):
        self.results: Dict[str, List[float]] = {}

    async def run(
        self,
        name: str,
        task: Callable,
        iterations: int = 10,
    ) -> Dict[str, Any]:
        """
        运行基准测试

        Args:
            name: 测试名称
            task: 测试任务
            iterations: 迭代次数

        Returns:
            Dict: 测试结果
        """
        durations = []

        for i in range(iterations):
            start = time.time()

            try:
                if asyncio.iscoroutinefunction(task):
                    await task()
                else:
                    task()

                duration = (time.time() - start) * 1000
                durations.append(duration)

            except Exception as e:
                logger.error(f"基准测试失败: {e}")

        if durations:
            result = {
                "name": name,
                "iterations": iterations,
                "avg_ms": sum(durations) / len(durations),
                "min_ms": min(durations),
                "max_ms": max(durations),
                "total_ms": sum(durations),
            }

            self.results[name] = durations

            return result

        return {"name": name, "error": "all iterations failed"}

    def compare(self, *names) -> Dict[str, Any]:
        """比较多个基准测试结果"""
        if not names:
            names = list(self.results.keys())

        comparison = {
            "names": names,
            "averages": {},
            "fastest": None,
            "slowest": None,
        }

        for name in names:
            if name in self.results:
                avg = sum(self.results[name]) / len(self.results[name])
                comparison["averages"][name] = avg

        if comparison["averages"]:
            comparison["fastest"] = min(comparison["averages"], key=comparison["averages"].get)
            comparison["slowest"] = max(comparison["averages"], key=comparison["averages"].get)

        return comparison

    def get_percentile(self, name: str, percentile: float = 95) -> float:
        """获取百分位数值"""
        if name not in self.results:
            return 0

        sorted_results = sorted(self.results[name])
        index = int(len(sorted_results) * percentile / 100)
        return sorted_results[min(index, len(sorted_results) - 1)]

    def summary(self) -> Dict[str, Dict[str, float]]:
        """获取所有基准测试摘要"""
        summary = {}
        for name, durations in self.results.items():
            if durations:
                summary[name] = {
                    "avg_ms": sum(durations) / len(durations),
                    "min_ms": min(durations),
                    "max_ms": max(durations),
                    "p95_ms": self.get_percentile(name, 95),
                }
        return summary

    def clear(self):
        """清空测试结果"""
        self.results.clear()
