#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
CSV加载器 + 关键词映射
"""

import csv
from pathlib import Path
from typing import Dict, List, Optional

from .models import CategoryStandard, SecondCategoryStandard


# ==================== 二级分类关键词映射 ====================
# 用于将文档中的二级标题名称映射到 StandardCategoryTable.csv 中的标准名称
# 格式: { CSV标准名称: [可能的文档名称列表] }
SECONDARY_CATEGORY_KEYWORDS = {
    # 编制依据 (basis)
    "法律法规": ["法律法规", "法律", "法规"],
    "标准规范": ["标准规范", "标准", "规范", "技术标准"],
    "文件制度": ["文件制度", "制度文件", "管理文件"],
    "编制原则": ["编制原则", "原则"],
    "编制范围": ["编制范围", "范围", "工程范围"],

    # 工程概况 (overview)
    "设计概况": ["设计概况", "工程简介", "工程概况", "概况"],
    "工程地质与水文气象": ["工程地质与水文气象", "地质", "水文", "气象", "工程地质", "水文气象", "地质与水文"],
    "周边环境": ["周边环境", "环境", "周围环境"],
    "施工平面及立面布置": ["施工平面及立面布置", "平面布置", "立面布置", "施工平面", "平面及立面"],
    "施工要求和技术保证条件": ["施工要求和技术保证条件", "施工要求", "技术保证", "保证条件"],
    "风险辨识与分级": ["风险辨识与分级", "风险辨识", "风险分级", "风险", "风险等级"],
    "参建各方责任主体单位": ["参建各方责任主体单位", "参建单位", "责任主体", "参建各方"],

    # 施工计划 (plan)
    "施工进度计划": ["施工进度计划", "进度计划", "进度", "工期计划"],
    "施工材料计划": ["施工材料计划", "材料计划", "材料"],
    "施工设备计划": ["施工设备计划", "设备计划", "机械设备", "设备"],
    "劳动力计划": ["劳动力计划", "劳动力", "人员计划", "用工计划"],
    "安全生产费用使用计划": ["安全生产费用使用计划", "安全费用", "安全费", "安全生产费用"],

    # 施工工艺技术 (technology)
    "主要施工方法概述": ["主要施工方法概述", "施工方法概述", "方法概述", "施工方法"],
    "技术参数": ["技术参数", "参数", "技术指标"],
    "工艺流程": ["工艺流程", "流程", "施工流程"],
    "施工准备": ["施工准备", "准备", "准备工作"],
    "施工方法及操作要求": ["施工方法及操作要求", "施工方案及操作要求", "操作要求", "施工方案", "施工方法", "方法及操作"],
    "检查要求": ["检查要求", "检查", "验收要求", "检查验收"],

    # 安全保证措施 (safety)
    "安全保证体系": ["安全保证体系", "安全体系", "安全管理体系"],
    "组织保证措施": ["组织保证措施", "组织措施", "组织保证"],
    "技术保证措施": ["技术保证措施", "技术保障措施", "技术措施", "保障措施", "技术保障", "安全防护措施", "安全防护"],
    "监测监控措施": ["监测监控措施", "监测措施", "监控措施", "监测监控"],
    "应急处置措施": ["应急处置措施", "应急预案", "应急措施", "应急处置"],

    # 质量保证措施 (quality)
    "质量保证体系": ["质量保证体系", "质量体系", "质量管理体系"],
    "质量目标": ["质量目标", "质量指标"],
    "工程创优规划": ["工程创优规划", "创优规划", "创优计划", "创优"],
    "质量控制程序与具体措施": ["质量控制程序与具体措施", "质量控制", "质量措施", "质量控制措施"],

    # 环境保证措施 (environment)
    "环境保证体系": ["环境保证体系", "环境体系", "环境管理体系"],
    "环境保护组织机构": ["环境保护组织机构", "环保组织", "环境组织"],
    "环境保护及文明施工措施": ["环境保护及文明施工措施", "环保措施", "文明施工", "环境保护", "环境措施"],

    # 施工管理及作业人员配备与分工 (management)
    "施工管理人员": ["施工管理人员", "管理人员", "管理人员配备"],
    "专职安全生产管理人员": ["专职安全生产管理人员", "专职安全员", "安全管理人员", "安全员", "特种作业人员", "特种工"],
    "其他作业人员": ["其他作业人员", "其他人员", "作业人员"],

    # 验收要求 (acceptance)
    "验收标准": ["验收标准", "验收规范", "标准"],
    "验收程序": ["验收程序", "验收流程", "程序"],
    "验收内容": ["验收内容", "验收项目"],
    "验收时间": ["验收时间", "验收日期"],
    "验收人员": ["验收人员", "验收参与人员"],

    # 其他资料 (other)
    "计算书": ["计算书", "计算", "验算"],
    "相关施工图纸": ["相关施工图纸", "施工图纸", "图纸"],
    "附图附表": ["附图附表", "附图", "附表"],
    "编制及审核人员情况": ["编制及审核人员情况", "编制人员", "审核人员"],
}


# ==================== 标准分类加载器 ====================

class CategoryStandardLoader:
    """加载 StandardCategoryTable.csv"""

    def __init__(self, csv_path: Path):
        self.csv_path = csv_path
        self.standards: List[CategoryStandard] = []
        self._load()

    def _load(self):
        """加载CSV文件"""
        with open(self.csv_path, 'r', encoding='utf-8-sig') as f:  # utf-8-sig处理BOM
            reader = csv.DictReader(f)
            for row in reader:
                self.standards.append(CategoryStandard(
                    first_code=row.get('first_code', ''),
                    first_name=row.get('first_name', ''),
                    first_seq=int(row.get('first_seq', '0') or 0),
                    second_code=row.get('second_code', ''),
                    second_name=row.get('second_name', ''),
                    second_seq=int(row.get('second_seq', '0') or 0),
                    second_focus=row.get('second_focus', ''),
                    third_code=row.get('third_code', ''),
                    third_name=row.get('third_name', ''),
                    third_seq=int(row.get('third_seq', '0') or 0),
                    third_focus=row.get('third_focus', ''),
                    keywords=row.get('keywords', '')
                ))

    def get_standards_by_second_code(self, second_code: str) -> List[CategoryStandard]:
        """根据二级分类代码获取对应的三级分类标准"""
        return [s for s in self.standards if s.second_code == second_code]

    def _find_standard_name_by_keyword(self, second_name: str) -> Optional[str]:
        """
        通过关键词映射查找标准二级分类名称

        Args:
            second_name: 文档中的二级标题名称

        Returns:
            匹配到的标准名称，未匹配返回None
        """
        cleaned_name = second_name.strip().lower()

        # 遍历映射表进行匹配
        for standard_name, keywords in SECONDARY_CATEGORY_KEYWORDS.items():
            for keyword in keywords:
                # 宽容匹配：关键词在标题中，或标题在关键词中
                if keyword.lower() in cleaned_name or cleaned_name in keyword.lower():
                    return standard_name

        return None

    def get_standards_by_second_name(self, second_name: str) -> List[CategoryStandard]:
        """
        根据二级分类名称获取对应的三级分类标准（支持模糊匹配）

        匹配优先级：
        1. 完全匹配 CSV 中的标准名称
        2. 包含关系匹配（标准名包含标题名，或标题名包含标准名）
        3. 关键词映射匹配（通过 SECONDARY_CATEGORY_KEYWORDS）

        Args:
            second_name: 二级标题名称

        Returns:
            匹配到的三级分类标准列表
        """
        cleaned_name = second_name.strip()

        # 1. 先尝试完全匹配
        exact = [s for s in self.standards if s.second_name == cleaned_name]
        if exact:
            return exact

        # 2. 包含关系匹配（取第一个命中的 second_name，再返回同名的全部行）
        for s in self.standards:
            if s.second_name in cleaned_name or cleaned_name in s.second_name:
                matched_name = s.second_name
                return [st for st in self.standards if st.second_name == matched_name]

        # 3. 使用关键词映射进行模糊匹配
        matched_standard_name = self._find_standard_name_by_keyword(cleaned_name)
        if matched_standard_name:
            return [s for s in self.standards if s.second_name == matched_standard_name]

        return []


class SecondCategoryStandardLoader:
    """加载 construction_plan_standards.csv（二级分类标准）"""

    def __init__(self, csv_path: Path):
        self.csv_path = csv_path
        self.standards: List[SecondCategoryStandard] = []
        self._load()

    def _load(self):
        """加载CSV文件"""
        with open(self.csv_path, 'r', encoding='utf-8-sig') as f:  # utf-8-sig处理BOM
            reader = csv.DictReader(f)
            for row in reader:
                self.standards.append(SecondCategoryStandard(
                    first_name=row.get('first_name', '').strip(),
                    second_name=row.get('second_name', '').strip(),
                    second_raw_content=row.get('second_raw_content', '').strip()
                ))

    def get_standard_by_second_name(self, second_name: str) -> Optional[SecondCategoryStandard]:
        """根据二级分类名称获取标准定义（支持模糊匹配）"""
        # 清理待匹配的名称
        cleaned_name = second_name.strip().lower()

        # 1. 先尝试完全匹配或包含关系匹配
        for std in self.standards:
            # 完全匹配
            if std.second_name.lower() == cleaned_name:
                return std
            # 包含关系匹配
            if std.second_name.lower() in cleaned_name or cleaned_name in std.second_name.lower():
                return std

        # 2. 使用关键词映射进行模糊匹配
        matched_standard_name = None
        for standard_name, keywords in SECONDARY_CATEGORY_KEYWORDS.items():
            for keyword in keywords:
                if keyword.lower() in cleaned_name or cleaned_name in keyword.lower():
                    matched_standard_name = standard_name
                    break
            if matched_standard_name:
                break

        if matched_standard_name:
            # 在standards中查找匹配的标准
            for std in self.standards:
                if std.second_name == matched_standard_name:
                    return std

        return None
