#!/usr/bin/env python3
"""Close batch-262 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-262"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-262-second-reptile-amphibian-reference-lexical-expansion-after-rule219-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "SECOND REPTILE/AMPHIBIAN-REFERENCE LEXICAL EXPANSION AFTER RULE 219 (Rule 220). 50 rows. TARGETS: "
    "bajuy lizard, bilngkumu crocodile, binanjal frill necked lizard, bindimu black snake, bubal tree snake, "
    "jijirrbay whip snake, kabul rock python, kalajarr scrub goanna, kundurr death adder, and yuday frog. SUPPORT: "
    "uninflected yinya/yaluy/yinyay. FRAMES: TARGET yaluy, TARGET yinyay, Yinya TARGET yinyay, TARGET yinya "
    "yinyay, and Yinya TARGET yaluy. REVIEW: all target nouns stayed bare reference labels. No Rule 175-176 exact "
    "surface duplicate, biwul black-snake/mother-in-law homograph, story-site/myth row, poison/biting/danger row, "
    "hunting/catching/trapping/killing row, food/edible/cooking row, egg/skin/scale/body-part row, habitat/water/"
    "river/sea/swamp row, tree-climbing/firestick/fighter/event row, colour predicate, target case, number morphology, "
    "derivation, productive compounding, productive reduplication, support inflection, mammal-reference drift, or "
    "fish-reference drift was opened."
)

LESSONS = [
    ("process", "Rule 220 continued the reptile/amphibian-reference domain only after checking earlier Rule 175-176 reptile batches for exact surface collisions.", "Rule 220: second reptile lexical cadence."),
    ("source", "Patz section 3.1 says nouns include fauna; Rule 220 uses bare reptile/amphibian nouns only.", "Rule 220: fauna noun source."),
    ("source", "Patz section 3.7 supports yinya, yaluy, and yinyay; Rule 220 keeps all three uninflected.", "Rule 220: demonstrative source."),
    ("process", "Rule 220 reused only bare deictic reference frames because they add lexical coverage without importing reptile behavior, danger, food, habitat, or event grammar.", "Rule 220: reference wording."),
    ("process", "Rejected or deferred fields included exact Rule 175-176 surfaces, biwul black-snake homograph, story-site/myth-heavy entries, poison/biting/food/event-heavy entries, and productive reduplication pressure.", "Rule 220: rejected reptile fields."),
    ("lexicon", "Bajuy stayed lizard reference only; slippery, catching, and food readings stayed closed.", "Rule 220: bajuy."),
    ("lexicon", "Bilngkumu stayed crocodile reference only; saltwater, river, fear, biting, danger, hunting, and story readings stayed closed.", "Rule 220: bilngkumu."),
    ("lexicon", "Binanjal stayed frill-necked-lizard reference only; neck/body-part, display, frightening, and dog-event readings stayed closed.", "Rule 220: binanjal."),
    ("lexicon", "Bindimu stayed black-snake reference only; red-bellied alternate and colour-predicate readings stayed closed.", "Rule 220: bindimu."),
    ("lexicon", "Bubal stayed tree-snake reference only; tree/habitat, biting, and death-event readings stayed closed.", "Rule 220: bubal."),
    ("lexicon", "Jijirrbay stayed whip-snake reference only; whip/object, speed, and bite prose stayed closed.", "Rule 220: jijirrbay."),
    ("lexicon", "Kabul stayed rock-python reference only; rock/place, food, squeezing, swallowing, and hunting prose stayed closed.", "Rule 220: kabul."),
    ("lexicon", "Kalajarr stayed scrub-goanna reference only; scrub/habitat, climbing, nest-raiding, food, cooking, and digging prose stayed closed.", "Rule 220: kalajarr."),
    ("lexicon", "Kundurr stayed death-adder reference only; danger, biting, poison, fear, and sickness prose stayed closed.", "Rule 220: kundurr."),
    ("lexicon", "Yuday stayed frog reference only; edible, rain, singing, swamp, and metamorphosis prose stayed closed.", "Rule 220: yuday."),
    ("morphology", "All target reptile/amphibian nouns stayed bare: no target case, possession, comitative, instrumental, locative, number, derivation, suffixing, plural, or reduplication.", "Rule 220: bare nouns."),
    ("morphology", "English modifiers inside animal labels, such as frill necked, black, tree, whip, rock, scrub, and death, remained lexical labels rather than Kuku morphology or separate predicates.", "Rule 220: label morphology guard."),
    ("morphology", "Yinya, yaluy, and yinyay stayed uninflected support forms only.", "Rule 220: support morphology."),
    ("syntax", "Rows 1-10 used TARGET yaluy.", "Rule 220: TARGET here frame."),
    ("syntax", "Rows 11-20 used TARGET yinyay.", "Rule 220: TARGET there frame."),
    ("syntax", "Rows 21-30 used Yinya TARGET yinyay.", "Rule 220: demonstrative TARGET there frame."),
    ("syntax", "Rows 31-40 used TARGET yinya yinyay.", "Rule 220: TARGET demonstrative there frame."),
    ("syntax", "Rows 41-50 used Yinya TARGET yaluy.", "Rule 220: demonstrative TARGET here frame."),
    ("fidelity", "English stayed literal reference prose: target reptile/amphibian label plus here/there/that support.", "Rule 220: literal English."),
    ("fidelity", "The batch did not turn source definitions into ecological, danger, food, story, or behavior claims.", "Rule 220: source-prose restraint."),
    ("register", "Rows remained plain elicitation-style reference statements, not hunting reports, warning stories, food statements, habitat claims, or mythological prose.", "Rule 220: register."),
    ("process", "Duplicate preflight, static guards, whole-corpus lint, five-lens review, lessons, lexeme logs, export, and live docs are required evidence before treating Rule 220 as complete.", "Rule 220: evidence standard."),
    ("handoff", "Next batch may continue from 13,197 if this closes; do not infer reptile behavior, danger, food, habitat, story, body-part, homograph, or event grammar from Rule 220.", "Rule 220: next cadence."),
]

LEXEMES = [
    ("bajuy", "noun", None, "NA", "lizard", "batch-262: lizard reference only; slippery/catching/food readings closed."),
    ("bilngkumu", "noun", None, "NA", "crocodile", "batch-262: crocodile reference only; saltwater/river/fear/biting/danger/hunting/story readings closed."),
    ("binanjal", "noun", None, "NA", "frill necked lizard", "batch-262: frill-necked-lizard reference only; neck/body-part/display/frightening/dog-event readings closed."),
    ("bindimu", "noun", None, "NA", "black snake", "batch-262: black-snake reference only; red-bellied alternate and colour-predicate readings closed."),
    ("bubal", "noun", None, "NA", "tree snake", "batch-262: tree-snake reference only; tree/habitat/biting/death-event readings closed."),
    ("jijirrbay", "noun", None, "NA", "whip snake", "batch-262: whip-snake reference only; whip/object/speed/bite prose closed."),
    ("kabul", "noun", None, "NA", "rock python", "batch-262: rock-python reference only; rock/place/food/squeezing/swallowing/hunting prose closed."),
    ("kalajarr", "noun", None, "NA", "scrub goanna", "batch-262: scrub-goanna reference only; scrub/habitat/climbing/nest-raiding/food/cooking/digging prose closed."),
    ("kundurr", "noun", None, "NA", "death adder", "batch-262: death-adder reference only; danger/biting/poison/fear/sickness prose closed."),
    ("yuday", "noun", None, "NA", "frog", "batch-262: frog reference only; edible/rain/singing/swamp/metamorphosis prose closed."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-262: local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-262: local demonstrative support only."),
    ("yinya", "demonstrative", None, "NA", "that; those", "batch-262: distal demonstrative support only; no inflection."),
]


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-262-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 220 rows. Morphology checked bare reptile/amphibian nouns and uninflected yinya/yaluy/yinyay support. Lexicon checked selected reptile/amphibian-reference labels only. Syntax checked five deictic reference frames. Fidelity checked literal reference English. Register stayed plain reference statement.",
        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 Rule 175-176 exact surface duplicate, biwul black-snake/mother-in-law homograph, story-site/myth row, poison/biting/danger row, hunting/catching/trapping/killing row, food/edible/cooking row, egg/skin/scale/body-part row, habitat/water/river/sea/swamp row, tree-climbing/firestick/fighter/event row, colour predicate, target case, number morphology, derivation, productive compounding, productive reduplication, support inflection, mammal-reference drift, or fish-reference 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 220 lessons covering source checks, field rejection, target senses, morphology, syntax, fidelity, register, and handoff.",
        artifact_path="batch_scripts/close_262.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 Rule 220 targets and support heads.",
        artifact_path="batch_scripts/close_262.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 262: 50 accepted Rule 220 second reptile/amphibian-reference rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_262.py",
        artifact_path="batch_scripts/close_262.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_after, words_after = db.execute(
        """
        SELECT
          COUNT(*),
          SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1)
        FROM sentences
        WHERE status IN ('accepted','revised')
        """
    ).fetchone()
    print(
        f"closed {LABEL}: accepted=50, reviews={reviews}, verified {verified_before}->{verified_after}, "
        f"kuku_words {words_before or 0}->{words_after or 0}"
    )
    return 0


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