"""术语表管理 + jieba 自定义词典 — 增强中文分词准确率。

领域术语（如"知识图谱"、"向量数据库"）默认会被 jieba 错误切分（如"知识/图谱"），
导致全文检索召回率下降。本模块通过 jieba.add_word() / jieba.load_userdict()
将术语表注入 jieba 词典，确保领域术语被正确识别为单个 token。

jieba 词典文件格式（每行一条）：
    词语 词频 词性
    例如：
        知识图谱 100 n
        向量数据库 100 n
"""

from __future__ import annotations

import logging
from pathlib import Path

from pydantic import BaseModel, ConfigDict

logger = logging.getLogger(__name__)


class TermEntry(BaseModel):
    """术语条目。"""

    model_config = ConfigDict()

    term: str
    frequency: int | None = None  # jieba 词频（None 表示使用默认）
    pos: str | None = None  # 词性标注（如 "n"、"v"）


class Termbase:
    """术语表管理 — 加载/添加/删除术语，同步到 jieba 自定义词典。

    使用方式：
        tb = Termbase()
        tb.add_term("知识图谱")
        tb.add_term("向量数据库", frequency=100, pos="n")
        tokens = tb.tokenize("知识图谱是向量数据库的基础")
        # tokens 中 "知识图谱" 和 "向量数据库" 作为整体 token 出现
    """

    def __init__(self) -> None:
        self._terms: dict[str, TermEntry] = {}

    def add_term(
        self,
        term: str,
        frequency: int | None = None,
        pos: str | None = None,
    ) -> None:
        """添加术语到词典。

        Args:
            term: 术语文本（非空）
            frequency: jieba 词频（None 表示使用默认）
            pos: 词性标注
        """
        term = term.strip()
        if not term:
            return

        self._terms[term] = TermEntry(term=term, frequency=frequency, pos=pos)

        # 同步到 jieba 词典
        # ponytail: freq=None 时 jieba 使用默认词频（足够高以覆盖默认切分）
        # 升级路径：若需精细控制词频，调用方应显式传入 frequency 参数
        import jieba

        if frequency is not None:
            jieba.add_word(term, freq=frequency, tag=pos)
        else:
            jieba.add_word(term, tag=pos)
        logger.debug("Added term to jieba dictionary: %s", term)

    def load_from_file(self, path: str) -> None:
        """从文件加载术语表（jieba 词典格式：词语 词频 词性）。

        Args:
            path: 词典文件路径

        Raises:
            FileNotFoundError: 文件不存在
        """
        file_path = Path(path)
        if not file_path.exists():
            raise FileNotFoundError(f"Termbase file not found: {path}")

        import jieba

        jieba.load_userdict(str(file_path))

        # 同步到内部 _terms 字典
        with file_path.open(encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                parts = line.split()
                term = parts[0]
                freq = int(parts[1]) if len(parts) > 1 and parts[1].isdigit() else None
                pos = parts[2] if len(parts) > 2 else None
                if term:
                    self._terms[term] = TermEntry(term=term, frequency=freq, pos=pos)

        logger.info("Loaded %d terms from %s", len(self._terms), path)

    def load_from_list(self, terms: list[str]) -> None:
        """从字符串列表加载术语。

        Args:
            terms: 术语字符串列表
        """
        for term in terms:
            self.add_term(term)

    def remove_term(self, term: str) -> None:
        """删除术语。

        Args:
            term: 要删除的术语
        """
        if term not in self._terms:
            return

        del self._terms[term]

        import jieba

        jieba.del_word(term)
        logger.debug("Removed term from jieba dictionary: %s", term)

    def list_terms(self) -> list[TermEntry]:
        """列出所有术语。

        Returns:
            TermEntry 列表（按添加顺序）
        """
        return list(self._terms.values())

    def tokenize(self, text: str) -> list[str]:
        """使用自定义词典分词。

        Args:
            text: 待分词文本

        Returns:
            token 列表（精确模式，cut_all=False）
        """
        import jieba

        return list(jieba.cut(text, cut_all=False))

    def __len__(self) -> int:
        return len(self._terms)

    def __contains__(self, term: str) -> bool:
        return term in self._terms


__all__ = ["TermEntry", "Termbase"]
