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

NOTES = (
    "BIRD-REFERENCE PERCEPTION DEBT SWEEP AFTER RULE 240 (Rule 241). 50 rows. TARGETS: birmba "
    "straw-necked ibis, jamarbina goose, nili-nili duck, mabal swallow, wungku domestic turkey, kuludu dove, "
    "kururrungka kookaburra, karrambil king parrot, yinjul parrot, and kadanji black cockatoo. SUPPORT: bare "
    "nominative ngayu, nyulu, yurra, bula, and jana plus yaluy/yinyay and nyajil. FRAMES: Ngayu TARGET "
    "yinyay nyajil, Nyulu TARGET yaluy nyajil, Yurra TARGET yinyay nyajil, Bula TARGET yaluy nyajil, "
    "and Jana TARGET yinyay nyajil. REVIEW: no flight, song, call, dance, warning, messenger, totem/moiety, "
    "sacred-bird, story-site, nest, egg, feather, wing, food, eating, hunting, catching, storm, place, water/tree/"
    "habitat, colour predicate, secondary-sense, possession, target case, target compound, productive "
    "reduplication, pronoun case, perception compound, support inflection, or recent fish/dwelling/fire drift "
    "was opened."
)

LESSONS = [
    ("source", "Rule 241 selected ten checked bird-reference noun heads: birmba, jamarbina, nili-nili, mabal, wungku, kuludu, kururrungka, karrambil, yinjul, and kadanji.", "Rule 241: target inventory."),
    ("source", "Patz section 3.1.2 supports nouns as terms for fauna and lists dikal as a bird classifier; Rule 241 uses only selected species/common-name labels and does not build classifier compounds.", "Rule 241: noun source."),
    ("source", "Patz section 3.5 Table 3.6 supplied the bare nominative pronoun forms ngayu, nyulu, yurra, bula, and jana.", "Rule 241: pronoun source."),
    ("source", "Patz section 3.7 Table 3.12 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 241 used only these bare local demonstratives.", "Rule 241: demonstrative source."),
    ("source", "Patz section 3.8.3.2 supplied nyaji-l 'see'; Rule 241 used only nonpast nyajil and did not build purposive, past-tense, or perception-compound rows.", "Rule 241: perception source."),
    ("process", "Exact duplicate preflight over all 50 planned Rule 241 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 241: duplicate preflight."),
    ("process", "Token-boundary coverage before banking was wungku 2, mabal 5, yinjul 7, birmba 8, kuludu 10, kadanji 11, kururrungka 11, jamarbina 14, and karrambil 14; yalngkurr had 5 but was rejected for sacred/totem/country pressure.", "Rule 241: coverage audit."),
    ("process", "Hard exclusions retained older bird traps: no flight, song, call, dance, warning, messenger, totem/moiety, sacred-bird, story-site, nest, egg, feather, wing, food, hunting, catching, storm, place, habitat, colour, possession, or event rows.", "Rule 241: hard exclusions."),
    ("lexicon", "Birmba was admitted as straw-necked ibis only; totem/moiety notes and cockatoo alternate prose stayed closed.", "Rule 241: birmba."),
    ("lexicon", "Jamarbina was admitted as goose only; no bird behaviour, food, or habitat prose was inferred.", "Rule 241: jamarbina."),
    ("lexicon", "Nili-nili was admitted as a whole lexical duck head only; the lexical reduplication note did not license productive reduplication.", "Rule 241: nili-nili."),
    ("lexicon", "Mabal was admitted as swallow bird only; English verb semantics and flight/action prose stayed closed.", "Rule 241: mabal."),
    ("lexicon", "Wungku was admitted as domestic turkey only; scrub turkey and diwan contrast prose stayed closed.", "Rule 241: wungku."),
    ("lexicon", "Kuludu was admitted as dove only; small-grey descriptive prose and colour predicates stayed closed.", "Rule 241: kuludu."),
    ("lexicon", "Kururrungka was admitted as kookaburra only; bronze-wing descriptive prose stayed closed.", "Rule 241: kururrungka."),
    ("lexicon", "Karrambil was admitted as king parrot only; no parrot behaviour, food, tree, or colour row was built.", "Rule 241: karrambil."),
    ("lexicon", "Yinjul was admitted as parrot only; fig-parrot/tree/food/habitat specificity stayed closed.", "Rule 241: yinjul."),
    ("lexicon", "Kadanji was admitted as black cockatoo only; totem/moiety, Yalanji/Nyungkul contrast, and kumurbina prose stayed closed.", "Rule 241: kadanji."),
    ("morphology", "All Rule 241 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 241: bare targets."),
    ("morphology", "The hyphen in nili-nili is lexical and dictionary-backed; Rule 241 does not generalize it to productive reduplication.", "Rule 241: lexical reduplication only."),
    ("morphology", "The subject support forms stayed bare nominatives: no pronoun case forms, possessive readings, or person/number extensions were introduced.", "Rule 241: bare nominative pronouns."),
    ("morphology", "Yaluy, yinyay, and nyajil stayed uninflected support heads; no demonstrative case, local-derived form, verb nominalization, purposive, or support suffix was admitted.", "Rule 241: uninflected support."),
    ("syntax", "Rows 1-10 used Ngayu TARGET yinyay nyajil.", "Rule 241: 1sg there perception band."),
    ("syntax", "Rows 11-20 used Nyulu TARGET yaluy nyajil.", "Rule 241: 3sg here perception band."),
    ("syntax", "Rows 21-30 used Yurra TARGET yinyay nyajil.", "Rule 241: 2pl there perception band."),
    ("syntax", "Rows 31-40 used Bula TARGET yaluy nyajil.", "Rule 241: 3du here perception band."),
    ("syntax", "Rows 41-50 used Jana TARGET yinyay nyajil.", "Rule 241: 3pl there perception band."),
    ("fidelity", "English stayed literal perception/reference prose: subject pronoun, selected bird label, here/there, and see only.", "Rule 241: literal English."),
    ("fidelity", "The batch did not convert dictionary examples or source prose into flight, song, call, dance, omen, messenger, totem, story, food, hunting, catching, nesting, egg, feather, wing, habitat, place, or event claims.", "Rule 241: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style perception clauses; no bird lore, taboo, food practice, hunting instruction, ecological statement, or narrative register was introduced.", "Rule 241: register."),
    ("process", "Rules 149-240 carry-forward traps stayed closed, especially fish-use/action traps, dwelling action/use/source traps, fire action/use/homograph traps, body-part possession/case/perception drift, and older bird-use/event rows.", "Rule 241: carry-forward closure."),
    ("handoff", "Next batch may continue from 14,247 if this closes; do not infer flight, song, call, omen, totem/moiety, nest/egg/feather/wing, food, hunting, catching, habitat, target case, pronoun case, perception-compound, or support-inflection grammar from Rule 241.", "Rule 241: next cadence."),
]

LEXEMES = [
    ("birmba", "noun", None, "NA", "straw-necked ibis", "batch-283: straw-necked-ibis perception/reference only; totem/moiety and cockatoo alternate prose closed."),
    ("jamarbina", "noun", None, "NA", "goose", "batch-283: goose perception/reference only; no behaviour, food, or habitat row."),
    ("nili-nili", "noun", None, "NA", "duck", "batch-283: duck perception/reference only; lexical reduplicated head, not productive reduplication."),
    ("mabal", "noun", None, "NA", "swallow", "batch-283: swallow bird perception/reference only; English verb/action semantics closed."),
    ("wungku", "noun", None, "NA", "domestic turkey", "batch-283: domestic-turkey perception/reference only; scrub-turkey/diwan contrast closed."),
    ("kuludu", "noun", None, "NA", "dove", "batch-283: dove perception/reference only; small-grey prose and colour predicates closed."),
    ("kururrungka", "noun", None, "NA", "kookaburra", "batch-283: kookaburra perception/reference only; bronze-wing descriptive prose closed."),
    ("karrambil", "noun", None, "NA", "king parrot", "batch-283: king-parrot perception/reference only; no behaviour, food, tree, or colour row."),
    ("yinjul", "noun", None, "NA", "parrot", "batch-283: parrot perception/reference only; fig-parrot/tree/food/habitat specificity closed."),
    ("kadanji", "noun", None, "NA", "black cockatoo", "batch-283: black-cockatoo perception/reference only; totem/moiety and Nyungkul kumurbina contrast closed."),
    ("ngayu", "pronoun", None, "NA", "first singular nominative", "batch-283: bare nominative subject support only."),
    ("nyulu", "pronoun", None, "NA", "third singular nominative", "batch-283: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-283: bare nominative subject support only."),
    ("bula", "pronoun", None, "NA", "third dual nominative", "batch-283: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-283: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-283: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-283: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-283: nonpast visual-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-283-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 241 rows. Morphology checked bare bird nouns, lexical nili-nili only, bare nominative pronouns, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected bird labels only. Syntax checked five 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 flight, song, call, dance, warning, messenger, totem/moiety, sacred-bird, story-site, nest, egg, feather, wing, food, eating, hunting, catching, storm, place, water/tree/habitat, colour predicate, secondary-sense, possession, target case, target compound, productive reduplication, pronoun case, perception compound, support inflection, or recent fish/dwelling/fire/body 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 241 lessons covering source checks, lexical target senses, hard exclusions, morphology, syntax, fidelity, register, process traps, and handoff.",
        artifact_path="batch_scripts/close_283.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 241 targets and support heads.",
        artifact_path="batch_scripts/close_283.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 283: 50 accepted Rule 241 bird-reference perception rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_283.py",
        artifact_path="batch_scripts/close_283.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-283-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())
