"""
财务与成本敏感数据脱敏处理器

处理对象：金额、设备租赁单价、材料单价、工程量数值等
执行策略：全量数值掩码，保留表格科目结构
"""

import re
from typing import Any
from .base_processor import BaseDesensitizer


class FinancialDesensitizer(BaseDesensitizer):
    """财务数据脱敏处理器"""

    def _compile_patterns(self):
        """编译财务数据相关正则表达式"""
        # 设备租赁单价（必须在通用金额之前匹配，防止金额模式先匹配）
        self.patterns["equipment_price"] = re.compile(
            r'(塔吊|起重机|挖掘机|装载机|压路机|混凝土搅拌站|钢筋加工设备)[\s\u4e00-\u9fa5]*'
            r'\d{1,6}(?:\.\d{1,2})?\s*(?:元|万元)?\s*/\s*(?:月|天|台班|小时)'
        )

        # 材料单价
        self.patterns["material_price"] = re.compile(
            r'(钢筋|混凝土|水泥|砂石|模板|脚手架|防水材料|保温材料)[\s\u4e00-\u9fa5]*'
            r'\d{1,5}(?:\.\d{1,2})?\s*(?:元|万元)?\s*/\s*(?:吨|立方米|平米|米|套)'
        )

        # 货币金额（含人民币符号、千分位）
        # 匹配：￥1,250,000.00、￥ 50000、50000元、50,000.00元
        self.patterns["amount_rmb"] = re.compile(
            r'￥\s*\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?'
        )
        # 金额后带单位，添加负向后顾 (?<!\d) 确保前面不是数字，避免部分匹配
        self.patterns["amount_yuan"] = re.compile(
            r'(?<!\d)\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?\s*(?:元|万元|亿元)'
        )

        # 工程量数值（保留单位，掩码数值）
        self.patterns["quantity"] = re.compile(
            r'(\d{1,6}(?:\.\d{1,2})?)\s*(立方米|m³|平米|㎡|米|m|吨|t|个|套|根)'
        )

        # 预算/费用合计
        self.patterns["total"] = re.compile(
            r'(总计|合计|总价|预算金额)[：:\s]*'
            r'[￥]?\s*\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?'
        )

        # 纯数字大金额（5位以上数字，可能是金额）
        self.patterns["large_number"] = re.compile(
            r'\b(\d{5,}(?:,\d{3})*(?:\.\d{1,2})?)\b'
        )

        # 百分比（通常与费用比例相关，保留）
        self.patterns["percentage"] = re.compile(
            r'(\d{1,3}(?:\.\d{1,2})?)\s*%'
        )

    def process(self, content: str, registry: Any, strict_mode: bool = False) -> str:
        """执行财务数据脱敏

        保留表格的表头、项目分类及科目结构
        仅掩码具体数值，确保AI能审查"是否编制了资金投入计划"
        """
        # 1. 设备租赁单价掩码（保留设备类型和单位）- 必须在通用金额之前
        def replace_equipment_price(match):
            equipment = match.group(1)
            registry.amounts.append(match.group(0))  # 记录金额用于统计
            return f"{equipment} [单价脱敏]/单位时间"

        content = self.patterns["equipment_price"].sub(replace_equipment_price, content)

        # 2. 材料单价掩码（保留材料名称和单位）- 必须在通用金额之前
        def replace_material_price(match):
            material = match.group(1)
            registry.amounts.append(match.group(0))  # 记录金额用于统计
            return f"{material} [单价脱敏]/单位"

        content = self.patterns["material_price"].sub(replace_material_price, content)

        # 3. 人民币金额掩码
        for match in self.patterns["amount_rmb"].finditer(content):
            registry.amounts.append(match.group(0))  # 记录金额用于统计
        content = self.patterns["amount_rmb"].sub("￥[金额脱敏]", content)

        # 4. 元单位金额掩码
        def replace_amount_yuan(match):
            text = match.group(0)
            registry.amounts.append(text)  # 记录金额用于统计
            # 保留单位（元/万元/亿元）
            if "万元" in text:
                return "[金额脱敏]万元"
            elif "亿元" in text:
                return "[金额脱敏]亿元"
            else:
                return "[金额脱敏]元"

        content = self.patterns["amount_yuan"].sub(replace_amount_yuan, content)

        # 5. 工程量数值掩码（保留单位）
        def replace_quantity(match):
            unit = match.group(2)
            registry.amounts.append(match.group(1))  # 记录数值用于统计
            return f"[数量脱敏]{unit}"

        content = self.patterns["quantity"].sub(replace_quantity, content)

        # 6. 预算合计掩码
        for match in self.patterns["total"].finditer(content):
            registry.amounts.append(match.group(0))  # 记录金额用于统计
        content = self.patterns["total"].sub(r"\1：￥[金额脱敏]", content)

        # 7. 严格模式下，大金额数字也掩码
        if strict_mode:
            for match in self.patterns["large_number"].finditer(content):
                registry.amounts.append(match.group(0))  # 记录金额用于统计
            content = self.patterns["large_number"].sub("[数值脱敏]", content)

        # 8. 百分比保留（通常是费率比例，不涉及具体金额）
        # content = self.patterns["percentage"].sub(r"[比例脱敏]%", content)

        return content

    def extract_amounts(self, content: str) -> list:
        """提取所有金额数值（用于统计）"""
        amounts = []

        for pattern_name in ["amount_rmb", "amount_yuan"]:
            for match in self.patterns[pattern_name].finditer(content):
                amounts.append({
                    "value": match.group(0),
                    "type": pattern_name,
                    "position": match.span()
                })

        return amounts
