"""
Segment recording & overrides — the review foundation.

During a translation job, every (source → translation) pair is recorded so
it can be persisted per job (translation_segments table), reviewed and
edited side-by-side, and re-applied when rebuilding the document.

Overrides are the inverse path: human-reviewed translations (approved or
edited segments) applied verbatim on rebuild — no provider call, no drift.
"""

from typing import Dict, List, Optional, Tuple

from core.logging import get_logger

logger = get_logger(__name__)


class SegmentRecorder:
    """Collects unique (source, translation) pairs in document order."""

    def __init__(self):
        self._pairs: List[Tuple[str, str]] = []
        self._seen: set = set()

    def record_pair(self, source: str, translation: str) -> None:
        if not source or not source.strip():
            return
        stripped = source.strip()
        # Identity pairs carry no review value ( untranslated or unchanged
        # text) — skip them so the review list stays actionable.
        if not translation or not translation.strip() or translation.strip() == stripped:
            return
        if stripped in self._seen:
            return
        self._seen.add(stripped)
        self._pairs.append((stripped, translation.strip()))

    def record_pairs(self, pairs) -> None:
        for source, translation in pairs:
            self.record_pair(source, translation)

    def get_pairs(self) -> List[Tuple[str, str]]:
        return list(self._pairs)

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


def apply_overrides(
    texts: List[str],
    overrides: Optional[Dict[str, str]],
) -> Tuple[Dict[int, str], List[int]]:
    """Split a batch: ({index: override_translation}, [indices to translate]).

    Overrides are keyed by the stripped source text (that is how segments
    are persisted). Identity overrides are treated as "no override" so the
    normal pipeline (TM → provider) stays in charge.
    """
    if not overrides:
        return {}, list(range(len(texts)))

    hits: Dict[int, str] = {}
    misses: List[int] = []
    for i, text in enumerate(texts):
        if not text or not text.strip():
            misses.append(i)
            continue
        override = overrides.get(text.strip())
        if override is not None and override.strip() and override.strip() != text.strip():
            hits[i] = override.strip()
        else:
            misses.append(i)
    return hits, misses
