"""
文档预处理/清洗服务

参考 Dify 的 DatasetProcessRule，支持可配置的文本清洗规则。
在文本提取之后、分块之前执行。
"""
import logging
import re
from typing import Dict, Any, List, Optional

logger = logging.getLogger(__name__)

# 默认预处理规则
DEFAULT_PROCESS_RULES: Dict[str, Any] = {
    "pre_processing_rules": [
        {"id": "remove_extra_spaces", "enabled": True},
        {"id": "remove_urls_emails", "enabled": False},
        {"id": "remove_html_tags", "enabled": False},
        {"id": "remove_consecutive_newlines", "enabled": True},
        {"id": "remove_trailing_whitespace", "enabled": True},
    ],
}


class CleaningService:
    """
    文本清洗服务

    支持的清洗规则：
    - remove_extra_spaces: 合并连续空格为单个空格
    - remove_urls_emails: 移除 URL 和邮箱地址
    - remove_html_tags: 移除 HTML 标签
    - remove_consecutive_newlines: 合并连续空行（3+）为双空行
    - remove_trailing_whitespace: 去除行尾空白
    """

    # 规则处理器映射
    RULE_PROCESSORS = {
        "remove_extra_spaces": "_remove_extra_spaces",
        "remove_urls_emails": "_remove_urls_emails",
        "remove_html_tags": "_remove_html_tags",
        "remove_consecutive_newlines": "_remove_consecutive_newlines",
        "remove_trailing_whitespace": "_remove_trailing_whitespace",
    }

    @classmethod
    def clean(cls, text: str, process_rules: Optional[Dict[str, Any]] = None) -> str:
        """
        根据预处理规则清洗文本

        Args:
            text: 原始文本
            process_rules: 预处理规则配置，为 None 则使用默认规则

        Returns:
            清洗后的文本
        """
        if not text:
            return text

        rules = process_rules or DEFAULT_PROCESS_RULES
        pre_rules = rules.get("pre_processing_rules", [])

        original_length = len(text)

        for rule in pre_rules:
            rule_id = rule.get("id", "")
            enabled = rule.get("enabled", False)

            if not enabled:
                continue

            processor_name = cls.RULE_PROCESSORS.get(rule_id)
            if not processor_name:
                logger.warning(f"未知的预处理规则: {rule_id}")
                continue

            processor = getattr(cls, processor_name, None)
            if processor:
                text = processor(text)

        cleaned_length = len(text)
        if original_length != cleaned_length:
            logger.info(
                f"文本清洗完成: {original_length} -> {cleaned_length} 字符 "
                f"(减少 {original_length - cleaned_length})"
            )

        return text.strip()

    @staticmethod
    def _remove_extra_spaces(text: str) -> str:
        """合并连续空格为单个空格（保留换行符）"""
        # 只处理同一行内的连续空格，不影响换行
        lines = text.split('\n')
        cleaned_lines = []
        for line in lines:
            cleaned_lines.append(re.sub(r'[ \t]+', ' ', line))
        return '\n'.join(cleaned_lines)

    @staticmethod
    def _remove_urls_emails(text: str) -> str:
        """移除 URL 和邮箱地址"""
        # 移除 URL
        text = re.sub(
            r'https?://[^\s<>"{}|\\^`\[\]]+',
            '',
            text,
        )
        # 移除邮箱
        text = re.sub(
            r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}',
            '',
            text,
        )
        return text

    @staticmethod
    def _remove_html_tags(text: str) -> str:
        """移除 HTML 标签，保留文本内容"""
        # 移除 script 和 style 标签及其内容
        text = re.sub(r'<script[^>]*>.*?</script>', '', text, flags=re.DOTALL | re.IGNORECASE)
        text = re.sub(r'<style[^>]*>.*?</style>', '', text, flags=re.DOTALL | re.IGNORECASE)
        # 移除所有 HTML 标签
        text = re.sub(r'<[^>]+>', '', text)
        # 解码常见 HTML 实体
        text = text.replace('&nbsp;', ' ')
        text = text.replace('&lt;', '<')
        text = text.replace('&gt;', '>')
        text = text.replace('&amp;', '&')
        text = text.replace('&quot;', '"')
        text = text.replace('&#39;', "'")
        return text

    @staticmethod
    def _remove_consecutive_newlines(text: str) -> str:
        """合并连续空行（3个以上换行）为双换行"""
        return re.sub(r'\n{3,}', '\n\n', text)

    @staticmethod
    def _remove_trailing_whitespace(text: str) -> str:
        """去除每行行尾空白"""
        return '\n'.join(line.rstrip() for line in text.split('\n'))

    @classmethod
    def get_default_rules(cls) -> Dict[str, Any]:
        """获取默认预处理规则"""
        return DEFAULT_PROCESS_RULES.copy()

    @classmethod
    def get_available_rules(cls) -> List[Dict[str, str]]:
        """获取所有可用的预处理规则"""
        return [
            {"id": "remove_extra_spaces", "label": "合并连续空格"},
            {"id": "remove_urls_emails", "label": "移除 URL 和邮箱"},
            {"id": "remove_html_tags", "label": "移除 HTML 标签"},
            {"id": "remove_consecutive_newlines", "label": "合并连续空行"},
            {"id": "remove_trailing_whitespace", "label": "去除行尾空白"},
        ]
