"""分块器基类 + Chunk 数据结构"""

from __future__ import annotations

import re
from abc import ABC, abstractmethod
from dataclasses import dataclass, field


@dataclass
class Chunk:
    """一个语义完整的文档块"""

    content: str
    section: str | None = None
    parent_section: str | None = None
    chunk_index: int = 0
    tags: list[str] = field(default_factory=list)
    token_count: int = 0
    embedding: list[float] | None = None  # indexer 填充
    summary: str | None = None  # 索引时生成

    def __post_init__(self):
        if not self.token_count:
            self.token_count = estimate_tokens(self.content)
        if not self.summary and self.content:
            self.summary = _make_summary(self.content)


class BaseChunker(ABC):
    """分块器抽象基类"""

    MAX_CHUNK_TOKENS = 1500

    @abstractmethod
    def chunk(self, content: str, file_path: str) -> list[Chunk]:
        """将文件内容分成语义完整的块"""

    def _split_oversized(self, text: str, section: str | None,
                         parent: str | None, start_index: int) -> list[Chunk]:
        """将超大块按段落再分割"""
        paragraphs = re.split(r"\n\n+", text.strip())
        chunks = []
        current = ""

        for para in paragraphs:
            candidate = (current + "\n\n" + para).strip() if current else para
            if estimate_tokens(candidate) > self.MAX_CHUNK_TOKENS and current:
                chunks.append(Chunk(
                    content=current,
                    section=section,
                    parent_section=parent,
                    chunk_index=start_index + len(chunks),
                ))
                current = para
            else:
                current = candidate

        if current.strip():
            chunks.append(Chunk(
                content=current,
                section=section,
                parent_section=parent,
                chunk_index=start_index + len(chunks),
            ))

        return chunks


def estimate_tokens(text: str) -> int:
    """近似 token 计数（中英文混合 ~3.5 字符/token）"""
    return max(1, int(len(text) / 3.5))


def _make_summary(text: str, max_chars: int = 200) -> str:
    """取前几句作为摘要"""
    sentences = re.split(r"[.。!！?\?\n]", text)
    summary = ""
    for s in sentences:
        s = s.strip()
        if not s:
            continue
        if len(summary) + len(s) > max_chars:
            break
        summary += s + ". " if not summary else " " + s + "."
    return summary.strip() or text[:max_chars].strip()
