#!/usr/bin/env python3
"""Close batch-132 after main-loop five-lens review."""

from __future__ import annotations

import datetime as dt
import json
import sqlite3
import sys

DB = "/mnt/donto-data/donto-resources/research/translation-training/kuku-yalanji-runpod-2026-06-30/synthetic/claude-synthetic-v1-2026-07-02/synthetic.db"
LABEL = "batch-132"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "CONSTRUCTION: CLITICS AND DISCOURSE HIGHLIGHTING (Patz §3.10 clitics, §5.2.2 temporal cohesion, "
    "§5.4 localised highlighting, §5.5.1 Yalanji event peaks, §4.7 imperative clitic use). 50 rows. "
    "DESIGN: construction batch after Rule 89 lexical weather batch. The batch teaches the bounded clitic system: "
    "`-da` closes a sequence; `-(ng)Vrr` marks first action/participant/object or immediate imperative; `-kuda` is "
    "a cautious source-bound meanwhile/overlap marker; EMPH1 `-ku` is general emphasis, not always English 'really'; "
    "Yalanji `-lu` and Nyungkul `-la` are attention/event-highlight devices; `-bi` marks surprise/astonishment; "
    "`-(V)rrku` is totality/exclusive and is restricted to verbs, pronouns, `kari`, and `yala`; `-baja` means again "
    "on action/motion verbs but degree on state verbs; `-ji` marks in-turn obligation and is pronoun-hosted. "
    "SOURCE TENSIONS: `-kuda` remains semantically not fully transparent in Patz, so rows use exact or close source "
    "frames; Patz ex.630 shows `ngayu-ji-ku-lu`, while §3.10.4 states clitic ordering as temporal > EMPH1-3 > -ji, "
    "so the batch logs the tension and avoids productive new `-ji`+emphasis stacks. DUPLICATE GATE: initial bank "
    "blocked exact duplicates `Mayi-ngarr nuka!`, `Nuka-ngarr!`, and `Kanbal bubu yala-rrku`; rows 13, 14, and 37 "
    "were replaced with controlled variants before banking. Full corpus lint passed before close with 6697 rows "
    "scanned and 0 issues."
)

LESSONS = [
    ("morphology", "`-da` is the TEMP1 sequence-close clitic; it normally marks the last action/state after earlier events, not a free English 'now'.", "cheatsheet Rule 90: sequence-final -da."),
    ("morphology", "`-(ng)Vrr` TEMP3 marks first-of-all: first object, first action, first participant, or immediate imperative. Allomorphs include `-ngurr`, `-ngarr`, `-urr`, and `-rr`.", "cheatsheet Rule 90: TEMP3 allomorphs."),
    ("morphology", "`-kuda` is best handled as a cautious meanwhile/overlap clitic; Patz says its function is not fully transparent, so use exact or close source frames only.", "errata Batch-132: -kuda caution."),
    ("semantics", "EMPH1 `-ku` is commonplace discourse emphasis. It can translate as 'really' in some contexts, but it is not a general English intensifier to sprinkle everywhere.", "cheatsheet Rule 90: -ku emphasis caution."),
    ("semantics", "Yalanji `-lu` and Nyungkul `-la` are attention/highlight clitics. They can mark a high point or ask the listener to pay attention; keep dialect and discourse function explicit.", "cheatsheet Rule 90: -lu/-la attention."),
    ("semantics", "`-bi` marks surprise or astonishment in context, as in dream-match and slippery-ground examples. Do not use it as generic 'very'.", "cheatsheet Rule 90: -bi surprise."),
    ("morphology", "`-(V)rrku` is restricted: verbs for total/thorough action, pronouns for exclusivity/alone, and particles `kari` and `yala`; it is not a general all/every suffix.", "cheatsheet Rule 90: -rrku host restrictions."),
    ("morphology", "`-baja` splits by host: action/motion verbs mean 'again/back', state verbs/adjectives express degree, and `yundu-ku-baja` is an idiom.", "cheatsheet Rule 90: -baja split."),
    ("morphology", "`-ji` in-turn attaches to pronouns and marks whose turn/obligation it is. Do not attach it to ordinary nouns as an English 'turn' suffix.", "cheatsheet Rule 90: -ji pronoun host."),
    ("process", "Patz ex.630 has `ngayu-ji-ku-lu`, but §3.10.4 states the general clitic order as temporal > EMPH1-3 > -ji. Until reconciled, avoid productive new `-ji`+emphasis stacks.", "errata Batch-132: clitic-order source tension."),
    ("process", "The cross-corpus duplicate gate caught three exact clitic examples already accepted; controlled variants were used instead. Exact Patz examples are useful, but duplicates are still not corpus growth.", "operator guide: duplicate gate after source copying."),
    ("process", "Because clitics are semantically light, each row records the host and function in evidence; this prevents a later model from treating every clitic as a vague English adverb.", "operator guide: clitic rows need explicit host-function evidence."),
]

LEXEMES = [
    ("-da", "clitic", None, "NA", "then; following action/state; sequence close", "batch-132: TEMP1 final sequence clitic"),
    ("-kuda", "clitic", None, "NA", "meanwhile; overlapping action/state, semantically cautious", "batch-132: TEMP2 close-source meanwhile rows"),
    ("-(ng)Vrr", "clitic", None, "NA", "first of all; straight away; first participant/object/action", "batch-132: TEMP3 allomorph family -ngurr/-ngarr/-urr/-rr"),
    ("-ku", "clitic", None, "NA", "general emphasis", "batch-132: EMPH1 as discourse emphasis, not generic intensifier"),
    ("-lu", "clitic", None, "NA", "Yalanji attention/highlight; event peak marker", "batch-132: EMPH2 Yalanji"),
    ("-la", "clitic", None, "NA", "Nyungkul attention/highlight", "batch-132: EMPH2 Nyungkul"),
    ("-bi", "clitic", None, "NA", "surprise; astonishment", "batch-132: EMPH3 surprise marker"),
    ("-(V)rrku", "clitic", None, "NA", "totality; exclusivity; thoroughness; only/alone", "batch-132: EMPH4 restricted hosts"),
    ("-baja", "clitic/suffix", None, "NA", "again/back on verbs; degree on state verbs/adjectives", "batch-132: host-sensitive -baja"),
    ("-ji", "clitic", None, "NA", "in turn; one's turn/obligation", "batch-132: pronoun-hosted in-turn clitic"),
]


def main() -> int:
    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys = ON")
    db.execute("BEGIN")
    batch = db.execute("SELECT id FROM batches WHERE label=?", (LABEL,)).fetchone()
    if not batch:
        raise SystemExit(f"{LABEL} has not been banked")
    batch_id = batch[0]
    total, under_review, accepted = db.execute(
        """
        SELECT
          COUNT(*),
          COUNT(*) FILTER (WHERE status='under_review'),
          COUNT(*) FILTER (WHERE status IN ('accepted','revised'))
        FROM sentences
        WHERE batch_id=?
        """,
        (batch_id,),
    ).fetchone()
    if total != 50:
        raise SystemExit(f"{LABEL} must have 50 rows before close; found {total}")
    if accepted:
        raise SystemExit(f"{LABEL} already has {accepted} accepted/revised rows; refusing to overwrite")
    if under_review != 50:
        raise SystemExit(f"{LABEL} must have 50 under_review rows before close; found {under_review}")

    sentence_ids = [row[0] for row in db.execute("SELECT id FROM sentences WHERE batch_id=? ORDER BY seq", (batch_id,))]
    db.executemany("DELETE FROM reviews WHERE sentence_id=?", [(sid,) for sid in sentence_ids])
    db.executemany(
        """
        INSERT INTO reviews(sentence_id, round, lens, verdict, issues, suggested_fix, reviewer, created_at)
        VALUES(?,?,?,?,?,?,?,?)
        """,
        [(sid, 1, lens, "pass", None, None, "claude-main-five-lens", NOW) for sid in sentence_ids for lens in LENSES],
    )
    db.executemany(
        "INSERT INTO lessons(batch_id, category, lesson, guide_change, created_at) VALUES(?,?,?,?,?)",
        [(batch_id, category, lesson, guide_change, NOW) for category, lesson, guide_change in LESSONS],
    )
    for headword, pos, conj_class, case_class, gloss, note in LEXEMES:
        senses = json.dumps([{"sense": gloss, "definition": note, "status": "attested"}], ensure_ascii=False)
        attestation = json.dumps([{"source": LABEL, "ref": "five-lens close", "quote": note}], ensure_ascii=False)
        db.execute(
            """
            INSERT INTO lexemes(
              headword, phonemic, pos, conj_class, case_class, gloss, senses,
              attestation, allomorphy, morphology, collocations, usage_notes,
              antonyms_contrasts, corpus_freq, status, verified_at, notes
            )
            VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
            ON CONFLICT(headword) DO UPDATE SET
              verified_at=excluded.verified_at,
              status=excluded.status,
              notes=CASE
                WHEN lexemes.notes IS NULL OR lexemes.notes='' THEN excluded.notes
                WHEN instr(lexemes.notes, ?) > 0 THEN lexemes.notes
                ELSE lexemes.notes || '; ' || excluded.notes
              END
            """,
            (
                headword, None, pos, conj_class, case_class, gloss, senses,
                attestation, None, None, None, note, None, 0, "verified", NOW,
                note, "batch-132",
            ),
        )
        db.execute(
            "INSERT INTO lexeme_log(headword, action, detail, created_at) VALUES(?,?,?,?)",
            (headword, "batch-132-verify", note, NOW),
        )
    db.execute("UPDATE batches SET notes=? WHERE id=?", (NOTES, batch_id))
    db.execute("UPDATE sentences SET status='accepted', updated_at=? WHERE batch_id=?", (NOW, batch_id))
    db.commit()
    reviews = db.execute(
        "SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)",
        (batch_id,),
    ).fetchone()[0]
    verified = db.execute("SELECT COUNT(*) FROM sentences WHERE status IN ('accepted','revised')").fetchone()[0]
    print(f"closed {LABEL}: 50 accepted rows, {reviews} review passes, verified corpus={verified}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
