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

NOTES = (
    "VISIBLE SKY/CELESTIAL NON-SINGULAR NONPAST PRONOUN PERCEPTION SWEEP AFTER RULE 283 "
    "(Rule 284). 50 rows. TARGETS: balbay lightning, binyu shooting star, dawar star, jiri sky, kaba rain, "
    "kija moon, wungar sun, kurrinkurrin mackerel sky, kurrubijal morning star, and yiril rainbow. SUPPORT: bare "
    "nominative ngali, ngaliny, yubal, yurra, and jana plus yaluy/yinyay and nyajil. FRAMES: Ngali TARGET "
    "yinyay nyajil, Ngaliny TARGET yaluy nyajil, Yubal TARGET yinyay nyajil, Yurra TARGET yaluy nyajil, and "
    "Jana TARGET yinyay nyajil. REVIEW: initial target set with ngurrban was rejected after duplicate "
    "Jana ngurrban yinyay nyajil. from Batch 195; sourced wungar fills the final slot. No moon/month/place-story, "
    "lightning strike, death-spirit/death-omen, heaven/sky-mob/fine-day compound, rain event, sun-time/hot-season "
    "compound, rainbow story/snake/water-hole extension, target case, pronoun case, demonstrative case, target "
    "compound, productive reduplication, perception compound, past/purposive/reduplicated perception drift, support "
    "inflection, or recent water/landform/fauna/body/dwelling/fire drift was opened."
)

LESSONS = [
    ("source", "Rule 284 selected ten visible sky/celestial target heads: balbay, binyu, dawar, jiri, kaba, kija, wungar, kurrinkurrin, kurrubijal, and yiril.", "Rule 284: visible target inventory."),
    ("source", "Direct dictionary line readback was explicit: balbay 900-911, binyu 3063-3074, dawar 5374-5382, jiri 9720-9730, kaba 11671-11679, kija 14143-14155, wungar 28081-28089, kurrinkurrin 16406-16419, kurrubijal 16557-16567, and yiril 30419-30427.", "Rule 284: 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 284: 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 284: non-singular source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 284 used only bare local demonstratives.", "Rule 284: demonstrative source."),
    ("source", "Patz section 3.8.3.2 lines 3043-3049 supplied nyaji-l 'see'; Rule 284 used corpus-conventional nyajil as the nonpast visual-perception surface only.", "Rule 284: nonpast perception source."),
    ("source", "Patz lines 2568-2571 supplied nyaji-ny 'see-PAST' only as past contrast; Rule 284 did not use past nyajin.", "Rule 284: past contrast."),
    ("process", "The first Rule 284 target set retained ngurrban but exact duplicate preflight found Jana ngurrban yinyay nyajil. in Batch 195; ngurrban was replaced with sourced wungar sun rather than special-casing one row.", "Rule 284: ngurrban replacement."),
    ("process", "Final preflight over the wungar replacement set returned 50 unique surfaces and no accepted, revised, or under-review collisions.", "Rule 284: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 283 was balbay 28, binyu 11, dawar 67, jiri 96, kaba 248, kija 97, wungar 655, kurrinkurrin 15, kurrubijal 28, and yiril 30.", "Rule 284: target coverage audit."),
    ("process", "Support coverage before banking after Rule 283 was ngali 323, ngaliny 265, yubal 275, yurra 280, jana 943, yaluy 2922, yinyay 3214, and nyajil 3047 by words_used JSON.", "Rule 284: support coverage audit."),
    ("lexicon", "Balbay remained visible lightning only; lightning-strike, danger, event, and causation rows stayed closed.", "Rule 284: balbay."),
    ("lexicon", "Binyu remained visible shooting star only; death-spirit, death-omen, mourning, and story rows stayed closed.", "Rule 284: binyu."),
    ("lexicon", "Dawar remained star only; straw-hat homograph dawarr and post-contact object rows stayed closed.", "Rule 284: dawar."),
    ("lexicon", "Jiri remained visible sky only; heaven, sky-mob, fine-day, cloudless-sky, place-name, and post-contact object rows stayed closed.", "Rule 284: jiri."),
    ("lexicon", "Kaba remained visible rain only; rain falling, rain coming, rainbird, no-rain, storm, weather-predication, and event rows stayed closed.", "Rule 284: kaba."),
    ("lexicon", "Kija remained visible moon only; month, Roaring Meg Falls, moon-story, creation-place, and place-name rows stayed closed.", "Rule 284: kija."),
    ("lexicon", "Wungar remained visible sun only; sunrise, sunset, midday, hot-season, sun-locative, sun-time, and motion-into-sun rows stayed closed.", "Rule 284: wungar."),
    ("lexicon", "Kurrinkurrin remained lexicalized mackerel sky only; its reduplicated source form was not generalized to productive reduplication.", "Rule 284: kurrinkurrin."),
    ("lexicon", "Kurrubijal remained morning star/Venus only; star story, time, place, and astronomy expansion rows stayed closed.", "Rule 284: kurrubijal."),
    ("lexicon", "Yiril remained visible rainbow only; rainbow-snake, story, water-hole, place-name, and yirri/yiri homograph drift stayed closed.", "Rule 284: yiril."),
    ("morphology", "All Rule 284 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 284: 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 284: 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 284: uninflected support."),
    ("morphology", "No target compound, place-name compound, weather-event construction, story construction, pronoun-case construction, or productive reduplication was built from the Rule 284 heads.", "Rule 284: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajil for first dual exclusive there nonpast visual perception.", "Rule 284: 1du exclusive there band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajil for first dual inclusive here nonpast visual perception.", "Rule 284: 1du inclusive here band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajil for second dual there nonpast visual perception.", "Rule 284: 2du there band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yaluy nyajil for second plural here nonpast visual perception.", "Rule 284: 2pl here band."),
    ("syntax", "Rows 41-50 used Jana TARGET yinyay nyajil for third plural there nonpast visual perception.", "Rule 284: 3pl there band."),
    ("fidelity", "English stayed literal visual nonpast perception/reference prose: selected subject pronoun value, target label, here/there, and see only.", "Rule 284: literal English."),
    ("fidelity", "The batch did not convert dictionary alternate glosses or source prose into month/place-story, lightning-strike, death-spirit/death-omen, heaven, sky-mob, fine-day, rain-event, sun-time/hot-season, rainbow-story, snake, water-hole, weather-event, danger, ownership, source, or use claims.", "Rule 284: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style visual nonpast perception clauses; no mythic narrative, omen report, weather forecast, astronomical explanation, route instruction, warning, source-prose, or story register was introduced.", "Rule 284: register."),
    ("process", "Rules 149-283 carry-forward traps stayed closed, especially recent visible sky/celestial and water/landform traps plus 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 284: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,397 if this closes; do not infer sky/celestial weather-event, story, death-omen, time-compound, target-case, pronoun-case, perception-compound, past/purposive/reduplicated perception, productive-reduplication, or support-inflection grammar from Rule 284.", "Rule 284: next cadence."),
]

LEXEMES = [
    ("balbay", "noun", None, "NA", "lightning", "batch-326: visible lightning nonpast perception/reference only; strike, danger, event, and causation rows closed."),
    ("binyu", "noun", None, "NA", "shooting star", "batch-326: visible shooting-star nonpast perception/reference only; death-spirit, death-omen, mourning, and story rows closed."),
    ("dawar", "noun", None, "NA", "star", "batch-326: visible star nonpast perception/reference only; dawarr straw-hat homograph closed."),
    ("jiri", "noun", None, "NA", "sky", "batch-326: visible sky nonpast perception/reference only; heaven, sky-mob, fine-day, cloudless-sky, and place-name rows closed."),
    ("kaba", "noun", None, "NA", "rain", "batch-326: visible rain nonpast perception/reference only; falling/coming/no-rain/rainbird/weather-event rows closed."),
    ("kija", "noun", None, "NA", "moon", "batch-326: visible moon nonpast perception/reference only; month, Roaring Meg Falls, moon-story, creation-place, and place-name rows closed."),
    ("wungar", "noun", None, "NA", "sun", "batch-326: visible sun nonpast perception/reference only; sunrise, sunset, midday, hot-season, sun-locative, and time rows closed."),
    ("kurrinkurrin", "noun", None, "NA", "mackerel sky", "batch-326: visible mackerel-sky nonpast perception/reference only; lexicalized reduplication, not productive pattern."),
    ("kurrubijal", "noun", None, "NA", "morning star", "batch-326: visible morning-star nonpast perception/reference only; time/story/place expansion closed."),
    ("yiril", "noun", None, "NA", "rainbow", "batch-326: visible rainbow nonpast perception/reference only; rainbow-snake/story/water-hole/place-name rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-326: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-326: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-326: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-326: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-326: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-326: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-326: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-326: 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-326-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 284 rows. Morphology checked bare sky/celestial nouns, bare nominative ngali/ngaliny/yubal/yurra/jana, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected visible sky/celestial senses only, with binyu/jiri/kaba/kija/wungar/yiril source-prose extensions closed. Syntax checked five 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 ngurrban duplicate, month/place-story, lightning strike, death-spirit/death-omen, heaven/sky-mob/fine-day compound, rain falling/coming/no-rain/rainbird/weather-event, sun-time/hot-season/sun-locative, rainbow story/snake/water-hole, target case, productive compound, productive reduplication, demonstrative case, pronoun case, perception compound, past/purposive/reduplicated perception drift, support inflection, or recent water/landform/fauna/body/dwelling/fire 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 284 lessons covering source checks, duplicate avoidance, nonpast perception support, sky/celestial 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 284 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 284 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-326-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="claude-main", detail=f"Closed Batch 326 / Rule 284 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_326.py", output_excerpt=f"closed batch-326: 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-326: 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())
