#!/usr/bin/env python3
"""Close batch-141 after main-loop five-lens review."""

from __future__ import annotations

import datetime as dt
import json
import sqlite3
import sys

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-141"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "LEXICAL: SOCIAL RELATIONS, TABOO, TRUTH, AND AUTHORITY WORDS (Rule 99). 50 rows. DESIGN: high-sensitivity "
    "lexical batch after Rule 98 construction work. COVERED: jawun/bangunji/banji/warrin/biwul/ngalayin kin and "
    "affinal rows; biwul and ngalayin avoidance with makuku-bawal; maja as a marked English loan from master; yalaku "
    "as custom/way without inventing a law noun; mandi/dabu/walarr moiety rows; cautious mulkal-mulkal totem row; "
    "Yalanji yirmbal/bubu yirmbal taboo rows; ngalba deceased-name substitute; burri name plus dalkil naming; "
    "manubaja/jurril/warmbiji/jurril-bungal/manubaja-bungal truth and lie rows; nyuyal blame, murru-kangal scold, "
    "murru-kaday/milka-murruji/murru-kaday-manil shame rows; balu desist/disapproval rows; kanyil curse-song rows. "
    "SOURCE CONTROLS: Patz 1.2.1.3, 1.2.1.7, 1.2.1.8, 4.7 ex.566/570/571, 4.8 ex.576, 4.9.2 ex.599-603; "
    "dictionary entries for all named lexemes. PROCESS STORAGE: added append-only process_events ledger and recorded "
    "source checks, conflict decisions, lint outputs, rebank, and close evidence. CORRECTIONS BEFORE CLOSE: row 22 "
    "analysis tightened from taboo-? to taboo-source.clitic for source-quoted Yirmbalda; no Kuku surface rows changed "
    "after banking. Pre-close lint scanned 7147 rows with 0 issues; verified metric remained 7097 before close."
)

LESSONS = [
    ("process", "Store process evidence in both the markdown log and the SQLite process_events ledger.", "operator guide Rule 99 process note."),
    ("lexicon", "`mandi` is permitted for moiety in this batch because the dictionary and later living-book rule supersede the older bama-jambul caution.", "dictionary errata Batch-141: mandi conflict decision."),
    ("lexicon", "Use Yalanji `yirmbal` for taboo rows; do not substitute Nyungkul `jabul` in Yalanji-controlled data.", "cheatsheet Rule 99: taboo lexicon."),
    ("lexicon", "`yalakay` is an interjection/source question frame, not a y-conjugation verb; retain final y.", "dictionary errata Batch-141: yalakay."),
    ("lexicon", "`burri` is the noun name/corroboree song; naming as a verb is `dalki-l`, never phantom `burri-l`.", "cheatsheet Rule 99: naming."),
    ("lexicon", "`biwul` has a homonymous black-snake entry, but social rows must cite the mother-in-law context.", "dictionary errata Batch-141: biwul homonym."),
    ("semantics", "`makuku-bawal` is a concrete avoidance verb, not a free abstract respect/avoidance marker.", "cheatsheet Rule 99: avoidance."),
    ("semantics", "`balu` marks desist/give-up/refrain/disapproval and differs from simple `kari` and specific `wawu-kari`.", "cheatsheet Rule 99: balu."),
    ("syntax", "`babaji-y` keeps the actor ABS, the person asked LOC, and the topic DAT even in lexical review rows.", "cheatsheet Rule 99: ask-about frame reminder."),
    ("syntax", "`murru-kangal` is source-shaped as scold/growl someone; retain the object but note the dictionary type-label tension.", "dictionary errata Batch-141: murru-kangal."),
    ("lexicon", "`kanyil badi` is the source phrase for singing a curse song; keep the actor as ABS with the badi-y phrase.", "cheatsheet Rule 99: curse song."),
    ("lexicon", "`ngalba` is a substitute name in taboo/name-avoidance contexts; do not treat it as the original name.", "cheatsheet Rule 99: ngalba."),
    ("register", "`maja` is a real source-attested boss word but an English loan; mark it in loans_used and avoid making it a general authority abstraction.", "dictionary errata Batch-141: maja."),
    ("lexicon", "`mulkal-mulkal` is polysemous; this batch only licenses the totem sense.", "dictionary errata Batch-141: mulkal-mulkal."),
    ("lexicon", "Prefer `manubaja` for truth in Yalanji-controlled rows; avoid dialect-marked `yukil` as a generic true adjective.", "cheatsheet Rule 99: truth words."),
]

LEXEMES = [
    ("jawun", "noun", None, "neutral", "friend; relation", "batch-141: social relation and COMIT row."),
    ("bangunji", "noun", None, "neutral", "cousin", "batch-141: cousin row."),
    ("banji", "noun", None, "neutral", "brother-in-law; sister-in-law", "batch-141: actual affinal relationship."),
    ("warrin", "noun", None, "neutral", "sister-in-law; brother-in-law", "batch-141: actual affinal relationship."),
    ("biwul", "noun", None, "neutral", "mother-in-law", "batch-141: mother-in-law and avoidance rows; black-snake homonym excluded."),
    ("ngalayin", "noun", None, "neutral", "father-in-law; son-in-law", "batch-141: reciprocal affinal term."),
    ("makuku-bawal", "verb-tr", "l", "NA", "avoid; change direction to avoid meeting someone", "batch-141: concrete avoidance verb."),
    ("maja", "noun", None, "neutral", "boss", "batch-141: source-attested English loan from master."),
    ("yalaku", "adverb", None, "NA", "custom; like; way", "batch-141: custom/like-that source usage."),
    ("mandi", "noun", None, "neutral", "moiety; subsection", "batch-141: moiety term, conflict decision logged."),
    ("dabu", "noun", None, "neutral", "dabu moiety; small black bee", "batch-141: moiety sense."),
    ("walarr", "noun", None, "neutral", "walarr moiety; beard; honey bee", "batch-141: moiety sense."),
    ("mulkal-mulkal", "noun", None, "neutral", "totem", "batch-141: totem sense only."),
    ("yirmbal", "noun", None, "neutral", "taboo; story place", "batch-141: Yalanji taboo rows."),
    ("bubu yirmbal", "noun", None, "neutral", "taboo place", "batch-141: source compound taboo place."),
    ("ngalba", "noun", None, "neutral", "taboo substitute name", "batch-141: deceased-name avoidance."),
    ("burri", "noun", None, "neutral", "name; corroboree song", "batch-141: name noun, not a verb."),
    ("dalkil", "verb-tr", "l", "NA", "give a name; call by name", "batch-141: naming verb."),
    ("manubaja", "noun", None, "neutral", "truth", "batch-141: truth rows."),
    ("manubaja-bungal", "verb-tr", "l", "NA", "believe", "batch-141: belief rows."),
    ("jurril", "noun", None, "neutral", "lie; untruth", "batch-141: lie noun."),
    ("warmbiji", "verb-intr", "y", "NA", "lie; prevaricate", "batch-141: intransitive lying rows."),
    ("jurril-bungal", "verb-tr", "l", "NA", "trick someone by lying", "batch-141: trick-by-lying rows."),
    ("yalakay", "interjection", None, "NA", "is it true? astonishment", "batch-141: retained final y in source question frame."),
    ("nyuyal", "verb-tr", "l", "NA", "blame; accuse", "batch-141: blame rows and source imperative."),
    ("murru-kangal", "verb-tr", "l", "NA", "scold; growl someone", "batch-141: source-shaped scold rows."),
    ("murru-kaday", "verb-intr", "y", "NA", "become ashamed; shy; bashful", "batch-141: inchoative shame row."),
    ("milka-murruji", "adjective", None, "NA", "ashamed; guilty", "batch-141: adjective shame row."),
    ("murru-kaday-manil", "verb-tr", "l", "NA", "shame someone", "batch-141: causative shame row."),
    ("balu", "particle", None, "NA", "desist; give up; refrain; disapproval", "batch-141: balu rows."),
    ("kanyil", "noun", None, "neutral", "curse song", "batch-141: curse-song rows."),
    ("kanyil badi", "construction", None, "NA", "sing a curse song", "batch-141: source usage phrase."),
    ("yinil", "particle", None, "NA", "afraid", "batch-141: yinil plus dative complement."),
]


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}")

    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-141-verify", note, 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 rows; only row 22 analysis metadata changed before close.",
        artifact_path="process_logs/batch-141-social-law-process.md",
        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 141: 50 accepted rows, five-lens reviews, lessons, lexeme logs, and process evidence stored.",
        command="python3 batch_scripts/close_141.py",
        artifact_path="batch_scripts/close_141.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]
    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-141-verify'").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, "
        f"{lesson_count} lessons, {lexeme_logs} lexeme/source-log rows, "
        f"{process_events} process events, verified corpus={verified}"
    )
    return 0


if __name__ == "__main__":
    sys.exit(main())
