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

NOTES = (
    "DWELLING/HOUSEHOLD COMPLEMENTARY PERCEPTION PRONOUN EXPANSION AFTER RULE 246 (Rule 247). 50 rows. "
    "TARGETS retained: bakarr ridge pole, bayan house, bira windbreak, jiji roof, kilili windbreak, "
    "wurun humpy, jakway door, yulal board, kararr blanket, and bilangkurr blanket. SUPPORT: bare "
    "nominative ngali, ngaliny, yubal, nganjin, and yurra plus yaluy/yinyay and nyajil. FRAMES: "
    "Ngali TARGET yaluy nyajil, Ngaliny TARGET yinyay nyajil, Yubal TARGET yaluy nyajil, "
    "Nganjin TARGET yinyay nyajil, and Yurra TARGET yaluy nyajil. REVIEW: no new dwelling lexeme, no "
    "yamba, yamba-kari, jakal, warrbi, building, setting up camp, spreading, entering, nailing, roofing, "
    "source-material prose, sleeping, covering, warming, front/open/shut, top-of-anything, plank/round-stick, "
    "ownership, locative house row, target case, pronoun case, perception compound, support inflection, target "
    "compound, productive reduplication, or recent fire/body/landform/fish/bird drift was opened."
)

LESSONS = [
    ("source", "Rule 247 retained the ten checked Rule 238 dwelling/household noun heads: bakarr, bayan, bira, jiji, kilili, wurun, jakway, yulal, kararr, and bilangkurr.", "Rule 247: retained target inventory."),
    ("source", "Dictionary and grammar readback confirmed bakarr as ridge pole, bayan as house, bira as windbreak, jiji as roof, kilili as windbreak, wurun as humpy, jakway as door, yulal as board, kararr as blanket, and bilangkurr as blanket.", "Rule 247: source readback."),
    ("source", "Patz section 3.1.2 supplied the habitat/object noun domain and lists bayan as camp/house/shelter; Rule 247 selected only the house sense.", "Rule 247: bayan source restraint."),
    ("source", "Patz section 3.5 Table 3.6 supplied the selected bare nominative pronouns ngali, ngaliny, yubal, nganjin, and yurra.", "Rule 247: pronoun source."),
    ("source", "Patz section 3.7 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 247 used only bare local demonstratives and did not add case-marked local forms.", "Rule 247: demonstrative source."),
    ("source", "Patz section 3.8.3.2 supplied nyaji-l 'see'; Rule 247 used only nonpast nyajil and did not build perception compounds, past, purposive, or infinitive rows.", "Rule 247: perception source."),
    ("process", "Exact duplicate preflight over all 50 final Rule 247 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 247: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 246 was bakarr 15, bayan 451, bira 16, jiji 15, kilili 15, wurun 38, jakway 25, yulal 25, kararr 32, and bilangkurr 32.", "Rule 247: target coverage audit."),
    ("process", "Pronoun coverage before banking was ngali 119, ngaliny 54, yubal 65, nganjin 71, and yurra 113; the batch added signal for dual, exclusive, and second-plural nominative forms.", "Rule 247: pronoun coverage audit."),
    ("lexicon", "Bakarr remained ridge pole only; pole material, house-building, construction, support action, and source-material rows stayed closed.", "Rule 247: bakarr."),
    ("lexicon", "Bayan remained house only; camp setup, shelter-event, possession, locative house, opium, particle, and yamba-kari rows stayed closed.", "Rule 247: bayan."),
    ("lexicon", "Bira remained windbreak only; making, setting, weather, rain, cold, and material-source rows stayed closed.", "Rule 247: bira."),
    ("lexicon", "Jiji remained roof only; top-of-anything, roofing-material, building, and source-prose extensions stayed closed.", "Rule 247: jiji."),
    ("lexicon", "Kilili remained windbreak only; construction, weather-shelter, material-source, and use rows stayed closed.", "Rule 247: kilili."),
    ("lexicon", "Wurun remained humpy only; halfway, building, sleeping, rain-shelter, and locative rows stayed closed.", "Rule 247: wurun."),
    ("lexicon", "Jakway remained door only; front, open, close, shut, entering, and door-use predicates stayed closed.", "Rule 247: jakway."),
    ("lexicon", "Yulal remained board only; plank wording, kimil round-stick contrast, nailing, building, and source-material prose stayed closed.", "Rule 247: yulal."),
    ("lexicon", "Kararr remained blanket only; sheet, grass bedding, spreading, sleeping, covering, warming, privative, and year-counting rows stayed closed.", "Rule 247: kararr."),
    ("lexicon", "Bilangkurr remained blanket only; clothing, sleeping, covering, warming, possession, and ownership rows stayed closed.", "Rule 247: bilangkurr."),
    ("morphology", "All Rule 247 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 247: bare targets."),
    ("morphology", "The subject support forms stayed bare nominatives: no pronoun case forms, possessive readings, or person/number extensions were introduced.", "Rule 247: 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 247: uninflected support."),
    ("morphology", "No target compound, lexicalized trap compound, dwelling-use construction, building construction, possession construction, or productive reduplication was built from the dwelling/household heads.", "Rule 247: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajil.", "Rule 247: 1du exclusive here perception band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajil.", "Rule 247: 1du inclusive there perception band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajil.", "Rule 247: 2du here perception band."),
    ("syntax", "Rows 31-40 used Nganjin TARGET yinyay nyajil.", "Rule 247: 1pl exclusive there perception band."),
    ("syntax", "Rows 41-50 used Yurra TARGET yaluy nyajil.", "Rule 247: 2pl here perception band."),
    ("fidelity", "English stayed literal perception/reference prose: selected subject pronoun value, target label, here/there, and see only.", "Rule 247: literal English."),
    ("fidelity", "The batch did not convert alternate glosses or source prose into building, setting camp, spreading, entering, nailing, roofing, sleeping, covering, warming, front/open/shut, top-of-anything, plank/round-stick, sheet, grass-bedding, ownership, locative, opium, or homograph claims.", "Rule 247: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style perception clauses; no construction, domestic-instruction, weather-shelter, bedding-use, ownership, narrative, ceremonial, or source-material register was introduced.", "Rule 247: register."),
    ("process", "Rules 149-246 carry-forward traps stayed closed, especially recent fire, body-part, landform, fish, and bird perception traps plus older dwelling action/use/homograph traps.", "Rule 247: carry-forward closure."),
    ("handoff", "Next batch may continue from 14,547 if this closes; do not infer building, setting camp, roofing, spreading, sleeping, covering, warming, front/open/shut, top-of-anything, plank/round-stick, ownership, locative house rows, target-case, pronoun-case, perception-compound, or support-inflection grammar from Rule 247.", "Rule 247: next cadence."),
]

LEXEMES = [
    ("bakarr", "noun", None, "NA", "ridge pole", "batch-289: ridge-pole perception/reference only; construction, pole-material, and source-material rows closed."),
    ("bayan", "noun", None, "NA", "house", "batch-289: house perception/reference only; camp/shelter setup, possession, locative, opium, particle, and yamba-kari rows closed."),
    ("bira", "noun", None, "NA", "windbreak", "batch-289: windbreak perception/reference only; making, setting, weather, rain, cold, and material-source rows closed."),
    ("jiji", "noun", None, "NA", "roof", "batch-289: roof perception/reference only; top-of-anything and roofing-material prose closed."),
    ("kilili", "noun", None, "NA", "windbreak", "batch-289: windbreak perception/reference only; construction, weather, source-material, and use rows closed."),
    ("wurun", "noun", None, "NA", "humpy", "batch-289: humpy perception/reference only; halfway, building, sleeping, rain-shelter, and locative rows closed."),
    ("jakway", "noun", None, "NA", "door", "batch-289: door perception/reference only; front/open/close/shut/entering predicates closed."),
    ("yulal", "noun", None, "NA", "board", "batch-289: board perception/reference only; plank wording, round-stick contrast, nailing, building, and source-material rows closed."),
    ("kararr", "noun", None, "NA", "blanket", "batch-289: blanket perception/reference only; sheet, grass bedding, spreading, sleeping, covering, warming, privative, and year-counting rows closed."),
    ("bilangkurr", "noun", None, "NA", "blanket", "batch-289: blanket perception/reference only; clothing, sleeping, covering, warming, and ownership rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-289: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-289: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-289: bare nominative subject support only."),
    ("nganjin", "pronoun", None, "NA", "first plural exclusive nominative", "batch-289: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-289: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-289: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-289: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-289: 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-289-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 247 rows. Morphology checked bare dwelling/household nouns, bare nominative ngali/ngaliny/yubal/nganjin/yurra, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected dwelling/household senses 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 yamba, yamba-kari, jakal, warrbi, building, setting up camp, spreading, entering, nailing, roofing/source-material prose, sleeping, covering, warming, front/open/shut, top-of-anything, plank/round-stick, sheet, grass, year-counting, ownership, locative house row, target case, pronoun case, perception compound, target compound, productive reduplication, support inflection, or recent fire/body/landform/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 247 lessons covering source checks, coverage, lexical target senses, morphology, syntax, fidelity, register, process traps, and handoff.",
        artifact_path="batch_scripts/close_289.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 247 targets and support heads.",
        artifact_path="batch_scripts/close_289.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 289: 50 accepted Rule 247 dwelling/household complementary pronoun-expansion rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_289.py",
        artifact_path="batch_scripts/close_289.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-289-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())
