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

NOTES = (
    "VISIBLE ARTEFACT/TOOL NON-SINGULAR COMPLEMENTARY NONPAST PRONOUN PERCEPTION SWEEP AFTER RULE 286 "
    "(Rule 287). 50 rows. TARGETS: badur hook, balji dilly bag, balur spear thrower, kaljan outrigger canoe, "
    "dajal fighting spear, dakilji cup, jidi torch, jindal three-pronged spear, jundi pumice stone, and karra rope. "
    "SUPPORT: bare nominative ngali, ngaliny, yubal, yurra, and jana plus yaluy/yinyay and nyajil. FRAMES: Ngali "
    "TARGET yaluy nyajil, Ngaliny TARGET yinyay nyajil, Yubal TARGET yaluy nyajil, Yurra TARGET yinyay nyajil, "
    "and Jana TARGET yaluy nyajil. REVIEW: Rule 287 inherits the final Rule 285-286 target set and does not reopen "
    "birungubay after Batch 231 duplicate pressure. No fishing, making, material source, canoe travel, rowing/"
    "paddling, spear throwing, fighting, biting, sharpening/rubbing, tying, fire/burning, post-contact loan object, "
    "target case, pronoun case, demonstrative case, target compound, productive reduplication, perception compound, "
    "past/purposive/reduplicated perception drift, support inflection, or recent water/landform/sky/fire/fauna/body/"
    "dwelling drift was opened."
)

LESSONS = [
    ("source", "Rule 287 selected ten visible artefact/tool target heads: badur, balji, balur, kaljan, dajal, dakilji, jidi, jindal, jundi, and karra.", "Rule 287: visible target inventory."),
    ("source", "Direct dictionary line readback was explicit: badur 256-268, balji 963-974, balur 1154-1170, kaljan 12560-12568, dajal 4499-4509, dakilji 4665-4676, jidi 8842-8851, jindal 9423-9433, jundi 10846-10857, and karra 13534-13544.", "Rule 287: dictionary source lines."),
    ("source", "Patz grammar lines 2577-2586 and 2592-2603 supplied the personal pronoun table and base forms for bare nominative ngali, ngaliny, yubal, yurra, and jana.", "Rule 287: pronoun source."),
    ("source", "Patz grammar lines 2674-2686 supplied the non-singular person/number contrasts used here: ngali 1du exclusive, ngaliny 1du inclusive, yubal 2du, yurra 2pl, and jana 3pl.", "Rule 287: non-singular source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 287 used only bare local demonstratives.", "Rule 287: demonstrative source."),
    ("source", "Patz section 3.8.3.2 lines 3043-3049 supplied nyaji-l 'see'; Rule 287 used corpus-conventional nyajil as the nonpast visual-perception surface only.", "Rule 287: nonpast perception source."),
    ("source", "Patz lines 2568-2571 supplied nyaji-ny 'see-PAST' only as past contrast; Rule 287 did not use past nyajin.", "Rule 287: past contrast."),
    ("process", "Rule 287 was scoped as a complementary nonpast consolidation of the Rule 286 visible artefact/tool field, reversing the here/there pairing without opening a new semantic or object-use expansion.", "Rule 287: complementary construction consolidation."),
    ("process", "Rule 287 retained the final Rule 285-286 kaljan replacement target set and did not reopen birungubay after Batch 231 duplicate pressure.", "Rule 287: birungubay stays excluded."),
    ("process", "Final preflight over the 50 complementary nonpast artefact/tool surfaces returned 50 unique strings and no accepted, revised, or under-review collisions.", "Rule 287: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 286 was badur 55, balji 204, balur 43, kaljan 13, dajal 10, dakilji 15, jidi 23, jindal 12, jundi 17, and karra 113.", "Rule 287: target coverage audit."),
    ("process", "Support coverage before banking after Rule 286 was ngali 353, ngaliny 295, yubal 305, yurra 310, jana 973, yaluy 2982, yinyay 3304, and nyajil 3147 by words_used JSON.", "Rule 287: support coverage audit."),
    ("lexicon", "Badur remained visible hook/hook-and-line only; fishing, sitting-with-line, catching, bait, and water-use rows stayed closed.", "Rule 287: badur."),
    ("lexicon", "Balji remained visible dilly bag only; making, weaving, grass/black-palm material-source, carrying, ownership, and use rows stayed closed.", "Rule 287: balji."),
    ("lexicon", "Balur remained visible spear thrower/woomera only; throwing, defence, judgement, weapon-use, and euphemism rows stayed closed.", "Rule 287: balur."),
    ("lexicon", "Kaljan remained visible outrigger canoe only; travel, rowing, paddling, sea/river route, and ownership rows stayed closed.", "Rule 287: kaljan."),
    ("lexicon", "Dajal remained visible fighting spear only; spearing, fighting, killing, hunting, throwing, and material-source rows stayed closed.", "Rule 287: dajal."),
    ("lexicon", "Dakilji remained visible cup only; drinking, filling, washing, loan/post-contact expansion, and use rows stayed closed.", "Rule 287: dakilji."),
    ("lexicon", "Jidi remained visible torch only; fire, burning, lighting, making, bark-source, and night-travel rows stayed closed.", "Rule 287: jidi."),
    ("lexicon", "Jindal remained visible three-pronged spear only; homophonous jindal 'bite' and puncture/snake/dog/wound rows stayed closed.", "Rule 287: jindal."),
    ("lexicon", "Jundi remained visible pumice stone only; sharpening, rubbing, grinding, abrasive-use, and material-source rows stayed closed.", "Rule 287: jundi."),
    ("lexicon", "Karra remained visible rope/cord/string only; tying, binding, carrying, weaving, and use rows stayed closed.", "Rule 287: karra."),
    ("morphology", "All Rule 287 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 287: bare targets."),
    ("morphology", "The subject support forms stayed bare nominatives: ngali, ngaliny, yubal, yurra, and jana were not inflected for accusative, dative, locative, ablative, comitative, or possessive.", "Rule 287: bare nominative non-singular pronouns."),
    ("morphology", "Yaluy, yinyay, and nyajil stayed uninflected support heads; no demonstrative case, local-derived form, past nyajin, purposive nyaji-nka, reduplicated watching form, or support suffix was admitted.", "Rule 287: uninflected support."),
    ("morphology", "No target compound, object-use construction, material-source construction, place-name compound, pronoun-case construction, or productive reduplication was built from the Rule 287 heads.", "Rule 287: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajil for first dual exclusive here nonpast visual perception.", "Rule 287: 1du exclusive here band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajil for first dual inclusive there nonpast visual perception.", "Rule 287: 1du inclusive there band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajil for second dual here nonpast visual perception.", "Rule 287: 2du here band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yinyay nyajil for second plural there nonpast visual perception.", "Rule 287: 2pl there band."),
    ("syntax", "Rows 41-50 used Jana TARGET yaluy nyajil for third plural here nonpast visual perception.", "Rule 287: 3pl here band."),
    ("fidelity", "English stayed literal visual nonpast perception/reference prose: selected subject pronoun value, target label, here/there, and see only.", "Rule 287: literal English."),
    ("fidelity", "The batch did not convert dictionary source prose into fishing, making, material-source, canoe travel, rowing, spear throwing, fighting, biting, sharpening, tying, fire, burning, ownership, post-contact loan, place, story, or use claims.", "Rule 287: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style visual nonpast perception clauses; no action narrative, object-use instruction, weapon account, travel report, manufacturing prose, warning, mythic narrative, or story register was introduced.", "Rule 287: register."),
    ("process", "Rules 149-286 carry-forward traps stayed closed, especially Rule 287 artefact/tool complementary nonpast perception drift plus recent sky/celestial and water/landform traps and older fire, fauna, body, dwelling, source-prose, homograph, target-case, pronoun-case, demonstrative-case, perception-compound, target-compound, productive-reduplication, and support-inflection traps.", "Rule 287: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,547 if this closes; do not infer artefact use, weapon action, canoe travel, material source, target case, pronoun case, perception compound, past/purposive/reduplicated perception, productive reduplication, or support-inflection grammar from Rule 287.", "Rule 287: next cadence."),
]

LEXEMES = [
    ("badur", "noun", None, "NA", "hook", "batch-329: visible hook/hook-and-line complementary nonpast perception/reference only; fishing action rows closed."),
    ("balji", "noun", None, "NA", "dilly bag", "batch-329: visible dilly-bag complementary nonpast perception/reference only; making, material-source, carrying, and use rows closed."),
    ("balur", "noun", None, "NA", "spear thrower", "batch-329: visible spear-thrower/woomera complementary nonpast perception/reference only; throwing, defence, and weapon-use rows closed."),
    ("kaljan", "noun", None, "NA", "outrigger canoe", "batch-329: visible outrigger-canoe complementary nonpast perception/reference only; travel, rowing, paddling, route, and ownership rows closed."),
    ("dajal", "noun", None, "NA", "fighting spear", "batch-329: visible fighting-spear complementary nonpast perception/reference only; spearing, fighting, killing, hunting, throwing, and material-source rows closed."),
    ("dakilji", "noun", None, "NA", "cup", "batch-329: visible cup complementary nonpast perception/reference only; drinking, filling, washing, and post-contact expansion rows closed."),
    ("jidi", "noun", None, "NA", "torch", "batch-329: visible torch complementary nonpast perception/reference only; fire, burning, lighting, making, bark-source, and night-travel rows closed."),
    ("jindal", "noun", None, "NA", "three-pronged spear", "batch-329: visible three-pronged-spear complementary nonpast perception/reference only; homophonous bite verb and wound rows closed."),
    ("jundi", "noun", None, "NA", "pumice stone", "batch-329: visible pumice/carborundum stone complementary nonpast perception/reference only; sharpening/rubbing/grinding use rows closed."),
    ("karra", "noun", None, "NA", "rope", "batch-329: visible rope/cord/string complementary nonpast perception/reference only; tying, binding, carrying, weaving, and use rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-329: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-329: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-329: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-329: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-329: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-329: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-329: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-329: nonpast visual perception support only, corpus-conventional surface from nyaji-l see-NONPAST."),
]


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 or under_review != 50 or accepted:
        raise SystemExit(f"{LABEL} close precheck failed: total={total}, under_review={under_review}, accepted={accepted}")

    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-329-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 287 rows. Morphology checked bare artefact/tool nouns, bare nominative ngali/ngaliny/yubal/yurra/jana, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected visible artefact/tool senses only, with badur fishing, balji making/material, balur weapon-use, kaljan travel, dajal action, jidi fire, jindal bite, jundi use, and karra tying extensions closed. Syntax checked five complementary non-singular nonpast pronoun-perception frame bands. Fidelity checked literal visual nonpast 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 birungubay duplicate, fishing, making, material-source, canoe travel, rowing/paddling, spear throwing, fighting, biting, sharpening/rubbing, tying, fire/burning, post-contact loan object, target case, productive compound, productive reduplication, demonstrative case, pronoun case, perception compound, past/purposive/reduplicated perception drift, support inflection, or recent water/landform/sky/fire/fauna/body/dwelling 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 287 lessons covering source checks, duplicate avoidance, complementary nonpast perception support, artefact/tool scope, coverage, lexical target senses, morphology, syntax, fidelity, register, process traps, and handoff.", artifact_path=PROCESS_LOG, 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 287 targets and support heads.", artifact_path=PROCESS_LOG, created_at=NOW)
    db.execute("UPDATE sentences SET status='accepted', updated_at=? WHERE batch_id=?", (NOW, batch_id))
    db.execute("UPDATE batches SET notes=?, cheatsheet_version=?, guide_version=? WHERE id=?", (NOTES, "Rule 287 accepted", "operator-guide-2026-07-09", batch_id))
    verified_after, words_after = db.execute(
        """
        SELECT COUNT(*), SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()
    accepted_after = db.execute("SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status='accepted'", (batch_id,)).fetchone()[0]
    review_count = db.execute("SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (batch_id,)).fetchone()[0]
    lesson_count = 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-329-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="claude-main", detail=f"Closed Batch 329 / Rule 287 with {accepted_after} accepted rows, {review_count} review passes, {lesson_count} lessons, and {lexeme_logs} lexeme/source-log rows. Verified sentences moved {verified_before}->{verified_after}; Kuku words moved {words_before}->{words_after}.", command="python3 batch_scripts/close_329.py", output_excerpt=f"closed batch-329: accepted={accepted_after}, reviews={review_count}, lessons={lesson_count}, lexeme_logs={lexeme_logs}, verified {verified_before}->{verified_after}, kuku_words {words_before}->{words_after}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print(
        f"closed batch-329: accepted={accepted_after}, reviews={review_count}, lessons={lesson_count}, "
        f"lexeme_logs={lexeme_logs}, verified {verified_before}->{verified_after}, kuku_words {words_before}->{words_after}"
    )
    return 0


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