#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
标准时效性审查器 - 基于内存匹配规则

使用 StandardMatchingService 替代原有的向量搜索+LLM判断方式，
提供更快速、准确的标准时效性审查功能。

使用示例:
    # 方法1: 使用便捷函数
    from foundation.infrastructure.mysql.async_mysql_conn_pool import AsyncMySQLPool

    db_pool = AsyncMySQLPool()
    await db_pool.initialize()

    results = await review_standards_timeliness(
        standards_list=[
            {"standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017"},
            {"standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2016"},
        ],
        db_pool=db_pool
    )

    # 方法2: 使用异步上下文管理器
    async with StandardTimelinessReviewer(db_pool=db_pool) as reviewer:
        results = reviewer.review_standards(standards_list)
"""
import asyncio
from typing import List, Dict, Any, Optional
from dataclasses import dataclass, asdict

from foundation.observability.logger.loggering import review_logger as logger
from core.construction_review.component.standard_matching import (
    StandardMatchingService,
    StandardMatchResult,
    MatchResultCode,
)


@dataclass
class TimelinessReviewResult:
    """时效性审查结果"""
    seq_no: int                              # 序号
    standard_name: str                       # 原始标准名称
    standard_number: str                     # 原始标准号
    process_result: str                      # 处理结果
    status_code: str                         # 状态码
    has_issue: bool                          # 是否有问题
    issue_type: Optional[str] = None         # 问题类型
    suggestion: Optional[str] = None         # 建议
    reason: Optional[str] = None             # 原因
    risk_level: str = "low"                  # 风险等级（与原有逻辑一致：low/high）
    replacement_name: Optional[str] = None   # 替代标准名称
    replacement_number: Optional[str] = None # 替代标准号
    final_result: Optional[str] = None       # 最终结果描述

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return asdict(self)


class StandardTimelinessReviewer:
    """
    标准时效性审查器

    基于 StandardMatchingService 提供的内存匹配功能，
    对标准列表进行时效性审查。
    """

    def __init__(self, db_pool=None, standard_service: Optional[StandardMatchingService] = None):
        """
        初始化审查器

        Args:
            db_pool: 数据库连接池，用于初始化 StandardMatchingService（如未提供standard_service则必填）
            standard_service: 已初始化的 StandardMatchingService 实例（优先级高于 db_pool）

        Raises:
            RuntimeError: 当db_pool和standard_service都为None时抛出异常
        """
        if standard_service is None and not db_pool:
            raise RuntimeError(
                "StandardTimelinessReviewer 初始化失败: 必须提供数据库连接池(db_pool)或已初始化的StandardMatchingService实例。\n"
                "Mock模式已取消，请确保数据库连接正常。"
            )
        self.db_pool = db_pool
        self._service = standard_service
        self._own_service = False  # 标记是否由本实例创建 service

    async def __aenter__(self):
        """异步上下文管理器入口"""
        if self._service is None:
            # own_db_pool=False 因为 db_pool 是外部传入的，不应该由本服务关闭
            self._service = StandardMatchingService(self.db_pool, own_db_pool=False)
            await self._service.initialize()
            self._own_service = True
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """异步上下文管理器出口"""
        if self._own_service and self._service:
            await self._service.close()
        return False

    def review_standards(self, standards: List[Dict[str, str]]) -> List[TimelinessReviewResult]:
        """
        审查标准列表的时效性

        Args:
            standards: 标准列表，每个元素包含:
                - standard_name: 标准名称
                - standard_number: 标准号

        Returns:
            List[TimelinessReviewResult]: 审查结果列表
        """
        if not self._service:
            raise RuntimeError("服务未初始化，请使用异步上下文管理器或调用 initialize()")

        # 使用 StandardMatchingService 进行匹配
        match_results = self._service.check_standards(standards)

        # 转换为时效性审查结果
        review_results = []
        for match_result in match_results:
            review_result = self._convert_match_to_review_result(match_result)
            review_results.append(review_result)

        return review_results

    def review_single(self, standard_name: str, standard_number: str, seq_no: int = 1) -> TimelinessReviewResult:
        """
        审查单个标准的时效性

        Args:
            standard_name: 标准名称
            standard_number: 标准号
            seq_no: 序号

        Returns:
            TimelinessReviewResult: 审查结果
        """
        if not self._service:
            raise RuntimeError("服务未初始化，请使用异步上下文管理器或调用 initialize()")

        match_result = self._service.check_single(seq_no, standard_name, standard_number)
        return self._convert_match_to_review_result(match_result)

    def _convert_match_to_review_result(self, match_result: StandardMatchResult) -> TimelinessReviewResult:
        """
        将匹配结果转换为时效性审查结果

        Args:
            match_result: 标准匹配结果

        Returns:
            TimelinessReviewResult: 时效性审查结果
        """
        # 根据状态码确定是否有问题和风险等级
        status_code = match_result.status_code

        if status_code == MatchResultCode.OK.value:
            # 正常状态 - 无风险
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result=match_result.process_result,
                status_code=status_code,
                has_issue=False,
                risk_level="low",
                final_result=match_result.final_result
            )

        elif status_code == MatchResultCode.SUBSTITUTED.value:
            # 被替代 - high（与原有逻辑一致）
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result=match_result.process_result,
                status_code=status_code,
                has_issue=True,
                issue_type="标准被替代",
                suggestion=f"请更新为现行标准: {match_result.substitute_name}{match_result.substitute_number}",
                reason=match_result.final_result,
                risk_level="high",
                replacement_name=match_result.substitute_name,
                replacement_number=match_result.substitute_number,
                final_result=match_result.final_result
            )

        elif status_code == MatchResultCode.ABOLISHED.value:
            # 废止无替代 - high（与原有逻辑一致）
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result=match_result.process_result,
                status_code=status_code,
                has_issue=True,
                issue_type="标准已废止",
                suggestion="该标准已废止且无现行替代，请检查是否仍需引用或寻找其他替代方案",
                reason=match_result.final_result,
                risk_level="high",
                final_result=match_result.final_result
            )

        elif status_code == MatchResultCode.MISMATCH.value:
            # 不匹配 - high（与原有逻辑一致：编号错误属于high）
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result=match_result.process_result,
                status_code=status_code,
                has_issue=True,
                issue_type="标准信息不匹配",
                suggestion=f"名称与标准号不匹配，实际应为: {match_result.substitute_name}{match_result.substitute_number}",
                reason=match_result.final_result,
                risk_level="high",
                replacement_name=match_result.substitute_name,
                replacement_number=match_result.substitute_number,
                final_result=match_result.final_result
            )

        elif status_code == MatchResultCode.NOT_FOUND.value:
            # 标准库不存在 - 直接过滤，不返回问题
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result=match_result.process_result,
                status_code=status_code,
                has_issue=False,
                risk_level="low",
                final_result=match_result.final_result
            )

        else:
            # 未知状态
            logger.warning(f"未知的匹配状态码: {status_code}")
            return TimelinessReviewResult(
                seq_no=match_result.seq_no,
                standard_name=match_result.original_name,
                standard_number=match_result.original_number,
                process_result="未知",
                status_code=status_code,
                has_issue=True,
                issue_type="未知状态",
                reason=match_result.final_result,
                risk_level="medium",
                final_result=match_result.final_result
            )

    def convert_to_standardized_format(
        self,
        review_results: List[TimelinessReviewResult],
        check_item: str = "timeliness_check",
        chapter_code: str = "basis",
        check_item_code: str = "standard_timeliness_check"
    ) -> List[Dict[str, Any]]:
        """
        将审查结果转换为标准格式（兼容原有审查系统）

        Args:
            review_results: 审查结果列表
            check_item: 检查项名称
            chapter_code: 章节代码
            check_item_code: 检查项代码

        Returns:
            List[Dict[str, Any]]: 标准格式的审查结果
        """
        standardized_results = []

        for result in review_results:
            # 标准库不存在或无问题的结果直接过滤，不返回
            if result.status_code == MatchResultCode.NOT_FOUND.value or not result.has_issue:
                continue
            else:
                # 有问题
                standardized_results.append({
                    "check_item": check_item,
                    "chapter_code": chapter_code,
                    "check_item_code": check_item_code,
                    "check_result": {
                        "location": f"《{result.standard_name}》（{result.standard_number}）",
                        "description": result.reason or result.final_result,
                        "suggestion": result.suggestion,
                        "issue_type": result.issue_type,
                        "standard_name": result.standard_name,
                        "standard_number": result.standard_number,
                        "replacement_name": result.replacement_name,
                        "replacement_number": result.replacement_number,
                    },
                    "exist_issue": True,
                    "risk_info": {"risk_level": result.risk_level}
                })

        return standardized_results


# ========== 便捷函数 ==========

async def review_standards_timeliness(
    standards_list: List[Dict[str, str]],
    db_pool=None,
    standard_service: Optional[StandardMatchingService] = None
) -> List[TimelinessReviewResult]:
    """
    审查标准列表时效性的便捷函数

    Args:
        standards_list: 标准列表，每个元素包含 standard_name 和 standard_number
        db_pool: 数据库连接池
        standard_service: 已初始化的 StandardMatchingService 实例（优先级高于 db_pool）

    Returns:
        List[TimelinessReviewResult]: 审查结果列表

    示例:
        results = await review_standards_timeliness(
            standards_list=[
                {"standard_name": "铁路桥涵设计规范", "standard_number": "TB 10002-2017"},
                {"standard_name": "起重机 钢丝绳 保养、维护、检验和报废", "standard_number": "GB/T 5972-2016"},
            ],
            db_pool=db_pool
        )
    """
    async with StandardTimelinessReviewer(db_pool=db_pool, standard_service=standard_service) as reviewer:
        return reviewer.review_standards(standards_list)


async def review_standard_timeliness_with_standardized_output(
    standards_list: List[Dict[str, str]],
    db_pool=None,
    standard_service: Optional[StandardMatchingService] = None,
    check_item: str = "timeliness_check",
    chapter_code: str = "basis",
    check_item_code: str = "standard_timeliness_check"
) -> List[Dict[str, Any]]:
    """
    审查标准列表时效性并输出标准格式的便捷函数

    Args:
        standards_list: 标准列表
        db_pool: 数据库连接池
        standard_service: 已初始化的 StandardMatchingService 实例
        check_item: 检查项名称
        chapter_code: 章节代码
        check_item_code: 检查项代码

    Returns:
        List[Dict[str, Any]]: 标准格式的审查结果
    """
    async with StandardTimelinessReviewer(db_pool=db_pool, standard_service=standard_service) as reviewer:
        review_results = reviewer.review_standards(standards_list)
        return reviewer.convert_to_standardized_format(
            review_results, check_item, chapter_code, check_item_code
        )
