#!/usr/bin/env python3
"""Close batch-242 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-242"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-242-distal-demonstrative-tree-reference-consolidation-after-rule199-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "DISTAL-DEMONSTRATIVE TREE-REFERENCE CONSTRUCTION CONSOLIDATION AFTER RULE 199 (Rule 200). 50 rows. "
    "TARGETS retained from Rule 199: jinjajalka tree, kurunkal mangrove, madu sea pine, marngkil ti tree, "
    "marrabal ti tree, milbarakal tree, mungari kaori pine, wurmbariji scrub tree, wuymbariji scrub tree, and "
    "kurrun tree. CONSTRUCTION: distal demonstrative yinya before and after a single tree noun, plus visual "
    "nyaji-l perception frames with demonstrative object NPs: Yinya TARGET yinyay, TARGET yinya yinyay, Ngayu "
    "yinya TARGET nyajil, Yundu TARGET yinya nyajil, and Jana yinya TARGET nyajin. REVIEW: all target heads "
    "stayed bare; yinya/yinyay stayed demonstrative support; pronoun A stayed bare; nyaji-l stayed visual. No "
    "proximal yala/yanyu decision, fruit, seed, food, medicine, poison, sap, timber, bark, wood, oar, woomera, "
    "spear, burning, cutting, gathering, growing/ecology, place-name, story/country, ownership, material-source, "
    "homograph, target-case, compound, plural, derivation, or tree-use row was opened."
)

LESSONS = [
    ("process", "Rule 200 consolidated Rule 199 tree-reference nouns in a different construction rather than adding new tree lexicon.", "Rule 200: construction after Rule 199."),
    ("process", "The construction target was distal yinya, avoiding a new proximal yala/yanyu decision.", "Rule 200: distal-only demonstrative scope."),
    ("process", "Exact duplicate preflight over all 50 planned distal-demonstrative surfaces returned no cross-corpus accepted/revised/under_review collisions.", "Rule 200: duplicate preflight."),
    ("source", "Patz grammar 3.7 supports yinya as that/those and yinyay as there.", "Rule 200: yinya/yinyay source."),
    ("source", "Patz grammar 4.1 supports demonstrative NP order both before and after one noun: yinya karrkay / karrkay yinya.", "Rule 200: preposed and postposed yinya."),
    ("source", "Patz grammar 4.2.1 supports yinya in nominal predicate readings such as Yinya mayi ngulkurr.", "Rule 200: nominal predicate support."),
    ("lexicon", "Jinjajalka remained an unidentified tree species only.", "Rule 200: jinjajalka tree only."),
    ("lexicon", "Kurunkal remained a mangrove/tree reference only; seed and habitat prose stayed closed.", "Rule 200: kurunkal reference only."),
    ("lexicon", "Madu remained sea pine only.", "Rule 200: madu sea pine only."),
    ("lexicon", "Marngkil remained ti tree only; zemia, wing, and food-source drift stayed closed.", "Rule 200: marngkil ti tree only."),
    ("lexicon", "Marrabal remained ti tree only; shell, nautilus shell, and button drift stayed closed.", "Rule 200: marrabal ti tree only."),
    ("lexicon", "Milbarakal remained a tree species only.", "Rule 200: milbarakal tree only."),
    ("lexicon", "Mungari remained kaori/kauri pine only.", "Rule 200: mungari kaori pine only."),
    ("lexicon", "Wurmbariji remained scrub tree only; jellyfish drift stayed closed.", "Rule 200: wurmbariji scrub tree only."),
    ("lexicon", "Wuymbariji remained scrub tree only.", "Rule 200: wuymbariji scrub tree only."),
    ("lexicon", "Kurrun remained a tree species only; bronze-wing pigeon homograph drift stayed closed.", "Rule 200: kurrun tree only."),
    ("morphology", "All tree targets stayed bare with no target case, possession, compounding, derivation, plural, or reduplication.", "Rule 200: bare target morphology."),
    ("morphology", "Yinya stayed uninflected as an absolutive demonstrative in NP and object-NP position.", "Rule 200: bare yinya."),
    ("morphology", "Yinyay stayed a local demonstrative, not a new tree-location morphology on the target noun.", "Rule 200: yinyay support only."),
    ("morphology", "Nyaji-l tense stayed consistent: nonpast nyajil and past nyajin with analysis nyaji-l and nyaji-ny.", "Rule 200: perception tense discipline."),
    ("syntax", "Rows 1-10 used Yinya TARGET yinyay as preposed demonstrative NP plus local predicate.", "Rule 200: preposed yinya frame."),
    ("syntax", "Rows 11-20 used TARGET yinya yinyay as postposed demonstrative NP plus local predicate.", "Rule 200: postposed yinya frame."),
    ("syntax", "Rows 21-30 used Ngayu yinya TARGET nyajil with a preposed-demonstrative object NP.", "Rule 200: 1sg preposed object NP."),
    ("syntax", "Rows 31-40 used Yundu TARGET yinya nyajil with a postposed-demonstrative object NP.", "Rule 200: 2sg postposed object NP."),
    ("syntax", "Rows 41-50 used Jana yinya TARGET nyajin with a preposed-demonstrative object NP and past perception.", "Rule 200: 3pl past preposed object NP."),
    ("fidelity", "English stayed literal: that X is there, I/you see that X, and they saw that X.", "Rule 200: literal English."),
    ("fidelity", "No English fruit, seed, edible, food, medicine, poison, sap, timber, wood, bark, oar, woomera, spear, burning, cutting, gathering, growing, ecology, place, story, country, ownership, material, homograph, or use wording was imported.", "Rule 200: denied English fields."),
    ("register", "Rows remained plain demonstrative reference/perception clauses, not botanical, ecological, ethnographic, material-use, or cultural claims.", "Rule 200: reference register."),
    ("handoff", "Next batch can return to a fresh bounded lexical field or a targeted debt sweep; all Rule 199-200 tree-use/source-prose traps remain closed.", "Rule 200: next cadence."),
]

LEXEMES = [
    ("jinjajalka", "noun", None, "NA", "jinjajalka tree; unidentified tree species", "batch-242: retained tree-reference target only in distal yinya frames."),
    ("kurunkal", "noun", None, "NA", "kurunkal mangrove; species of mangrove", "batch-242: retained mangrove/tree target only; seed/habitat prose closed."),
    ("madu", "noun", None, "NA", "madu sea pine", "batch-242: retained sea pine tree-reference target only."),
    ("marngkil", "noun", None, "NA", "marngkil ti tree; species of ti tree", "batch-242: retained ti-tree target only; zemia/wing/food-source drift closed."),
    ("marrabal", "noun", None, "NA", "marrabal ti tree; species of ti tree", "batch-242: retained ti-tree target only; shell/button drift closed."),
    ("milbarakal", "noun", None, "NA", "milbarakal tree; species of tree", "batch-242: retained tree-reference target only."),
    ("mungari", "noun", None, "NA", "mungari kaori pine; kauri pine tree", "batch-242: retained kaori/kauri pine target only."),
    ("wurmbariji", "noun", None, "NA", "wurmbariji scrub tree", "batch-242: retained scrub-tree target only; jellyfish/ecology/growing drift closed."),
    ("wuymbariji", "noun", None, "NA", "wuymbariji scrub tree", "batch-242: retained scrub-tree target only; ecology/growing drift closed."),
    ("kurrun", "noun", None, "NA", "kurrun tree; tree species with English name unknown", "batch-242: retained tree-reference target only; bird homograph closed."),
    ("yinya", "demonstrative", None, "NA", "that; there", "batch-242: distal demonstrative in preposed and postposed NP order."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-242: local demonstrative support in distal presentational rows."),
    ("nyaji-l", "verb", "l", "NA", "see; hear; perceive", "batch-242: visual perception verb with distal-demonstrative tree-reference objects."),
    ("ngayu", "pronoun", None, "NA", "I; 1sg nominative", "batch-242: bare pronoun A in preposed-demonstrative object rows."),
    ("yundu", "pronoun", None, "NA", "you; 2sg nominative", "batch-242: bare pronoun A in postposed-demonstrative object rows."),
    ("jana", "pronoun", None, "NA", "they; 3pl nominative", "batch-242: bare pronoun A in past preposed-demonstrative object rows."),
]


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:
        raise SystemExit(f"{LABEL} must have 50 rows before close; found {total}")
    if accepted:
        raise SystemExit(f"{LABEL} already has {accepted} accepted/revised rows; refusing to overwrite")
    if under_review != 50:
        raise SystemExit(f"{LABEL} must have 50 under_review rows before close; found {under_review}")

    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.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-242-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 by SQL token estimate)",
        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 200 rows. Morphology checked target heads bare, yinya uninflected, yinyay local support only, pronoun A bare, and nyaji-l tense forms. Lexicon checked the ten retained tree senses and kept seed, food, medicine, poison, sap, timber, bark, wood, oar, woomera, spear, burning, cutting, gathering, growing/ecology, place-name, story/country, ownership, material-source, homograph, and tree-use semantics closed. Syntax checked preposed and postposed yinya NPs plus perception frames. Fidelity checked literal distal English. Register stayed plain reference/perception.",
        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 yala/yanyu decision, target case, compound, possessive, comitative, instrumental, locative, dative, ablative, perlative, privative, degree, comparison, plural, causative, inchoative, derivation, productive reduplication, fruit, seed, edible, medicine, poison, sap, timber, bark, wood, oar, woomera, spear, burning, cutting, gathering, growing, ecology, place, story, country, ownership, material-source, bird, shell, button, wing, zemia, jellyfish, leech, necklace, or use row.",
        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 200 lessons covering source checks, demonstrative construction, target senses, homograph closures, morphology, syntax, fidelity, register, and handoff.",
        artifact_path="batch_scripts/close_242.py",
        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 retained tree targets, yinya, yinyay, pronouns, and nyaji-l.",
        artifact_path="batch_scripts/close_242.py",
        created_at=NOW,
    )
    db.execute("UPDATE batches SET notes=? WHERE id=?", (NOTES, batch_id))
    db.execute("UPDATE sentences SET status='accepted', updated_at=? WHERE batch_id=?", (NOW, batch_id))
    record_event(
        db,
        batch_label=LABEL,
        phase="close",
        event_type="close-success",
        actor="claude-main",
        detail="Closed Batch 242: 50 accepted Rule 200 distal-demonstrative tree-reference construction-consolidation rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_242.py",
        artifact_path="batch_scripts/close_242.py",
        created_at=NOW,
    )
    db.commit()

    reviews = db.execute(
        "SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)",
        (batch_id,),
    ).fetchone()[0]
    verified = db.execute("SELECT COUNT(*) FROM sentences WHERE status IN ('accepted','revised')").fetchone()[0]
    under_review_remaining = db.execute("SELECT COUNT(*) FROM sentences WHERE status='under_review'").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 LIKE 'batch-242%'").fetchone()[0]
    process_events = db.execute("SELECT COUNT(*) FROM process_events WHERE batch_label=?", (LABEL,)).fetchone()[0]
    print(
        f"closed {LABEL}: 50 accepted rows, {reviews} review passes, {lesson_count} lessons, "
        f"{lexeme_logs} lexeme/source-log rows, {process_events} process events, "
        f"under_review={under_review_remaining}, verified corpus={verified}"
    )
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
