"""
Stratified sampler for the L1 quality layer.

The L1 layer sends a small number of (source, translation) pairs to a
cheap LLM for a quality verdict. We don't want to send ALL chunks
(cost, latency) and we don't want to send random chunks (might miss
the problematic ones). We use a simple but effective strategy:

  - Prefer the LONGEST chunks (they contain the most diagnostic
    information per call).
  - Skip chunks that the L0 already flagged (we already know they're
    bad; we don't need the LLM to confirm).
  - Never sample more than `max_samples` chunks.
  - If `min_chunks` chunks aren't available, skip the L1 entirely
    (small documents don't need it).
"""

from __future__ import annotations

from typing import List, Tuple


def sample_chunks_for_l1(
    source_chunks: List[str],
    translated_chunks: List[str],
    failed_indices: set,
    max_samples: int = 5,
    min_chunks: int = 10,
) -> List[Tuple[str, str]]:
    """
    Select a sample of (source, translation) pairs to send to the L1 judge.

    Args:
        source_chunks: Original texts.
        translated_chunks: Translated texts (same length as source_chunks).
        failed_indices: Set of indices that L0 already flagged as bad.
                        These are SKIPPED — we want fresh signal, not
                        confirmation of an already-detected failure.
        max_samples: Maximum number of pairs to return.
        min_chunks: If the document has fewer than this many chunks,
                    return an empty list (not enough signal to bother
                    calling the LLM).

    Returns:
        A list of (source, translated) tuples, ready to send to the LLM
        judge. Order: longest chunks first.
    """
    n = min(len(source_chunks), len(translated_chunks))

    if n < min_chunks:
        return []

    # Build candidate list, excluding L0 failures
    candidates: List[Tuple[int, int, str, str]] = []
    for i in range(n):
        if i in failed_indices:
            continue
        src = (source_chunks[i] or "").strip()
        trans = (translated_chunks[i] or "").strip()
        # Skip very short pairs (not enough context for the LLM to judge)
        if len(src) < 5 and len(trans) < 5:
            continue
        # Skip pairs where source and translation are identical
        # (probably a non-translated cell like a number, code, or brand)
        if src == trans:
            continue
        # Rank by length of the translation (longer = more diagnostic)
        rank = len(trans) + len(src) // 2
        candidates.append((rank, i, src, trans))

    # Sort by length descending and take top N
    candidates.sort(key=lambda c: c[0], reverse=True)
    selected = candidates[:max_samples]

    # Return in original document order (helps the LLM judge maintain
    # context, and makes the verdict easier to interpret)
    selected.sort(key=lambda c: c[1])

    return [(src, trans) for _rank, _i, src, trans in selected]
