"""Sentence-boundary text splitting for long-form audio generation."""

from __future__ import annotations

import re

# Split after sentence-ending punctuation (Western + CJK)
_SENTENCE_SPLIT = re.compile(r"(?<=[.!?])\s+|(?<=[。！？])")

# Split after clause-level punctuation
_CLAUSE_SPLIT = re.compile(r"(?<=[,;:\u2014])\s+|(?<=[、；：])")


def split_into_chunks(text: str, max_chars: int = 3500) -> list[str]:
    """Split text into chunks at sentence boundaries.

    Never splits mid-sentence. Falls back to clause boundaries for long
    sentences, then word boundaries as a last resort.

    Args:
        text: The input text to split.
        max_chars: Maximum characters per chunk (100-4096).

    Returns:
        List of text chunks, each within max_chars.
    """
    if max_chars < 100:
        raise ValueError("max_chars must be at least 100")
    if max_chars > 4096:
        raise ValueError("max_chars must be at most 4096 (API limit)")

    trimmed = text.strip()
    if not trimmed:
        return []
    if len(trimmed) <= max_chars:
        return [trimmed]

    sentences = _SENTENCE_SPLIT.split(trimmed)
    chunks: list[str] = []
    current = ""

    for sentence in sentences:
        stripped = sentence.strip()
        if not stripped:
            continue

        if len(stripped) > max_chars:
            if current:
                chunks.append(current.strip())
                current = ""
            chunks.extend(_split_long_sentence(stripped, max_chars))
            continue

        combined = f"{current} {stripped}" if current else stripped

        if len(combined) > max_chars:
            chunks.append(current.strip())
            current = stripped
        else:
            current = combined

    if current.strip():
        chunks.append(current.strip())

    return chunks


def _split_long_sentence(sentence: str, max_chars: int) -> list[str]:
    """Split a sentence that exceeds max_chars at clause boundaries."""
    clauses = _CLAUSE_SPLIT.split(sentence)

    if len(clauses) > 1:
        chunks: list[str] = []
        current = ""

        for clause in clauses:
            stripped = clause.strip()
            if not stripped:
                continue

            if len(stripped) > max_chars:
                if current:
                    chunks.append(current.strip())
                    current = ""
                chunks.extend(_split_at_words(stripped, max_chars))
                continue

            combined = f"{current} {stripped}" if current else stripped
            if len(combined) > max_chars:
                chunks.append(current.strip())
                current = stripped
            else:
                current = combined

        if current.strip():
            chunks.append(current.strip())

        return chunks

    return _split_at_words(sentence, max_chars)


def _split_at_words(text: str, max_chars: int) -> list[str]:
    """Last-resort splitting at word boundaries."""
    words = text.split()
    chunks: list[str] = []
    current = ""

    for word in words:
        combined = f"{current} {word}" if current else word
        if len(combined) > max_chars and current:
            chunks.append(current.strip())
            current = word
        else:
            current = combined

    if current.strip():
        chunks.append(current.strip())

    return chunks
