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

NOTES = (
    "VISIBLE WATER/LANDFORM NON-SINGULAR PAST PRONOUN PERCEPTION SWEEP AFTER RULE 276 (Rule 277). 50 rows. "
    "TARGETS: bana water, dajali deep water, jalun sea, jirka spring, jukar sand, manjal mountain, wawubaja river, "
    "yilki creek, yiri waterfall, and yirri running water. SUPPORT: bare non-singular nominative ngali, ngaliny, "
    "yubal, yurra, and jana plus yaluy/yinyay and nyajin. FRAMES: Ngali TARGET yaluy nyajin, Ngaliny TARGET yinyay "
    "nyajin, Yubal TARGET yaluy nyajin, Yurra TARGET yinyay nyajin, and Jana TARGET yaluy nyajin. REVIEW: no pronoun "
    "case, water-use, drinking/getting/filling/washing/swimming, travel, route, road, crossing, flood, tide, "
    "salt-pan, whale-oil, spring-season, place-name, source-use, ecology, story, water-spirit, danger, ownership, "
    "target case, demonstrative case, target compound, productive reduplication, perception compound, support "
    "inflection, or recent sky/fire/fauna/body/dwelling drift was opened."
)

LESSONS = [
    ("source", "Rule 277 retained ten visible water/landform target heads from the fresh Rule 276 source pass: bana, dajali, jalun, jirka, jukar, manjal, wawubaja, yilki, yiri, and yirri.", "Rule 277: visible target inventory."),
    ("source", "Direct dictionary line readback remained explicit: bana 1264-1272, 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 277: 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 277: pronoun source."),
    ("source", "Patz grammar lines 2674 and 2682-2686 supplied the non-singular pronoun distinctions used here: ngali first dual exclusive, ngaliny first dual inclusive, yubal second dual, yurra second plural, and jana third plural.", "Rule 277: non-singular pronoun source."),
    ("source", "Patz Table 3.12 lines 2838-2845 supplied Yalanji yaluy 'here' and yinyay 'there'; Rule 277 used only bare local demonstratives.", "Rule 277: demonstrative source."),
    ("source", "Patz lines 2568-2571 supplied nyaji-ny 'see-PAST' and lines 3043-3049 supplied nyaji-l 'see'; Rule 277 used corpus-conventional nyajin as the past visual-perception surface only.", "Rule 277: past perception source."),
    ("process", "Rule 277 complements Rule 276 by changing only the subject-pronoun band to non-singular nominative forms while keeping the same visible water/landform target scope.", "Rule 277: complementary sweep."),
    ("process", "Exact duplicate preflight over all 50 planned Rule 277 Kuku surfaces returned no accepted, revised, or under-review collisions.", "Rule 277: duplicate preflight."),
    ("process", "Token-aware target coverage before banking after Rule 276 was bana 613, dajali 53, jalun 98, jirka 13, jukar 93, manjal 40, wawubaja 206, yilki 12, yiri 10, and yirri 10.", "Rule 277: target coverage audit."),
    ("process", "Support coverage before banking after Rule 276 was ngali 281, ngaliny 215, yubal 229, yurra 244, jana 1537, yaluy 2764, yinyay 3038, and nyajin 1602.", "Rule 277: support coverage audit."),
    ("lexicon", "Bana remained water only; drinking, getting, filling, washing, and water-source/use rows stayed closed.", "Rule 277: bana."),
    ("lexicon", "Dajali remained deep water only; no danger, crossing, swimming, travel, route, or depth-event predicate was imported.", "Rule 277: dajali."),
    ("lexicon", "Jalun remained sea only; flood, seafarer, sea-fauna, salt-water, route, and tide rows stayed closed.", "Rule 277: jalun."),
    ("lexicon", "Jirka remained spring as a water source only; season and place-name readings stayed closed.", "Rule 277: jirka."),
    ("lexicon", "Jukar remained sand only; sandfly, sand goanna, sand whiting, beach-use, and material rows stayed closed.", "Rule 277: jukar."),
    ("lexicon", "Manjal remained mountain only; mountain story, mountain-and-river place, dog legend, route, and place-name prose stayed closed.", "Rule 277: manjal."),
    ("lexicon", "Wawubaja remained river only; travel, route, crossing, bank, place-name, and water-use rows stayed closed.", "Rule 277: wawubaja."),
    ("lexicon", "Yilki remained creek only; creek-place, crossing, travel, ecology, and use prose stayed closed.", "Rule 277: yilki."),
    ("lexicon", "Yiri remained waterfall only; no rainbow yiril, escape yiril, place-name, water-use, or story row was imported.", "Rule 277: yiri."),
    ("lexicon", "Yirri remained running water only; yirri-damal leak, current/flow event, and water-use rows stayed closed.", "Rule 277: yirri."),
    ("morphology", "All Rule 277 target nouns stayed bare: no LOC, DAT, ABL, PERL, ERG, INST, COMIT, POSS, PRIV, EXCESS, plural, derivation, or target suffix was admitted.", "Rule 277: 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 277: bare non-singular nominatives."),
    ("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 277: 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 277 heads.", "Rule 277: no compounds or reduplication."),
    ("morphology", "English labels such as deep water and running water remained target glosses, not Kuku morphology or new event predicates.", "Rule 277: label morphology guard."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajin for first dual exclusive here past visual perception.", "Rule 277: 1du exclusive here band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajin for first dual inclusive there past visual perception.", "Rule 277: 1du inclusive there band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajin for second dual here past visual perception.", "Rule 277: 2du here band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yinyay nyajin for second plural there past visual perception.", "Rule 277: 2pl there band."),
    ("syntax", "Rows 41-50 used Jana TARGET yaluy nyajin for third plural here past visual perception.", "Rule 277: 3pl here band."),
    ("fidelity", "English stayed literal visual past perception/reference prose: selected non-singular subject pronoun value, target label, here/there, and saw only.", "Rule 277: 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, or use claims.", "Rule 277: 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, or story register was introduced.", "Rule 277: register."),
    ("process", "Rules 149-276 carry-forward traps stayed closed, especially recent visible water/landform traps plus older sky, fire, fauna, body, dwelling, and source-prose traps.", "Rule 277: carry-forward closure."),
    ("handoff", "Next batch may continue from 16,047 if this closes; do not infer water-use, travel, route, place-name, flood/tide, ecology, story, target-case, pronoun-case, perception-compound, or support-inflection grammar from Rule 277.", "Rule 277: next cadence."),
]

LEXEMES = [
    ("bana", "noun", None, "NA", "water", "batch-319: visible water perception/reference only; drinking, getting, filling, washing, and water-use rows closed."),
    ("dajali", "noun", None, "NA", "deep water", "batch-319: visible deep-water perception/reference only; danger, crossing, swimming, and route rows closed."),
    ("jalun", "noun", None, "NA", "sea", "batch-319: visible sea perception/reference only; flood, seafarer, sea-fauna, tide, and route rows closed."),
    ("jirka", "noun", None, "NA", "spring", "batch-319: visible spring/water-source perception/reference only; season and place-name rows closed."),
    ("jukar", "noun", None, "NA", "sand", "batch-319: visible sand perception/reference only; sandfly, sand goanna, sand whiting, beach-use, and material rows closed."),
    ("manjal", "noun", None, "NA", "mountain", "batch-319: visible mountain perception/reference only; mountain story, dog legend, route, and place-name prose closed."),
    ("wawubaja", "noun", None, "NA", "river", "batch-319: visible river perception/reference only; travel, route, crossing, bank, place-name, and water-use rows closed."),
    ("yilki", "noun", None, "NA", "creek", "batch-319: visible creek perception/reference only; creek-place, crossing, travel, ecology, and use prose closed."),
    ("yiri", "noun", None, "NA", "waterfall", "batch-319: visible waterfall perception/reference only; rainbow yiril, escape yiril, place-name, water-use, and story rows closed."),
    ("yirri", "noun", None, "NA", "running water", "batch-319: visible running-water perception/reference only; yirri-damal leak and water-use rows closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-319: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-319: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-319: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-319: bare nominative subject support only."),
    ("jana", "pronoun", None, "NA", "third plural nominative", "batch-319: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-319: bare local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-319: bare local demonstrative support only."),
    ("nyajin", "verb", "l", "NA", "saw", "batch-319: 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-319-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 277 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. 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, mountain story, water-source use, water spirit, fish/shellfish/reptile/plant/ecology, danger, ownership, target case, productive compound, productive reduplication, demonstrative case, perception compound, 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 277 lessons covering source checks, non-singular pronoun 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 277 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 277 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-319-verify'").fetchone()[0]
    record_event(
        db,
        batch_label=LABEL,
        phase="close",
        event_type="close-success",
        actor="claude-main",
        detail=f"Closed Batch 319 / Rule 277 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_319.py",
        output_excerpt=f"closed batch-319: 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-319: 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())
