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

NOTES = (
    "VISIBLE WATER/LANDFORM NON-SINGULAR COMPLEMENTARY PAST PRONOUN PERCEPTION SWEEP AFTER RULE 281 "
    "(Rule 282). 50 rows. TARGETS: bubu ground/earth, dajali deep water, jalun sea, jirka spring, jukar sand, "
    "manjal mountain, wawubaja river, yilki creek, yiri waterfall, and yirri running water. SUPPORT: bare "
    "nominative ngali, ngaliny, yubal, yurra, and jana plus yaluy/yinyay and nyajin. FRAMES: Ngali TARGET "
    "yinyay nyajin, Ngaliny TARGET yaluy nyajin, Yubal TARGET yinyay nyajin, Yurra TARGET yaluy nyajin, and "
    "Jana TARGET yinyay nyajin. REVIEW: first target set with bana was rejected after exact duplicate pressure; "
    "daburri was also rejected in this frame set; 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, jukar sand-compound/source-prose, wawubaja travel/route/crossing/bank/place-name/"
    "water-use, mountain story, water-source use, water-spirit, danger, ownership, target case, demonstrative case, "
    "target compound, productive reduplication, perception compound, nonpast/purposive/reduplicated perception drift, "
    "support inflection, or recent sky/fire/fauna/body/dwelling drift was opened."
)

LESSONS = [
    ("source", "Rule 282 selected ten visible water/landform target heads: bubu, dajali, jalun, jirka, jukar, manjal, wawubaja, yilki, yiri, and yirri.", "Rule 282: visible target inventory."),
    ("source", "Direct dictionary line readback was explicit: bubu 3452-3470, dajali 4510-4518, jalun 7612-7620, jirka 9803-9813, jukar 10254-10262, manjal 17832-17840, wawubaja 26813-26821, yilki 30031-30039, yiri 30410-30418, and yirri 30507-30515.", "Rule 282: 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 282: 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 282: non-singular source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 282 used only bare local demonstratives.", "Rule 282: demonstrative source."),
    ("source", "Patz lines 2568-2571 supplied nyaji-ny 'see-PAST'; Rule 282 used corpus-conventional nyajin as the past visual-perception surface only.", "Rule 282: past perception source."),
    ("source", "Patz lines 3043-3049 supplied nyaji-l 'see' only as nonpast contrast; Rule 282 did not use nonpast nyajil.", "Rule 282: nonpast contrast."),
    ("process", "The first Rule 282 target set retained bana but exact duplicate preflight found Jana bana yinyay nyajin. in Batch 193; bana was replaced with sourced bubu ground/earth rather than special-casing one row.", "Rule 282: duplicate avoidance."),
    ("process", "A daburri replacement candidate was also rejected because Jana daburri yinyay nyajin. already existed in Batch 194; final preflight over the bubu set returned no accepted, revised, or under-review collisions.", "Rule 282: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 281 was bubu 975, dajali 103, jalun 260, jirka 39, jukar 192, manjal 108, wawubaja 399, yilki 41, yiri 35, and yirri 35.", "Rule 282: target coverage audit."),
    ("process", "Support coverage before banking after Rule 281 was ngali 303, ngaliny 245, yubal 255, yurra 260, jana 923, yaluy 2882, yinyay 3154, and nyajin 300 by words_used JSON.", "Rule 282: support coverage audit."),
    ("lexicon", "Bubu remained visible ground/earth only; country, belonging, place, Shipton's Flats example prose, and dirtiness rows stayed closed.", "Rule 282: bubu."),
    ("lexicon", "Dajali remained deep water only; no danger, crossing, swimming, travel, route, or depth-event predicate was imported.", "Rule 282: dajali."),
    ("lexicon", "Jalun remained sea only; flood, seafarer, sea-fauna, salt-water, route, and tide rows stayed closed.", "Rule 282: jalun."),
    ("lexicon", "Jirka remained spring as a water source only; season and place-name readings stayed closed.", "Rule 282: jirka."),
    ("lexicon", "Jukar remained sand only; sandfly, sand goanna, sand whiting, beach-use, material, and compound rows stayed closed.", "Rule 282: jukar."),
    ("lexicon", "Manjal remained mountain only; mountain story, dog legend, route, and place-name prose stayed closed.", "Rule 282: manjal."),
    ("lexicon", "Wawubaja remained visible river only; travel, route, crossing, bank, place-name, and water-use rows stayed closed.", "Rule 282: wawubaja."),
    ("lexicon", "Yilki remained creek only; creek-place, crossing, travel, ecology, and use prose stayed closed.", "Rule 282: yilki."),
    ("lexicon", "Yiri remained waterfall only; no rainbow yiril, escape yiril, place-name, water-use, or story row was imported.", "Rule 282: yiri."),
    ("lexicon", "Yirri remained running water only; yirri-damal leak, current/flow event, and water-use rows stayed closed.", "Rule 282: yirri."),
    ("morphology", "All Rule 282 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 282: 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 282: bare nominative non-singular 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 282: 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 282 heads.", "Rule 282: no compounds or reduplication."),
    ("syntax", "Rows 1-10 used Ngali TARGET yinyay nyajin for first dual exclusive there past visual perception.", "Rule 282: 1du exclusive there band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yaluy nyajin for first dual inclusive here past visual perception.", "Rule 282: 1du inclusive here band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yinyay nyajin for second dual there past visual perception.", "Rule 282: 2du there band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yaluy nyajin for second plural here past visual perception.", "Rule 282: 2pl here band."),
    ("syntax", "Rows 41-50 used Jana TARGET yinyay nyajin for third plural there past visual perception.", "Rule 282: 3pl there band."),
    ("fidelity", "English stayed literal visual past perception/reference prose: selected subject pronoun value, target label, here/there, and saw only.", "Rule 282: 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, sand species, or use claims.", "Rule 282: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style visual past 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 282: register."),
    ("process", "Rules 149-281 carry-forward traps stayed closed, especially recent visible water/landform traps plus older sky, fire, fauna, body, dwelling, and source-prose traps.", "Rule 282: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,297 if this closes; do not infer water-use, travel, route, place-name, flood/tide, ecology, story, bubu country/place, jukar compounds, wawubaja route/crossing, target-case, pronoun-case, perception-compound, nonpast/purposive/reduplicated perception, or support-inflection grammar from Rule 282.", "Rule 282: next cadence."),
]

LEXEMES = [
    ("bubu", "noun", None, "NA", "ground", "batch-324: visible ground/earth past perception/reference only; country, belonging, place, and dirtiness rows closed."),
    ("dajali", "noun", None, "NA", "deep water", "batch-324: visible deep-water past perception/reference only; danger, crossing, swimming, and route rows closed."),
    ("jalun", "noun", None, "NA", "sea", "batch-324: visible sea past perception/reference only; flood, seafarer, sea-fauna, tide, and route rows closed."),
    ("jirka", "noun", None, "NA", "spring", "batch-324: visible spring/water-source past perception/reference only; season and place-name rows closed."),
    ("jukar", "noun", None, "NA", "sand", "batch-324: visible sand past perception/reference only; sandfly, sand goanna, sand whiting, beach-use, and material rows closed."),
    ("manjal", "noun", None, "NA", "mountain", "batch-324: visible mountain past perception/reference only; mountain story, dog legend, route, and place-name prose closed."),
    ("wawubaja", "noun", None, "NA", "river", "batch-324: visible river past perception/reference only; travel, route, crossing, bank, place-name, and water-use rows closed."),
    ("yilki", "noun", None, "NA", "creek", "batch-324: visible creek past perception/reference only; creek-place, crossing, travel, ecology, and use prose closed."),
    ("yiri", "noun", None, "NA", "waterfall", "batch-324: visible waterfall past perception/reference only; rainbow yiril, escape yiril, place-name, water-use, and story rows closed."),
    ("yirri", "noun", None, "NA", "running water", "batch-324: visible running-water past perception/reference only; yirri-damal leak and water-use rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-324: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-324: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-324: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-324: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-324: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-324: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-324: bare local demonstrative support only."),
    ("nyajin", "verb", "l", "NA", "saw", "batch-324: 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-324-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 282 rows. Morphology checked bare water/landform nouns, bare nominative ngali/ngaliny/yubal/yurra/jana, bare yaluy/yinyay, and nyajin past only. Lexicon checked selected visible water/landform senses only, with bubu/jukar/wawubaja restricted to literal reference. Syntax checked five complementary non-singular past pronoun-perception frame 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 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, jukar sand species/material/source-prose, wawubaja travel/route/crossing/bank/place-name/water-use, mountain story, water-source use, water spirit, fish/shellfish/reptile/plant/ecology, danger, ownership, target case, productive compound, productive reduplication, demonstrative case, perception compound, nonpast/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 282 lessons covering source checks, duplicate avoidance, past 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 282 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 282 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-324-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="claude-main", detail=f"Closed Batch 324 / Rule 282 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_324.py", output_excerpt=f"closed batch-324: 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-324: 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())
