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

from __future__ import annotations

import datetime as dt
import json
import sqlite3

from process_ledger import ensure_schema, record_event

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-292"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-292-fire-reference-complementary-pronoun-expansion-after-rule249-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "FIRE-REFERENCE COMPLEMENTARY PERCEPTION PRONOUN EXPANSION AFTER RULE 249 (Rule 250). 50 rows. "
    "TARGETS retained: baya fire, jimal fire stick, jirramar small sticks, kubu smoke, kunjin fire, "
    "miyilkura smouldering log, ngalku bush fire, ngaluri flames, ngunjil charcoal, and wula flames. "
    "SUPPORT: bare nominative ngali, ngaliny, yubal, nganjin, and yurra plus yaluy/yinyay and nyajil. "
    "FRAMES: Ngali TARGET yinyay nyajil, Ngaliny TARGET yaluy nyajil, Yubal TARGET yinyay nyajil, "
    "Nganjin TARGET yaluy nyajil, and Yurra TARGET yinyay nyajil. REVIEW: no new fire lexeme, no "
    "fire-making, lighting, firewood, collecting, cooking, burning, clearing, spreading, leaping-flame event, "
    "hot-coal/ash extension, smoke-source, smoke-out, loan, ritual-smoke prose, body-fluid homograph, mullet/place/"
    "tadpole homograph, target case, target compound, productive reduplication, pronoun case, perception compound, "
    "support inflection, or recent body/landform/dwelling/fish/bird drift was opened."
)

LESSONS = [
    ("source", "Rule 250 retained the ten checked Rule 236 fire-reference noun heads: baya, jimal, jirramar, kubu, kunjin, miyilkura, ngalku, ngaluri, ngunjil, and wula.", "Rule 250: retained target inventory."),
    ("source", "Dictionary line readback confirmed baya as fire, jimal as fire stick, jirramar as small sticks, kubu as smoke, kunjin as fire, miyilkura as smouldering log, ngalku as bush fire, ngaluri as flames, ngunjil as charcoal, and wula as flames.", "Rule 250: dictionary source readback."),
    ("source", "Direct dictionary readback used lines 1948-1964 for baya, 9258-9294 for jimal and nearby traps, 9863-9875 for jirramar, 14707-14729 for kubu and kubu-kubu, 15880-15889 for kunjin and kunjirr, 19985-19994 for miyilkura, 21918-21950 for ngalku/ngalkun/ngalkunbu, 22014-22025 for ngaluri, 23679-23688 for ngunjil, and 27719-27730 for wula/wulay.", "Rule 250: line-level source evidence."),
    ("source", "Patz section 3.5 Table 3.6 supplied the selected bare nominative pronouns ngali, ngaliny, yubal, nganjin, and yurra.", "Rule 250: pronoun source."),
    ("source", "Patz section 3.7 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 250 used only the bare local demonstratives and did not add case-marked local forms.", "Rule 250: demonstrative source."),
    ("source", "Patz section 3.8.3.2 supplied nyaji-l 'see'; Rule 250 used only nonpast nyajil and did not build perception compounds, past, purposive, or infinitive rows.", "Rule 250: perception source."),
    ("process", "Exact duplicate preflight over all 50 final Rule 250 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 250: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 249 was baya 468, jimal 43, jirramar 15, kubu 71, kunjin 21, miyilkura 15, ngalku 15, ngaluri 15, ngunjil 78, and wula 69.", "Rule 250: target coverage audit."),
    ("process", "Pronoun coverage before banking was ngali 151, ngaliny 85, yubal 99, nganjin 101, and yurra 144; the batch added opposite-location signal for dual, exclusive, and second-plural nominative forms.", "Rule 250: pronoun coverage audit."),
    ("lexicon", "Baya remained fire only; firewood, baya wayu, lighting, collecting, cooking, and fire-use rows stayed closed.", "Rule 250: baya."),
    ("lexicon", "Jimal remained fire stick only; jimal damal fire-making, twirling, story, and jimalili rows stayed closed.", "Rule 250: jimal."),
    ("lexicon", "Jirramar remained small sticks only; kindling action, starting-fire use, collecting, and material-use rows stayed closed.", "Rule 250: jirramar."),
    ("lexicon", "Kubu remained smoke only; smoke-source, smoke-out, warning, motion, kubu-kubu tadpole, and use rows stayed closed.", "Rule 250: kubu."),
    ("lexicon", "Kunjin remained fire only; no contrast with baya and no kunjirr ritual-smoke/purification prose was imported.", "Rule 250: kunjin."),
    ("lexicon", "Miyilkura remained smouldering log only; burning, cooking, warming, ash, eye/miyil, and use rows stayed closed.", "Rule 250: miyilkura."),
    ("lexicon", "Ngalku remained bush fire only; clearing, spreading, grassfire, danger, warning, ngalkun mullet, and ngalkunbu place rows stayed closed.", "Rule 250: ngalku."),
    ("lexicon", "Ngaluri remained flames only; the source usage with flames leaping up was not converted into a leap-up event predicate.", "Rule 250: ngaluri."),
    ("lexicon", "Ngunjil remained charcoal only; hot coals and hot ashes extensions stayed closed.", "Rule 250: ngunjil."),
    ("lexicon", "Wula remained flames only; dalngarri synonymy, dalngarri's urine/body-fluid homograph, and nearby wulay verb drift stayed closed.", "Rule 250: wula."),
    ("morphology", "All Rule 250 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 250: bare targets."),
    ("morphology", "The subject support forms stayed bare nominatives: no pronoun case forms, possessive readings, or person/number extensions were introduced.", "Rule 250: bare nominative pronouns."),
    ("morphology", "Yaluy, yinyay, and nyajil stayed uninflected support heads; no demonstrative case, local-derived form, verb nominalization, purposive, past, or support suffix was admitted.", "Rule 250: uninflected support."),
    ("morphology", "No target compound, lexicalized trap compound, fire-use construction, smoke-source construction, or productive reduplication was built from the fire-reference heads.", "Rule 250: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajil.", "Rule 250: 1du exclusive there perception band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajil.", "Rule 250: 1du inclusive here perception band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajil.", "Rule 250: 2du there perception band."),
    ("syntax", "Rows 31-40 used Nganjin TARGET yaluy nyajil.", "Rule 250: 1pl exclusive here perception band."),
    ("syntax", "Rows 41-50 used Yurra TARGET yinyay nyajil.", "Rule 250: 2pl there perception band."),
    ("fidelity", "English stayed literal perception/reference prose: selected subject pronoun value, target label, here/there, and see only.", "Rule 250: literal English."),
    ("fidelity", "The batch did not convert dictionary alternate glosses or source prose into fire-making, firewood, lighting, collecting, cooking, burning, clearing, spreading, smoke-source, smoke-out, leaping, hot-coal, ash, body-fluid, ritual, story, or use claims.", "Rule 250: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style perception clauses; no danger, warning, ceremony, story, environmental-management, cooking, or instruction register was introduced.", "Rule 250: register."),
    ("process", "Rules 149-249 carry-forward traps stayed closed, especially recent body-part, landform, dwelling, fish, and bird perception traps plus older fire action/use/homograph traps.", "Rule 250: carry-forward closure."),
    ("handoff", "Next batch may continue from 14,697 if this closes; do not infer fire-making, firewood, cooking, burning, clearing, spreading, hot-coal/ash, smoke-source, body-fluid homograph, loan, target-case, pronoun-case, perception-compound, or support-inflection grammar from Rule 250.", "Rule 250: next cadence."),
]

LEXEMES = [
    ("baya", "noun", None, "NA", "fire", "batch-292: fire perception/reference only; firewood, baya wayu, lighting, collecting, cooking, and use rows closed."),
    ("jimal", "noun", None, "NA", "fire stick", "batch-292: fire-stick perception/reference only; jimal damal fire-making and jimalili story rows closed."),
    ("jirramar", "noun", None, "NA", "small sticks", "batch-292: small-sticks perception/reference only; starting-fire/kindling-use prose closed."),
    ("kubu", "noun", None, "NA", "smoke", "batch-292: smoke perception/reference only; smoke-source, smoke-out, kubu-kubu tadpole, and warning rows closed."),
    ("kunjin", "noun", None, "NA", "fire", "batch-292: fire perception/reference only; no asserted contrast with baya; kunjirr ritual-smoke prose closed."),
    ("miyilkura", "noun", None, "NA", "smouldering log", "batch-292: smouldering-log perception/reference only; burning, cooking, warming, ash, and eye/miyil drift closed."),
    ("ngalku", "noun", None, "NA", "bush fire", "batch-292: bush-fire perception/reference only; clearing, spreading, danger, warning, ngalkun mullet, and ngalkunbu place closed."),
    ("ngaluri", "noun", None, "NA", "flames", "batch-292: flames perception/reference only; leap-up event predicate closed."),
    ("ngunjil", "noun", None, "NA", "charcoal", "batch-292: charcoal perception/reference only; hot coals and hot ashes extensions closed."),
    ("wula", "noun", None, "NA", "flames", "batch-292: flames perception/reference only; dalngarri body-fluid homograph and wulay verb drift closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-292: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-292: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-292: bare nominative subject support only."),
    ("nganjin", "pronoun", None, "NA", "first plural exclusive nominative", "batch-292: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-292: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-292: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-292: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-292: nonpast perception support only."),
]


def main() -> int:
    db = sqlite3.connect(DB)
    db.execute("PRAGMA foreign_keys = ON")
    db.execute("BEGIN")
    ensure_schema(db)
    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}")

    total_rows = db.execute("SELECT COUNT(*) FROM sentences WHERE status!='rejected'").fetchone()[0]
    verified_before, words_before = db.execute(
        """
        SELECT
          COUNT(*),
          SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()
    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.execute("DELETE FROM lessons WHERE batch_id=?", (batch_id,))
    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,
                LABEL,
            ),
        )
        db.execute(
            "INSERT INTO lexeme_log(headword, action, detail, created_at) VALUES(?,?,?,?)",
            (headword, "batch-292-verify", note, NOW),
        )

    record_event(
        db,
        batch_label=LABEL,
        phase="lint",
        event_type="under-review-lint-green",
        actor="claude-main",
        detail=f"After banking, lint scanned {total_rows} rows and found 0 issues; verified total remained {verified_before} before close.",
        command="python3 lint_corpus.py",
        output_excerpt=f"lint: {total_rows} rows scanned, 0 issues flagged; GOAL METRIC: {verified_before} / 20000 verified sentences ({words_before or 0} Kuku words)",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="review",
        event_type="five-lens-pass",
        actor="claude-main",
        detail="Manual five-lens review passed all 50 Rule 250 rows. Morphology checked bare fire-reference nouns, bare nominative ngali/ngaliny/yubal/nganjin/yurra, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected fire-reference senses only. Syntax checked five opposite-location pronoun-perception frame bands. Fidelity checked literal reference/perception English. Register stayed plain elicitation-style.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="review",
        event_type="review-detail",
        actor="claude-main",
        detail="Final review retained no fire-making, lighting, firewood, collecting, cooking, burning, clearing, spreading, leaping-flame event, smoke-source, smoke-out, hot coals, hot ashes, body-fluid homograph, loan, ritual-smoke prose, mullet/place/tadpole homograph, target case, productive compound, productive reduplication, pronoun case, perception compound, support inflection, or recent body/landform/dwelling/fish/bird drift.",
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="review",
        event_type="lesson-inventory",
        actor="claude-main",
        detail=f"Inserted {len(LESSONS)} Rule 250 lessons covering source checks, coverage, lexical target senses, morphology, syntax, fidelity, register, process traps, and handoff.",
        artifact_path="batch_scripts/close_292.py",
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="review",
        event_type="lexeme-source-log",
        actor="claude-main",
        detail=f"Inserted {len(LEXEMES)} lexeme/source-log rows for Rule 250 targets and support heads.",
        artifact_path="batch_scripts/close_292.py",
        created_at=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))
    record_event(
        db,
        batch_label=LABEL,
        phase="close",
        event_type="close-success",
        actor="claude-main",
        detail="Closed Batch 292: 50 accepted Rule 250 fire-reference complementary pronoun-expansion rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_292.py",
        artifact_path="batch_scripts/close_292.py",
        created_at=NOW,
    )
    db.commit()

    reviews = db.execute(
        "SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)",
        (batch_id,),
    ).fetchone()[0]
    lessons = db.execute("SELECT COUNT(*) FROM lessons WHERE batch_id=?", (batch_id,)).fetchone()[0]
    lexeme_logs = db.execute(
        "SELECT COUNT(*) FROM lexeme_log WHERE action='batch-292-verify'"
    ).fetchone()[0]
    verified_after, words_after = db.execute(
        """
        SELECT
          COUNT(*),
          SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()
    print(
        f"closed {LABEL}: accepted=50, reviews={reviews}, lessons={lessons}, "
        f"lexeme_logs={lexeme_logs}, verified {verified_before}->{verified_after}, "
        f"kuku_words {words_before}->{words_after}"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
