#!/usr/bin/env python3
"""Close batch-306 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-306"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-306-mammal-nonsingular-pronoun-perception-after-rule263-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "MAMMAL NON-SINGULAR PRONOUN PERCEPTION SWEEP AFTER RULE 263 (Rule 264). 50 rows. "
    "TARGETS: bala sugar glider, darrba grass wallaby, jarrabina tree kangaroo, jayju kangaroo rat, "
    "jungarr marsupial native cat, kukur rat, mali small bat, murramu dingo, ngumbi bandicoot, and yawa "
    "possum. SUPPORT: bare nominative ngali, ngaliny, yubal, nganjin, and ngana plus yaluy/yinyay and "
    "nyajil. FRAMES: Ngali TARGET yinyay nyajil, Ngaliny TARGET yaluy nyajil, Yubal TARGET yinyay nyajil, "
    "Nganjin TARGET yaluy nyajil, and Ngana TARGET yinyay nyajil. REVIEW: no Rule 177-178 duplicate surface, "
    "Rule 219 alternate, introduced animal/loan drift, bala skinny/weak/boney adjective homograph, jarrabina "
    "tree-climbing prose, murral cross-reference expansion, mali species-prose expansion, murramu synonym "
    "ngamu-murramu, dog-loan, attack/event row, ngumbi little/spotted source-prose property row, hunting/"
    "catching/trapping/killing/biting/attacking/spearing row, food/edible/cooking/meat row, skin/fur/tail/"
    "claw/body-part row, habitat/ecology/water/river/sea/hollow/cave row, story/place/totem/moiety/ceremony "
    "row, colour predicate, source-prose row, target case, target compound, productive reduplication, pronoun "
    "case, demonstrative case, perception compound, purposive, past, support inflection, reptile/amphibian "
    "drift, fish drift, bird drift, insect drift, shellfish drift, or recent dwelling/landform/body/fire drift "
    "was opened."
)

LESSONS = [
    ("source", "Rule 264 retained the ten checked Rule 219/253/254 mammal noun heads: bala, darrba, jarrabina, jayju, jungarr, kukur, mali, murramu, ngumbi, and yawa.", "Rule 264: target inventory."),
    ("source", "Dictionary line readback was explicit: bala 720-728, darrba 5306-5315, jarrabina 8248-8259, jayju 8602-8610, jungarr 10882-10892, kukur 15002-15010, mali 17566-17577, murramu 21010-21020, ngumbi 23562-23572, and yawa 29634-29642.", "Rule 264: dictionary source lines."),
    ("source", "Patz grammar lines 2577-2603 supplied bare nominative ngali, ngaliny, yubal, nganjin, and ngana; Rule 264 used no pronoun case forms.", "Rule 264: non-singular pronoun source."),
    ("source", "Patz grammar lines 2682-2684 and corpus precedent supported the English alignment: ngali 1du exclusive, ngaliny 1du inclusive, yubal 2du, nganjin 1pl exclusive, and ngana 1pl inclusive.", "Rule 264: inclusive/exclusive source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 264 used only the bare local demonstratives.", "Rule 264: demonstrative source."),
    ("source", "Patz section 3.8.3.2 lines 3043-3049 supplied nyaji-l 'see'; Rule 264 used only the nonpast form nyajil and did not build perception compounds or purposive rows.", "Rule 264: perception source."),
    ("process", "Rule 264 returns to the mammal target field after the reptile/amphibian Rule 262-263 pair while preserving the same non-singular pronoun perception frame discipline.", "Rule 264: field rotation."),
    ("process", "Exact duplicate preflight over all 50 planned Rule 264 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 264: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 263 was bala 19, darrba 48, jarrabina 20, jayju 18, jungarr 17, kukur 21, mali 25, murramu 38, ngumbi 18, and yawa 44.", "Rule 264: target coverage audit."),
    ("process", "Support coverage before banking after Rule 263 was ngali 199, ngaliny 134, yubal 145, nganjin 151, ngana 899, yaluy 2453, yinyay 2696, and nyajil 3017.", "Rule 264: support coverage audit."),
    ("lexicon", "Bala was admitted as sugar glider only; the skinny, weak, and boney adjective homograph stayed closed.", "Rule 264: bala."),
    ("lexicon", "Darrba was admitted as grass wallaby only; wallaby behavior, food, hunting, and habitat readings stayed closed.", "Rule 264: darrba."),
    ("lexicon", "Jarrabina was admitted as tree kangaroo only; tree-climbing prose and murral cross-reference expansion stayed closed.", "Rule 264: jarrabina."),
    ("lexicon", "Jayju was admitted as kangaroo rat only; rat behavior, pest, food, and habitat prose stayed closed.", "Rule 264: jayju."),
    ("lexicon", "Jungarr was admitted as marsupial native cat only; quoll commentary and domestic/introduced cat drift stayed closed.", "Rule 264: jungarr."),
    ("lexicon", "Kukur was admitted as rat only; introduced-animal, pest, food, and habitat semantics stayed closed.", "Rule 264: kukur."),
    ("lexicon", "Mali was admitted as small bat only; species prose, cave, night, flying, and roosting readings stayed closed.", "Rule 264: mali."),
    ("lexicon", "Murramu was admitted as dingo only; ngamu-murramu synonym expansion, dog-loan, attack, biting, and event readings stayed closed.", "Rule 264: murramu."),
    ("lexicon", "Ngumbi was admitted as bandicoot only; little/spotted source-prose property rows and digging/habitat rows stayed closed.", "Rule 264: ngumbi."),
    ("lexicon", "Yawa was admitted as possum only; food, hunting, habitat, story, and body-part readings stayed closed.", "Rule 264: yawa."),
    ("morphology", "All Rule 264 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 264: bare targets."),
    ("morphology", "English modifiers inside mammal labels, such as sugar, grass, tree, kangaroo, marsupial, native, small, and spotted/little source prose, remained lexical-label prose rather than Kuku morphology or separate predicates.", "Rule 264: label morphology guard."),
    ("morphology", "The subject support forms stayed bare nominatives: ngali, ngaliny, yubal, nganjin, and ngana were not inflected for accusative, dative, locative, ablative, comitative, or possessive.", "Rule 264: bare non-singular 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 264: uninflected support."),
    ("morphology", "No target compound, lexicalized trap compound, or productive reduplication was built from the mammal heads.", "Rule 264: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajil.", "Rule 264: 1du exclusive there perception band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajil.", "Rule 264: 1du inclusive here perception band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajil.", "Rule 264: 2du there perception band."),
    ("syntax", "Rows 31-40 used Nganjin TARGET yaluy nyajil.", "Rule 264: 1pl exclusive here perception band."),
    ("syntax", "Rows 41-50 used Ngana TARGET yinyay nyajil.", "Rule 264: 1pl inclusive there perception band."),
    ("fidelity", "English stayed literal perception/reference prose: subject pronoun, selected mammal label, here/there, and see only.", "Rule 264: literal English."),
    ("fidelity", "The batch did not convert dictionary examples, alternate glosses, or source prose into hunting, catching, trapping, killing, biting, attacking, spearing, food, edible, cooking, meat, skin, fur, tail, claw, body-part, habitat, ecology, water, river, sea, hollow, cave, story, place, totem, moiety, ceremony, colour, source-material, or event claims.", "Rule 264: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style perception clauses; no warning, hunting report, food statement, habitat claim, animal-behavior report, or story register was introduced.", "Rule 264: register."),
    ("process", "Rules 149-263 carry-forward traps stayed closed, especially mammal-source-prose traps, reptile/amphibian use/action traps, fish-use/action traps, bird event/use/lore traps, insect and shellfish source-prose traps, dwelling action/use/source traps, fire action/use/homograph traps, landform route/water/event drift, and body-part possession/body-state drift.", "Rule 264: carry-forward closure."),
    ("handoff", "Next batch may continue from 15,397 if this closes; do not infer mammal behavior, use, habitat, story, body-part, homograph, source-prose, target-case, pronoun-case, demonstrative-case, perception-compound, purposive, past, or support-inflection grammar from Rule 264.", "Rule 264: next cadence."),
]

LEXEMES = [
    ("bala", "noun", None, "NA", "sugar glider", "batch-306: sugar-glider perception/reference only; skinny/weak/boney adjective homograph closed."),
    ("darrba", "noun", None, "NA", "grass wallaby", "batch-306: grass-wallaby perception/reference only; behavior/food/hunting/habitat readings closed."),
    ("jarrabina", "noun", None, "NA", "tree kangaroo", "batch-306: tree-kangaroo perception/reference only; tree-climbing prose and murral cross-reference closed."),
    ("jayju", "noun", None, "NA", "kangaroo rat", "batch-306: kangaroo-rat perception/reference only; behavior/pest/food/habitat readings closed."),
    ("jungarr", "noun", None, "NA", "marsupial native cat", "batch-306: marsupial-native-cat perception/reference only; quoll commentary and domestic/introduced cat drift closed."),
    ("kukur", "noun", None, "NA", "rat", "batch-306: rat perception/reference only; introduced-animal, pest, food, and habitat semantics closed."),
    ("mali", "noun", None, "NA", "small bat", "batch-306: small-bat perception/reference only; species prose, cave, night, flying, and roosting readings closed."),
    ("murramu", "noun", None, "NA", "dingo", "batch-306: dingo perception/reference only; ngamu-murramu synonym, dog-loan, attack, biting, and event readings closed."),
    ("ngumbi", "noun", None, "NA", "bandicoot", "batch-306: bandicoot perception/reference only; little/spotted source-prose, digging, and habitat readings closed."),
    ("yawa", "noun", None, "NA", "possum", "batch-306: possum perception/reference only; food, hunting, habitat, story, and body-part readings closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-306: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-306: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-306: bare nominative subject support only."),
    ("nganjin", "pronoun", None, "NA", "first plural exclusive nominative", "batch-306: bare nominative subject support only."),
    ("ngana", "pronoun", None, "NA", "first plural inclusive nominative", "batch-306: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-306: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-306: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-306: 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-306-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 264 rows. Morphology checked bare mammal nouns, bare nominative non-singular pronouns, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected mammal labels only. Syntax checked five non-singular 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 Rule 177-178 duplicate surface, no Rule 219 alternate, no introduced animal or loan drift, no bala adjective-homograph row, no jarrabina tree-climbing or murral expansion, no murramu synonym/dog/attack row, no ngumbi little/spotted property row, no hunting/catching/trapping/killing/biting/attacking/spearing row, no food/edible/cooking/meat row, no skin/fur/tail/claw/body-part row, no habitat/ecology/water/river/sea/hollow/cave row, no story/place/totem/moiety/ceremony row, no colour predicate, no source-prose row, no target case, no productive compound, no productive reduplication, no pronoun case, no demonstrative case, no perception compound, no purposive, no past, and no support inflection.",
        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 264 lessons covering source checks, lexical target senses, field rotation, hard exclusions, morphology, syntax, fidelity, register, process traps, and handoff.",
        artifact_path="batch_scripts/close_306.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 264 targets and support heads.",
        artifact_path="batch_scripts/close_306.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 306: 50 accepted Rule 264 mammal non-singular pronoun perception rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_306.py",
        artifact_path="batch_scripts/close_306.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-306-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())
