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

NOTES = (
    "VISIBLE WATER/LANDFORM NON-SINGULAR COMPLEMENTARY NONPAST PRONOUN PERCEPTION SWEEP AFTER RULE 280 "
    "(Rule 281). 50 rows. TARGETS: dajali deep water, jalun sea, jirka spring, bubu ground/earth, wawubaja "
    "river, daburri swamp, dulngku reef, yilki creek, yiri waterfall, and yirri running water. 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: first target set with manjal was rejected after exact duplicate pressure; "
    "no pronoun case, water-use, drinking/getting/filling/washing/swimming, travel, route, road, crossing, flood, "
    "tide, salt-pan, whale-oil, spring-season, place-name, bubu country/place extension, wawubaja travel/route/"
    "crossing/bank/place-name/water-use, daburri ecology/use, dulngku fishing/navigation, source-use, story, "
    "water-spirit, danger, ownership, target case, demonstrative case, target compound, productive reduplication, "
    "perception compound, past/purposive/reduplicated perception drift, support inflection, or recent sky/fire/"
    "fauna/body/dwelling drift was opened."
)

LESSONS = [
    ("source", "Rule 281 selected ten visible water/landform target heads: dajali, jalun, jirka, bubu, wawubaja, daburri, dulngku, yilki, yiri, and yirri.", "Rule 281: visible target inventory."),
    ("source", "Direct dictionary line readback was explicit: dajali 4510-4518, jalun 7612-7620, jirka 9803-9813, bubu 3452-3470, wawubaja 26813-26821, daburri 4431-4441, dulngku 6521-6529, yilki 30031-30039, yiri 30410-30418, and yirri 30507-30515.", "Rule 281: 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 281: 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 281: non-singular source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 281 used only bare local demonstratives.", "Rule 281: demonstrative source."),
    ("source", "Patz lines 3043-3049 supplied nyaji-l 'see' as the nonpast form; Rule 281 used corpus-conventional nyajil as the nonpast visual-perception surface only.", "Rule 281: nonpast perception source."),
    ("source", "Patz lines 2568-2571 supplied nyaji-ny 'see-PAST' only as contrast; Rule 281 did not use past nyajin.", "Rule 281: past contrast."),
    ("process", "The first Rule 281 target set retained manjal but exact duplicate preflight found Jana manjal yinyay nyajil. in Batch 194; manjal was replaced with sourced wawubaja river rather than special-casing one row.", "Rule 281: duplicate avoidance."),
    ("process", "Exact duplicate preflight over the final 50 Rule 281 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 281: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 280 was bubu 970, daburri 44, dajali 98, dulngku 63, jalun 255, jirka 34, wawubaja 394, yilki 36, yiri 30, and yirri 30.", "Rule 281: target coverage audit."),
    ("process", "Support coverage before banking after Rule 280 was ngali 293, ngaliny 235, yubal 245, yurra 250, jana 913, yaluy 2862, yinyay 3124, and nyajil 2997 by words_used JSON.", "Rule 281: support coverage audit."),
    ("lexicon", "Dajali remained deep water only; no danger, crossing, swimming, travel, route, or depth-event predicate was imported.", "Rule 281: dajali."),
    ("lexicon", "Jalun remained sea only; flood, seafarer, sea-fauna, salt-water, route, and tide rows stayed closed.", "Rule 281: jalun."),
    ("lexicon", "Jirka remained spring as a water source only; season and place-name readings stayed closed.", "Rule 281: jirka."),
    ("lexicon", "Bubu remained visible ground/earth only; country, belonging, place, Shipton's Flats example prose, and dirtiness rows stayed closed.", "Rule 281: bubu."),
    ("lexicon", "Wawubaja remained visible river only; travel, route, crossing, bank, place-name, and water-use rows stayed closed.", "Rule 281: wawubaja."),
    ("lexicon", "Daburri remained swamp/brackish swamp water only; ecology, use, crossing, danger, and place rows stayed closed.", "Rule 281: daburri."),
    ("lexicon", "Dulngku remained reef only; fishing, travel, navigation, danger, ecology, and place rows stayed closed.", "Rule 281: dulngku."),
    ("lexicon", "Yilki remained creek only; creek-place, crossing, travel, ecology, and use prose stayed closed.", "Rule 281: yilki."),
    ("lexicon", "Yiri remained waterfall only; no rainbow yiril, escape yiril, place-name, water-use, or story row was imported.", "Rule 281: yiri."),
    ("lexicon", "Yirri remained running water only; yirri-damal leak, current/flow event, and water-use rows stayed closed.", "Rule 281: yirri."),
    ("morphology", "All Rule 281 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 281: 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 281: 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 281: uninflected support."),
    ("morphology", "No target compound, place-name compound, water-use construction, route/travel construction, pronoun-case construction, or productive reduplication was built from the Rule 281 heads.", "Rule 281: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajil for first dual exclusive there nonpast visual perception.", "Rule 281: 1du exclusive there band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajil for first dual inclusive here nonpast visual perception.", "Rule 281: 1du inclusive here band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajil for second dual there nonpast visual perception.", "Rule 281: 2du there band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yaluy nyajil for second plural here nonpast visual perception.", "Rule 281: 2pl here band."),
    ("syntax", "Rows 41-50 used Jana TARGET yinyay nyajil for third plural there nonpast visual perception.", "Rule 281: 3pl there band."),
    ("fidelity", "English stayed literal visual nonpast perception/reference prose: selected subject pronoun value, target label, here/there, and see only.", "Rule 281: literal English."),
    ("fidelity", "The batch did not convert dictionary alternate glosses or source prose into drinking, getting, filling, washing, swimming, crossing, travel, route, flood, tide, salt-pan, whale-oil, season, place-name, story, ecology, fauna/flora, water-spirit, danger, ownership, country/belonging, dirtiness, fishing/navigation, or use claims.", "Rule 281: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style visual nonpast perception clauses; no route instruction, travel narrative, ecological note, water-use instruction, danger warning, country/place statement, fishing/navigation note, or story register was introduced.", "Rule 281: register."),
    ("process", "Rules 149-280 carry-forward traps stayed closed, especially recent visible water/landform traps plus older sky, fire, fauna, body, dwelling, and source-prose traps.", "Rule 281: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,247 if this closes; do not infer water-use, travel, route, place-name, flood/tide, ecology, story, bubu country/place, wawubaja route/crossing, daburri swamp-use, dulngku reef-use, target-case, pronoun-case, perception-compound, past/purposive/reduplicated perception, or support-inflection grammar from Rule 281.", "Rule 281: next cadence."),
]

LEXEMES = [
    ("dajali", "noun", None, "NA", "deep water", "batch-323: visible deep-water nonpast perception/reference only; danger, crossing, swimming, and route rows closed."),
    ("jalun", "noun", None, "NA", "sea", "batch-323: visible sea nonpast perception/reference only; flood, seafarer, sea-fauna, tide, and route rows closed."),
    ("jirka", "noun", None, "NA", "spring", "batch-323: visible spring/water-source nonpast perception/reference only; season and place-name rows closed."),
    ("bubu", "noun", None, "NA", "ground", "batch-323: visible ground/earth nonpast perception/reference only; country, belonging, place, and dirtiness rows closed."),
    ("wawubaja", "noun", None, "NA", "river", "batch-323: visible river nonpast perception/reference only; travel, route, crossing, bank, place-name, and water-use rows closed."),
    ("daburri", "noun", None, "NA", "swamp", "batch-323: visible swamp/brackish-swamp-water nonpast perception/reference only; ecology, use, crossing, danger, and place rows closed."),
    ("dulngku", "noun", None, "NA", "reef", "batch-323: visible reef nonpast perception/reference only; fishing, travel, navigation, danger, ecology, and place rows closed."),
    ("yilki", "noun", None, "NA", "creek", "batch-323: visible creek nonpast perception/reference only; creek-place, crossing, travel, ecology, and use prose closed."),
    ("yiri", "noun", None, "NA", "waterfall", "batch-323: visible waterfall nonpast perception/reference only; rainbow yiril, escape yiril, place-name, water-use, and story rows closed."),
    ("yirri", "noun", None, "NA", "running water", "batch-323: visible running-water nonpast perception/reference only; yirri-damal leak and water-use rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-323: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-323: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-323: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-323: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-323: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-323: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-323: bare local demonstrative support only."),
    ("nyajil", "verb", "l", "NA", "see", "batch-323: nonpast visual perception support only, corpus-conventional surface from nyaji-l see.NPST."),
]


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-323-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 281 rows. Morphology checked bare water/landform nouns, bare nominative ngali/ngaliny/yubal/yurra/jana, bare yaluy/yinyay, and nyajil nonpast only. Lexicon checked selected visible water/landform senses only, with bubu/wawubaja/daburri/dulngku restricted to literal reference. 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 pronoun case, drinking, getting, filling, washing, swimming, crossing, travel, route, road, flood, tide, salt-pan, whale-oil, spring-season, place-name, bubu country/place extension, wawubaja travel/route/crossing/bank/place-name/water-use, daburri ecology/use, dulngku fishing/navigation, mountain story, water-source use, water spirit, fish/shellfish/reptile/plant/ecology, danger, ownership, target case, productive compound, productive reduplication, demonstrative case, perception compound, past/purposive/reduplicated perception drift, support inflection, or recent 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 281 lessons covering source checks, duplicate avoidance, nonpast perception support, water/landform 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 281 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 281 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-323-verify'").fetchone()[0]
    record_event(
        db,
        batch_label=LABEL,
        phase="close",
        event_type="close-success",
        actor="claude-main",
        detail=f"Closed Batch 323 / Rule 281 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_323.py",
        output_excerpt=f"closed batch-323: 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-323: 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())
