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

NOTES = (
    "VISIBLE TRADITIONAL WEAPON/TOOL COMPLEMENTARY NON-SINGULAR PAST PERCEPTION SWEEP AFTER RULE 293 "
    "(Rule 294). 50 rows. TARGETS: bangkal tongs, kurrajan spear point, dara bamboo spear stick, jaba stick, "
    "kunjuri shield, nambarr bamboo stick, wangal boomerang, manbir spear barb, wakay wooden sword, and wulburr "
    "bamboo spear stick. SUPPORT: bare nominative ngali, ngaliny, yubal, nganjin, and ngana plus yaluy/yinyay and "
    "nyajin. REVIEW: Rule 294 explicitly sources the past nyaji-ny/nyajin counterpart to Rule 293 and uses "
    "complementary local-demonstrative bands not previously accepted for these target/pronoun pairings. No cooking, "
    "earth-oven/vine source, turtle spearing, fire-hardening, nose-piercing, weapon use, throwing, hunting, fighting, "
    "piercing, cutting, material-source, target case, pronoun case, demonstrative case, target compound, productive "
    "reduplication, perception compound, nonpast/purposive/reduplicated perception drift, support inflection, or "
    "carried water/landform/sky/fire/fauna/body/dwelling drift was opened."
)

LESSONS = [
    ("source", "Rule 294 selected the same ten visible traditional weapon/tool target heads as Rule 293: bangkal, kurrajan, dara, jaba, kunjuri, nambarr, wangal, manbir, wakay, and wulburr.", "Rule 294: target inventory."),
    ("source", "Direct dictionary line readback was explicit: bangkal 1478-1489, kurrajan 16196-16207, dara 5215-5226, jaba 6843-6857, kunjuri 15915-15923, nambarr 21516-21526, wangal 25943-25951, manbir 17699-17707, wakay 25192-25202, and wulburr 27767-27776.", "Rule 294: 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, nganjin, and ngana.", "Rule 294: pronoun source."),
    ("source", "Patz grammar lines 2674-2686 supplied the non-singular person/number contrasts used here, including ngali exclusive dual, ngana inclusive plural, and yubal context.", "Rule 294: non-singular source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 294 used only bare local demonstratives.", "Rule 294: demonstrative source."),
    ("source", "Patz examples at lines 2023 and 2568-2571 supplied nyaji-ny 'see-PAST', and the inflection section at lines 3149-3162 supplied the nonpast/past contrast; Rule 294 used corpus-conventional nyajin as the past visual-perception surface.", "Rule 294: past perception source."),
    ("process", "Rule 294 was scoped as the sourced past counterpart to Rule 293's complementary local-demonstrative non-singular nonpast coverage, not as a new lexical or action field.", "Rule 294: complementary past scope."),
    ("process", "Exact preflight over all 50 planned surfaces returned no accepted, revised, or under-review collisions.", "Rule 294: duplicate preflight."),
    ("process", "Final preflight retained no durray, jinil, mirru, kurajan, ngurmu, birungubay, or biyul surfaces.", "Rule 294: excluded-head check."),
    ("process", "Token-aware target coverage before banking after Rule 293 was bangkal 109, kurrajan 43, dara 27, jaba 44, kunjuri 52, nambarr 42, wangal 67, manbir 35, wakay 36, and wulburr 36.", "Rule 294: target coverage audit."),
    ("process", "Support coverage before banking after Rule 293 was ngali 393, ngaliny 335, yubal 345, nganjin 248, ngana 915, yaluy 3172, yinyay 3464, and nyajin 600 by words_used JSON.", "Rule 294: support coverage audit."),
    ("lexicon", "Bangkal remained visible tongs only; cooking, kurrma earth-oven, voya vine, gathering, and action rows stayed closed.", "Rule 294: bangkal."),
    ("lexicon", "Kurrajan remained visible spear point only; turtle spearing, wattle source, fire-hardening, piercing, and use rows stayed closed.", "Rule 294: kurrajan."),
    ("lexicon", "Dara remained visible bamboo spear stick only; spear use, bamboo-source, hunting, fighting, throwing, and material-source rows stayed closed.", "Rule 294: dara."),
    ("lexicon", "Jaba remained visible stick only; sapling, post, horn, walking-use, and plant rows stayed closed.", "Rule 294: jaba."),
    ("lexicon", "Kunjuri remained visible shield only; fighting, defence, body-covering, ownership, and weapon-use rows stayed closed.", "Rule 294: kunjuri."),
    ("lexicon", "Nambarr remained visible bamboo stick only; nose-piercing and implement-use rows stayed closed.", "Rule 294: nambarr."),
    ("lexicon", "Wangal remained visible boomerang only; throwing, hunting, fighting, play, return, and travel rows stayed closed.", "Rule 294: wangal."),
    ("lexicon", "Manbir remained visible spear barb only; stabbing, hooking, piercing, injury, spear-use, and component-manufacture rows stayed closed.", "Rule 294: manbir."),
    ("lexicon", "Wakay remained visible wooden sword only; people-group source prose, fighting, cutting, and use rows stayed closed.", "Rule 294: wakay."),
    ("lexicon", "Wulburr remained visible bamboo spear stick only; spear use, bamboo-source, hunting, fighting, throwing, and material-source rows stayed closed.", "Rule 294: wulburr."),
    ("morphology", "All Rule 294 target nouns stayed bare absolutive objects: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 294: bare targets."),
    ("morphology", "All five subject support forms stayed bare nominatives: no accusative, dative, locative, ablative, comitative, possessive, or other pronoun case form was admitted.", "Rule 294: bare nominative pronouns."),
    ("morphology", "Yaluy, yinyay, and nyajin stayed uninflected support heads; no demonstrative case, local-derived form, nonpast nyajil, purposive nyaji-nka, reduplicated watching form, or support suffix was admitted.", "Rule 294: 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 294 heads.", "Rule 294: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajin for first dual exclusive there past visual perception.", "Rule 294: 1du exclusive there band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajin for first dual inclusive here past visual perception.", "Rule 294: 1du inclusive here band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajin for second dual there past visual perception.", "Rule 294: 2du there band."),
    ("syntax", "Rows 31-40 used Nganjin TARGET yaluy nyajin for first plural exclusive here past visual perception.", "Rule 294: 1pl exclusive here band."),
    ("syntax", "Rows 41-50 used Ngana TARGET yinyay nyajin for first plural inclusive there past visual perception.", "Rule 294: 1pl inclusive there band."),
    ("fidelity", "English stayed literal visual past perception/reference prose: selected subject pronoun value, target label, here/there, and saw only.", "Rule 294: literal English."),
    ("fidelity", "The batch did not convert dictionary source prose into cooking, vine source, earth-oven use, turtle spearing, fire-hardening, nose-piercing, throwing, hunting, fighting, piercing, cutting, ownership, place, story, or use claims.", "Rule 294: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style visual past perception clauses; no action narrative, object-use instruction, weapon account, manufacturing prose, warning, mythic narrative, or story register was introduced.", "Rule 294: register."),
    ("process", "Rules 149-293 carry-forward traps stayed closed, especially recent weapon/tool perception traps plus older sky, water/landform, fire, fauna, body, dwelling, source-prose, homograph, target-case, pronoun-case, demonstrative-case, perception-compound, target-compound, productive-reduplication, and support-inflection traps.", "Rule 294: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,897 if this closes; do not infer weapon action, cooking, turtle spearing, material source, nose piercing, target case, pronoun case, perception compound, nonpast/purposive/reduplicated perception, productive reduplication, or support-inflection grammar from Rule 294.", "Rule 294: next cadence."),
]

LEXEMES = [
    ("bangkal", "noun", None, "NA", "tongs", "batch-336: visible tongs past perception/reference only; cooking, vine, kurrma, and action rows closed."),
    ("kurrajan", "noun", None, "NA", "spear point", "batch-336: visible spear-point past perception/reference only; turtle-spearing, wattle, fire-hardening, piercing, and use rows closed."),
    ("dara", "noun", None, "NA", "bamboo spear stick", "batch-336: visible bamboo-spear-stick past perception/reference only; spear-use and material-source rows closed."),
    ("jaba", "noun", None, "NA", "stick", "batch-336: visible stick past perception/reference only; sapling, post, horn, walking-use, and plant rows closed."),
    ("kunjuri", "noun", None, "NA", "shield", "batch-336: visible shield past perception/reference only; fighting, defence, body-covering, ownership, and use rows closed."),
    ("nambarr", "noun", None, "NA", "bamboo stick", "batch-336: visible bamboo-stick past perception/reference only; nose-piercing and implement-use rows closed."),
    ("wangal", "noun", None, "NA", "boomerang", "batch-336: visible boomerang past perception/reference only; throwing, hunting, fighting, play, return, and travel rows closed."),
    ("manbir", "noun", None, "NA", "spear barb", "batch-336: visible spear-barb past perception/reference only; stabbing, hooking, piercing, injury, spear-use, and manufacture rows closed."),
    ("wakay", "noun", None, "NA", "wooden sword", "batch-336: visible wooden-sword past perception/reference only; people-group source prose, fighting, cutting, and use rows closed."),
    ("wulburr", "noun", None, "NA", "bamboo spear stick", "batch-336: visible bamboo-spear-stick past perception/reference only; spear-use and material-source rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-336: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-336: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-336: bare nominative subject support only."),
    ("nganjin", "pronoun", None, "NA", "first plural exclusive nominative", "batch-336: bare nominative subject support only."),
    ("ngana", "pronoun", None, "NA", "first plural inclusive nominative", "batch-336: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-336: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-336: bare local demonstrative support only."),
    ("nyajin", "verb", "l", "NA", "saw", "batch-336: past visual perception support only, corpus-conventional surface from nyaji-ny see-PAST."),
]


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-336-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 294 rows. Morphology checked bare traditional weapon/tool noun objects, five bare non-singular nominative pronoun forms, bare yaluy/yinyay, and nyajin past only. Lexicon checked selected visible target senses only, with cooking/vine/earth-oven, turtle/fire/piercing, nose-piercing, weapon-use, throwing, hunting, fighting, cutting, and material-source extensions closed. Syntax checked five complementary pronoun-perception bands. Fidelity checked literal visual past 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 collided durray/jinil/mirru/kurajan/ngurmu/birungubay heads, Nyungkal biyul, cooking, earth-oven/vine source, turtle spearing, fire-hardening, nose-piercing, weapon use, throwing, hunting, fighting, piercing, cutting, target case, productive compound, productive reduplication, demonstrative case, pronoun case, perception compound, nonpast/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 294 lessons covering source checks, complementary past scope, duplicate avoidance, 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 294 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 294 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-336-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="claude-main", detail=f"Closed Batch 336 / Rule 294 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_336.py", output_excerpt=f"closed batch-336: 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-336: 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())
