"""Split long source text for LLM extraction (context budget)."""
from __future__ import annotations


def split_text_for_extraction(
    text: str,
    max_content_chars: int,
    overlap_chars: int,
) -> list[str]:
    """
    Split `text` into chunks so each chunk length <= max_content_chars.
    Tries to break on paragraph boundaries; carries overlap for continuity.
    """
    if max_content_chars <= 0:
        return [text]
    stripped = text or ""
    if len(stripped) <= max_content_chars:
        return [stripped]

    overlap = max(0, min(overlap_chars, max_content_chars // 4))
    chunks: list[str] = []
    start = 0
    n = len(stripped)

    while start < n:
        end = min(start + max_content_chars, n)
        if end < n:
            window = stripped[start:end]
            last_para = window.rfind("\n\n")
            if last_para > max(len(window) // 3, 200):
                end = start + last_para + 2

        chunk = stripped[start:end].strip()
        if chunk:
            chunks.append(chunk)

        if end >= n:
            break
        start = max(0, end - overlap)

    return chunks if chunks else [stripped[:max_content_chars]]


def distribute_max_norms_across_chunks(max_norms: int, chunk_count: int) -> list[int]:
    """Split max_norms across chunks (sum equals max_norms)."""
    if chunk_count <= 0:
        return []
    if max_norms <= 0:
        return [0] * chunk_count
    base, rem = divmod(max_norms, chunk_count)
    return [base + (1 if i < rem else 0) for i in range(chunk_count)]


def dedupe_norm_dicts_by_title(items: list[dict]) -> list[dict]:
    """Keep first occurrence per normalized title (cheap merge for chunk overlap)."""
    seen: set[str] = set()
    out: list[dict] = []
    for item in items:
        if not isinstance(item, dict):
            out.append(item)
            continue
        title = item.get("title")
        key = (str(title).strip().lower() if title is not None else "").strip() or None
        if key is None:
            out.append(item)
            continue
        if key in seen:
            continue
        seen.add(key)
        out.append(item)
    return out
