"""DRAFT telecast_type rules for EPG titles -> Crystal's vocabulary.

Ordered rules; first match wins. Vocabulary taken from the real
global_sports.telecast_type distribution:
  LIVE, HIGHLIGHTS, PRE_POST_ANALYSIS, STUDIO, ARCHIVE, NON_EVENT, UNKNOWN

Each rule returns (telecast_type, confidence). Anything that falls through
is UNKNOWN/low and must go to analyst review, never silently to a default.
"""
import re

# Sport keywords: if none present, the row is not sport at all.
# NOTE the consequence of a miss here — it is NON_EVENT, a confident wrong
# answer, not UNKNOWN. It never reaches analyst review. So the list has to
# cover the vocabulary the feeds actually use:
#   - football markers were absent entirely (fifa/football/uefa/soccer), so a
#     World Cup listing only matched via the incidental "wc"/"world cup" tokens
#   - Spanish and Portuguese feeds ("COPA DO MUNDO", "MUNDIAL") matched nothing
#     at all and every row was silently dropped as not-sport
SPORT_HINT = re.compile(
    r"\b(icc|t20|odi|test match|cricket|wc|world cup|cwc|ipl|wt20"
    r"|fifa|football|uefa|soccer|futbol|fútbol|mundial|copa|liga"
    r"|olympic|olympics|rugby|tennis|f1|motogp|nba|nfl)\b", re.I)

# Branded standalone studio programmes. Crystal labels these '-none-', NOT
# PRE_POST_ANALYSIS — verified against global_sports (CRICKET COUNTDOWN 72,717
# rows, GAME PLAN 23,031, MATCH POINT 14,458, all '-none-').
STUDIO_BRAND = re.compile(
    r"\bcountdown\b|\bgame plan\b|\bmatch point\b|\bfollow the blues\b|"
    r"\bknow your team\b|\bsports time\b|\bbest of the\b", re.I)

RULES = [
    # 0. An explicit pre/post show OUTRANKS the word "Live" — a title like
    # "Live ICC T20 WC 2024 Pre Show" is the wrapper, not the match itself.
    (re.compile(r"\bpre[- ]show\b|\bpost[- ]show\b|\bbuild-?up\b", re.I),
     "PRE_POST_ANALYSIS", "high"),

    # 1. Explicit live markers. "(L)", "Live ", "Crick Live"
    (re.compile(r"^\(l\)|\blive\b", re.I), "LIVE", "high"),

    # 2. Retrospective packages. Crystal's ARCHIVE is branded nostalgia
    # programming (WWE-RAW, AO CLASSICS, WIMBLEDON HEROES, LEGENDS) — it is
    # NOT used for highlights of an older edition of the same event.
    (re.compile(r"\bgreatest matches\b|\bclassics?\b|\blegends\b|\bheroes\b|"
                r"\brewind\b|\bincredible finals\b", re.I), "ARCHIVE", "high"),

    # 3. Highlights markers: Hlts, Hlts., HL, H/L, Hls, Mini Hls, Highlights.
    # Applies regardless of edition year: highlights of the 2007 World Cup are
    # still HIGHLIGHTS (verified: 6,247 such rows, zero labelled ARCHIVE).
    # "H/L" is the single most common spelling in the live feed — 2,723 of
    # 12,404 World Cup rows, 22% — and the slash defeats \bhl\b, so it has to
    # be matched explicitly or a fifth of the schedule falls to UNKNOWN.
    (re.compile(r"\bhlts?\.?\b|\bhighlights?\b|\bhls\b|\bhl\b|\bh\s*/\s*l\b|\bmini hls\b", re.I),
     "HIGHLIGHTS", "high"),

    # 4. Pre/post wrappers genuinely attached to a live telecast.
    (re.compile(r"\bpre show\b|\bpost show\b|\bbuild-?up\b|\bpre\b|\bpost\b|"
                r"\bpreview\b|\breview\b", re.I), "PRE_POST_ANALYSIS", "high"),
]


def classify(title: str) -> tuple[str, str]:
    """Return (telecast_type, confidence)."""
    t = (title or "").strip()
    if not t:
        return "UNKNOWN", "low"

    # Non-sport content on a sports channel (films, sitcoms, filler).
    if not SPORT_HINT.search(t):
        return "NON_EVENT", "medium"

    # Branded studio programme -> Crystal's '-none-'. Checked before the
    # ordered rules because e.g. "Countdown Spl-ICC Men's T20 WC" would
    # otherwise be caught by a later pattern.
    if STUDIO_BRAND.search(t):
        return "-none-", "high"

    for pat, label, conf in RULES:
        if pat.search(t):
            return label, conf

    # Sport, a fixture ("X v Y"), no live/highlight marker -> ambiguous.
    if re.search(r"\b[a-z]{2,4}\s+v(?:s)?\s+[a-z]{2,4}\b", t, re.I):
        return "LIVE", "low"          # plausible but unproven -> review

    return "UNKNOWN", "low"
