"""
上下文监控器（重复调用检测）
==========================

从 `LlmCallback.performance_monitor` 中读取工具调用记录，
通过规则引擎检测 duplicate_calls，并返回去重后的告警列表。
"""
import time
from dataclasses import dataclass
from typing import List, Set, TYPE_CHECKING

import logging
logger = logging.getLogger(__name__)

from ..monitoring.llm_callback import LlmCallback


@dataclass
class Warning:
    """
    上下文感知告警对象（当前仅用于重复调用 duplicate_calls）。
    """

    warning_id: str
    """唯一标识符（用于去重）"""

    warning_type: str
    """警告类型：当前仅使用 duplicate_calls"""

    severity: str
    """严重程度：info / warning / critical"""

    message: str
    """给 LLM 的告警文案"""

    timestamp: float
    """警告生成时间戳"""

    details: dict = None
    """详细信息（可选，用于调试）"""

    def __post_init__(self):
        """初始化后验证"""
        # 验证 severity
        valid_severities = {"info", "warning", "critical"}
        if self.severity not in valid_severities:
            raise ValueError(
                f"Invalid severity: {self.severity}. "
                f"Must be one of {valid_severities}"
            )

        # 验证 warning_type（当前只支持 duplicate_calls）
        valid_types = {"duplicate_calls"}
        if self.warning_type not in valid_types:
            logger.warning(
                f"Unknown warning_type: {self.warning_type}. "
                f"Expected one of {valid_types}"
            )

        # 初始化 details
        if self.details is None:
            self.details = {}

    def __str__(self) -> str:
        """字符串表示"""
        return f"[{self.severity.upper()}] {self.warning_type}: {self.message}"

    def __repr__(self) -> str:
        """调试表示"""
        return (
            f"Warning(id={self.warning_id}, "
            f"type={self.warning_type}, "
            f"severity={self.severity})"
        )

    def to_dict(self) -> dict:
        """转换为字典（用于序列化）"""
        return {
            "warning_id": self.warning_id,
            "warning_type": self.warning_type,
            "severity": self.severity,
            "message": self.message,
            "timestamp": self.timestamp,
            "details": self.details
        }


class ContextMonitor:
    """上下文监控器，只负责检测重复调用告警并做去重。"""

    def __init__(
        self,
        callback: 'LlmCallback',
    ):
        """初始化监控器。"""
        self.callback = callback

        # 唯一的状态：已发出的警告（用于去重）
        self.warnings_issued: Set[str] = set()

        # 延迟导入 RuleEngine（避免循环导入）
        from langchain_agentx.middleware.context_rule_engine import RuleEngine
        self.rule_engine = RuleEngine()

        logger.info("ContextMonitor initialized | duplicate_calls=True")

    def detect(self) -> List[Warning]:
        """执行检测并返回新的告警列表（基于 warning_id 去重）。"""
        # 1. 检查 performance_monitor 是否存在
        if not hasattr(self.callback, 'performance_monitor'):
            logger.warning("Callback does not have performance_monitor")
            return []

        perf_monitor = self.callback.performance_monitor
        if perf_monitor is None:
            logger.warning("Callback.performance_monitor is None")
            return []

        # 2. 读取数据
        tool_records = perf_monitor.records  # List[ToolCallRecord]

        # 如果没有工具调用，直接返回
        if not tool_records:
            logger.debug("No tool calls to analyze")
            return []

        # 计算统计指标
        try:
            metrics = perf_monitor.calculate_metrics()
        except Exception as e:
            logger.error(f"Failed to calculate metrics: {e}", exc_info=True)
            return []

        # 3. 执行规则检测
        try:
            all_warnings = self.rule_engine.check(tool_records, metrics)
        except Exception as e:
            logger.error(f"Failed to check rules: {e}", exc_info=True)
            return []

        # 4. 过滤已发出的警告
        new_warnings = [
            w for w in all_warnings
            if w.warning_id not in self.warnings_issued
        ]

        # 5. 记录已发出的警告
        for w in new_warnings:
            self.warnings_issued.add(w.warning_id)

        if new_warnings:
            logger.info(
                f"Detected {len(new_warnings)} new warnings | "
                f"types={[w.warning_type for w in new_warnings]}"
            )

        return new_warnings

    def reset(self) -> None:
        """重置监控器状态（清空已发出的告警 ID）。"""
        self.warnings_issued.clear()
        logger.info("ContextMonitor state reset")

    def get_issued_warning_ids(self) -> Set[str]:
        """获取已发出的告警 ID 集合（只读拷贝）。"""
        return self.warnings_issued.copy()


# 便捷函数
def create_monitor(
    callback: 'LlmCallback',
    config_path: str | None = None
) -> ContextMonitor:
    """创建监控器（便捷函数，config_path 已废弃，仅保留兼容参数）。"""
    if config_path is not None:
        logger.warning(
            "create_monitor(config_path=...) 已废弃，"
            "上下文感知配置现由内部默认值管理（仅保留重复调用检测）。"
        )

    return ContextMonitor(callback)

