"""
错误分析器
智能错误分析，提供修复建议
"""
import re
from dataclasses import dataclass, field
from typing import Optional, List, Dict, Literal
from playwright.async_api import Page
from loguru import logger

from .console_monitor import ConsoleLogEntry


Severity = Literal["low", "medium", "high", "critical"]


@dataclass
class ErrorLocation:
    """错误位置"""
    url: str
    line: int
    column: int = 0


@dataclass
class ErrorAnalysisResult:
    """错误分析结果"""
    type: str
    message: str
    possible_causes: List[str] = field(default_factory=list)
    suggestions: List[str] = field(default_factory=list)
    severity: Severity = "medium"
    references: List[str] = field(default_factory=list)
    location: Optional[ErrorLocation] = None


# 已知错误模式库
ERROR_PATTERNS = [
    {
        "pattern": re.compile(r"Cannot read propert(?:y|ies) of undefined"),
        "type": "TypeError",
        "causes": [
            "访问了未定义对象的属性",
            "异步数据尚未加载完成",
            "选择器未找到对应元素",
        ],
        "suggestions": [
            "添加空值检查 (?. 操作符)",
            "使用 waitFor 等待元素出现",
            "检查选择器是否正确",
            "确保异步操作已完成",
        ],
        "severity": "high",
        "references": [
            "https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Errors/Cant_access_property",
        ],
    },
    {
        "pattern": re.compile(r"Cannot read propert(?:y|ies) of null"),
        "type": "TypeError",
        "causes": [
            "元素不存在时尝试访问属性",
            "DOM 元素已被移除",
            "选择器匹配到空结果",
        ],
        "suggestions": [
            "添加 null 检查",
            "使用可选链操作符 (?.)",
            "等待元素附加到 DOM",
        ],
        "severity": "high",
        "references": [],
    },
    {
        "pattern": re.compile(r"is not a function"),
        "type": "TypeError",
        "causes": [
            "调用了不存在的方法",
            "方法名拼写错误",
            "对象类型与预期不符",
        ],
        "suggestions": [
            "检查方法名是否正确",
            "确认对象类型",
            "查看 API 文档确认方法存在",
        ],
        "severity": "high",
        "references": [],
    },
    {
        "pattern": re.compile(r"is not defined"),
        "type": "ReferenceError",
        "causes": [
            "变量未声明",
            "变量名拼写错误",
            "作用域问题",
        ],
        "suggestions": [
            "检查变量是否已声明",
            "确认变量名拼写正确",
            "检查变量作用域",
        ],
        "severity": "high",
        "references": [],
    },
    {
        "pattern": re.compile(r"Failed to fetch"),
        "type": "NetworkError",
        "causes": [
            "网络请求失败",
            "CORS 策略限制",
            "服务器无响应",
        ],
        "suggestions": [
            "检查网络连接",
            "确认 API 地址正确",
            "检查 CORS 配置",
            "添加错误处理和重试逻辑",
        ],
        "severity": "medium",
        "references": [
            "https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS",
        ],
    },
    {
        "pattern": re.compile(r"NetworkError|ERR_CONNECTION_REFUSED|ERR_NAME_NOT_RESOLVED"),
        "type": "NetworkError",
        "causes": [
            "网络连接问题",
            "DNS 解析失败",
            "服务器不可达",
        ],
        "suggestions": [
            "检查网络连接",
            "确认 URL 正确",
            "检查防火墙设置",
        ],
        "severity": "critical",
        "references": [],
    },
    {
        "pattern": re.compile(r"Unexpected token"),
        "type": "SyntaxError",
        "causes": [
            "JSON 解析错误",
            "JavaScript 语法错误",
            "响应格式不正确",
        ],
        "suggestions": [
            "检查 JSON 格式",
            "使用 try-catch 包裹 JSON.parse",
            "验证 API 响应格式",
        ],
        "severity": "medium",
        "references": [],
    },
    {
        "pattern": re.compile(r"timeout|Timeout|TimeoutError"),
        "type": "TimeoutError",
        "causes": [
            "操作超时",
            "页面加载缓慢",
            "元素等待超时",
        ],
        "suggestions": [
            "增加超时时间",
            "优化页面加载性能",
            "检查元素是否存在",
        ],
        "severity": "medium",
        "references": [],
    },
    {
        "pattern": re.compile(r"CORS|Cross-Origin"),
        "type": "CORSError",
        "causes": [
            "跨域请求被阻止",
            "服务器未配置 CORS 头",
        ],
        "suggestions": [
            "配置服务器 CORS 响应头",
            "使用代理服务器",
            "在开发环境禁用 CORS 检查",
        ],
        "severity": "medium",
        "references": [
            "https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS",
        ],
    },
    {
        "pattern": re.compile(r"401|Unauthorized"),
        "type": "AuthError",
        "causes": [
            "未登录或登录过期",
            "认证信息不正确",
        ],
        "suggestions": [
            "检查登录状态",
            "刷新认证 Token",
            "重新登录",
        ],
        "severity": "high",
        "references": [],
    },
    {
        "pattern": re.compile(r"403|Forbidden"),
        "type": "PermissionError",
        "causes": [
            "无访问权限",
            "权限不足",
        ],
        "suggestions": [
            "检查用户权限",
            "联系管理员获取权限",
        ],
        "severity": "medium",
        "references": [],
    },
    {
        "pattern": re.compile(r"404|Not Found"),
        "type": "NotFoundError",
        "causes": [
            "资源不存在",
            "URL 地址错误",
            "资源已被删除",
        ],
        "suggestions": [
            "检查 URL 是否正确",
            "确认资源是否存在",
        ],
        "severity": "low",
        "references": [],
    },
    {
        "pattern": re.compile(r"500|Internal Server Error"),
        "type": "ServerError",
        "causes": [
            "服务器内部错误",
            "后端代码异常",
        ],
        "suggestions": [
            "联系后端开发人员",
            "查看服务器日志",
        ],
        "severity": "critical",
        "references": [],
    },
]


class ErrorAnalyzer:
    """
    错误分析器
    智能分析错误并提供修复建议
    """

    def __init__(self, page: Page):
        self.page = page
        self._errors: List[ConsoleLogEntry] = []
        self._analysis_results: List[ErrorAnalysisResult] = []

    def analyze(self, error: ConsoleLogEntry | str) -> ErrorAnalysisResult:
        """
        分析错误

        Args:
            error: 错误对象或错误消息

        Returns:
            ErrorAnalysisResult: 分析结果
        """
        message = error.message if isinstance(error, ConsoleLogEntry) else error
        log_entry = error if isinstance(error, ConsoleLogEntry) else None

        # 查找匹配的错误模式
        for pattern_config in ERROR_PATTERNS:
            if pattern_config["pattern"].search(message):
                result = ErrorAnalysisResult(
                    type=pattern_config["type"],
                    message=message,
                    possible_causes=list(pattern_config["causes"]),
                    suggestions=list(pattern_config["suggestions"]),
                    severity=pattern_config["severity"],
                    references=list(pattern_config["references"]),
                )

                if log_entry and log_entry.url:
                    result.location = ErrorLocation(
                        url=log_entry.url,
                        line=log_entry.line_number or 0,
                        column=log_entry.column_number or 0,
                    )

                return result

        # 未知错误类型
        return ErrorAnalysisResult(
            type="UnknownError",
            message=message,
            possible_causes=["未知错误类型，需要进一步分析"],
            suggestions=[
                "检查错误堆栈信息",
                "搜索错误消息寻找解决方案",
                "在相关社区寻求帮助",
            ],
            severity="medium",
            references=[],
        )

    def analyze_all(self, errors: List[ConsoleLogEntry]) -> List[ErrorAnalysisResult]:
        """批量分析错误"""
        return [self.analyze(error) for error in errors]

    def add_error(self, error: ConsoleLogEntry) -> None:
        """添加错误到分析队列"""
        self._errors.append(error)
        self._analysis_results.append(self.analyze(error))

    def get_results(self) -> List[ErrorAnalysisResult]:
        """获取所有分析结果"""
        return list(self._analysis_results)

    def get_by_severity(self, severity: Severity) -> List[ErrorAnalysisResult]:
        """获取指定严重程度的错误"""
        return [r for r in self._analysis_results if r.severity == severity]

    def get_critical_errors(self) -> List[ErrorAnalysisResult]:
        """获取严重错误"""
        return self.get_by_severity("critical")

    def get_high_priority_errors(self) -> List[ErrorAnalysisResult]:
        """获取高优先级错误"""
        return self.get_by_severity("high")

    def clear(self) -> None:
        """清空分析结果"""
        self._errors = []
        self._analysis_results = []

    def print_report(self) -> None:
        """打印分析报告"""
        print("\n=== 错误分析报告 ===")
        print(f"总错误数: {len(self._analysis_results)}")

        by_severity = {
            "critical": len(self.get_by_severity("critical")),
            "high": len(self.get_by_severity("high")),
            "medium": len(self.get_by_severity("medium")),
            "low": len(self.get_by_severity("low")),
        }

        print(f"  - 严重: {by_severity['critical']}")
        print(f"  - 高: {by_severity['high']}")
        print(f"  - 中: {by_severity['medium']}")
        print(f"  - 低: {by_severity['low']}")

        if self._analysis_results:
            print("\n错误详情:")
            for i, result in enumerate(self._analysis_results, 1):
                print(f"\n{i}. [{result.severity.upper()}] {result.type}")
                print(f"   消息: {result.message}")
                if result.location:
                    print(f"   位置: {result.location.url}:{result.location.line}")
                print("   可能原因:")
                for cause in result.possible_causes:
                    print(f"     - {cause}")
                print("   修复建议:")
                for suggestion in result.suggestions:
                    print(f"     - {suggestion}")

    def export_json(self) -> str:
        """导出分析报告为 JSON"""
        import json

        return json.dumps({
            "total": len(self._analysis_results),
            "by_severity": {
                "critical": len(self.get_by_severity("critical")),
                "high": len(self.get_by_severity("high")),
                "medium": len(self.get_by_severity("medium")),
                "low": len(self.get_by_severity("low")),
            },
            "results": [
                {
                    "type": r.type,
                    "message": r.message,
                    "severity": r.severity,
                    "possible_causes": r.possible_causes,
                    "suggestions": r.suggestions,
                    "location": {
                        "url": r.location.url,
                        "line": r.location.line,
                        "column": r.location.column,
                    } if r.location else None,
                }
                for r in self._analysis_results
            ],
        }, ensure_ascii=False, indent=2)

    def import_from_monitor(self, monitor) -> None:
        """从控制台监控器导入错误"""
        errors = monitor.get_errors()
        for error in errors:
            self.add_error(error)

    async def quick_analyze(self, wait_time: float = 1.0) -> List[ErrorAnalysisResult]:
        """
        快速分析页面错误

        Args:
            wait_time: 等待时间（秒）

        Returns:
            List[ErrorAnalysisResult]: 分析结果列表
        """
        errors: List[ConsoleLogEntry] = []

        def error_handler(error: Exception):
            errors.append(ConsoleLogEntry(
                level="error",
                message=str(error),
            ))

        self.page.on("pageerror", error_handler)

        # 等待一段时间收集错误
        await asyncio.sleep(wait_time)

        self.page.remove_listener("pageerror", error_handler)

        return self.analyze_all(errors)


import asyncio


def create_error_analyzer(page: Page) -> ErrorAnalyzer:
    """创建错误分析器实例"""
    return ErrorAnalyzer(page)
