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

NOTES = (
    "STATE-PREDICATE LEXICAL EXPANSION AFTER RULE 192 (Rule 193). 50 rows. TARGETS: dakwuy hungry, bambay sick, "
    "dukul-wuri really angry, kala-burra weak, warngku-kaday sleepy, wawu-mini happy, wawu-buyun worried, "
    "milka-murruji ashamed, ngulkurr well, and juwamalmal lethargic. FRAMES: first-person state predicates with "
    "ngayu, second-person negated state predicates with yundu kari, third-person singular negated state predicates "
    "with nyulu kari, third-person plural state predicates with jana, and inclusive negated state predicates with "
    "ngana kari. REVIEW: targets stayed bare; no food/cooking/eating, doctor/medicine/magic/healing, illness-cause, "
    "body-part analysis, anger event, sleep event, making-happy/promise/play cause, worry/dread/travel/desire event, "
    "theft/promise/avoidance/shaming-causative row, food-good/moral-good ngulkurr reading, causative, inchoative, "
    "degree, case, plural, target compound, productive reduplication, or Rule 191-192 perception drift."
)

LESSONS = [
    ("process", "Rule 193 deliberately selected a bounded bodily/mental state predicate field after the Rule 191-192 perception pair.", "Rule 193: state-predicate lexical cadence."),
    ("process", "The source pass preferred adjective-like stative predicates that can stand after a bare pronoun subject.", "Rule 193: predicate source triage."),
    ("process", "Planned `Ngayu milka-murruji.` was rejected as an exact duplicate of Batch 129 row 38; `Ngayu kari milka-murruji.` was banked instead.", "Rule 193: duplicate avoidance."),
    ("process", "Verb-state candidates such as `jibabadi-y`, `murru-kaday`, `mulkay-warri`, and `wawu-wulay` were deferred to avoid tense/aspect drift.", "Rule 193: deferred verbal predicates."),
    ("process", "Polysemous or heavier candidates such as `muna`, `yanji`, `wunbu`, `ngalu-ngalu`, and `walu-jirrbu-jirrbu` were left for narrower future passes.", "Rule 193: deferred polysemy."),
    ("lexicon", "`dakwuy` was admitted as hungry only; food, cooking, eating, and food-preparation rows stayed closed.", "Rule 193: dakwuy."),
    ("lexicon", "`bambay` was admitted as sick only; illness-cause, doctor, medicine, magic, and healing rows stayed closed.", "Rule 193: bambay."),
    ("lexicon", "`dukul-wuri` was admitted as really angry only; head/body-part analysis, nodding, fighting, yelling, throwing, and threat rows stayed closed.", "Rule 193: dukul-wuri."),
    ("lexicon", "`kala-burra` was admitted as weak only; carrying, failing, work, hunting, and cause rows stayed closed.", "Rule 193: kala-burra."),
    ("lexicon", "`warngku-kaday` was admitted as sleepy only; sleep-event, lying-down, bed, and habitual-sleeper rows stayed closed.", "Rule 193: warngku-kaday."),
    ("lexicon", "`wawu-mini` was admitted as happy only; making-happy, promise, play, ceremony, and event-cause rows stayed closed.", "Rule 193: wawu-mini."),
    ("lexicon", "`wawu-buyun` was admitted as worried only; consequence, dread-event, travel, missing, and desire rows stayed closed.", "Rule 193: wawu-buyun."),
    ("lexicon", "`milka-murruji` was admitted as ashamed only; theft, promise, avoidance, ear/body-part, and shaming-causative rows stayed closed.", "Rule 193: milka-murruji."),
    ("lexicon", "`ngulkurr` was admitted as well only; food-good, moral-good, good-things, and comparative rows stayed closed.", "Rule 193: ngulkurr."),
    ("lexicon", "`juwamalmal` was admitted as lethargic only; illness-cause, sleeping, medical, and diagnosis rows stayed closed.", "Rule 193: juwamalmal."),
    ("morphology", "All Rule 193 target heads stayed bare with no case, degree, causative, inchoative, plural, target compound, or productive-reduplicated form.", "Rule 193: bare target morphology."),
    ("morphology", "`kari` was the only added operator and was glossed as NEG before the state predicate.", "Rule 193: kari negation."),
    ("morphology", "Lexicalized compounds such as `dukul-wuri`, `warngku-kaday`, `wawu-mini`, `wawu-buyun`, `milka-murruji`, and `kala-burra` were treated as dictionary heads, not productive formations.", "Rule 193: lexical compound distinction."),
    ("morphology", "`ngulkurr` was selected from the substantive dictionary entry and not from the placeholder entry that repeats the headword.", "Rule 193: ngulkurr source distinction."),
    ("syntax", "Rows 1-10 used bare `ngayu` plus one state predicate; row 8 included source-backed pre-adjectival `kari` to avoid duplication.", "Rule 193: ngayu state predicates."),
    ("syntax", "Rows 11-20 used bare `yundu`, `kari`, and one state predicate.", "Rule 193: yundu kari predicates."),
    ("syntax", "Rows 21-30 used bare `nyulu`, `kari`, and one state predicate.", "Rule 193: nyulu kari predicates."),
    ("syntax", "Rows 31-40 used bare `jana` plus one state predicate.", "Rule 193: jana state predicates."),
    ("syntax", "Rows 41-50 used inclusive `ngana`, `kari`, and one state predicate.", "Rule 193: ngana kari predicates."),
    ("handoff", "Next cadence should consolidate the Rule 193 state-predicate field without opening the deferred verb-state candidates, body-part idioms, event causes, degree morphology, case, plural, or productive reduplication.", "Rule 193: next cadence."),
]

LEXEMES = [
    ("dakwuy", "adjective", None, "NA", "hungry", "batch-235: admitted as hungry state predicate only; no food/cooking/eating row."),
    ("bambay", "adjective", None, "NA", "sick", "batch-235: admitted as sick state predicate only; no illness-cause, doctor, medicine, magic, or healing row."),
    ("dukul-wuri", "adjective", None, "NA", "really angry", "batch-235: admitted as really angry state predicate only; no head/body-part analysis, nodding, fighting, yelling, throwing, or threat row."),
    ("kala-burra", "adjective", None, "NA", "weak", "batch-235: admitted as weak state predicate only; no carrying, failing, work, hunting, or cause row."),
    ("warngku-kaday", "adjective", None, "NA", "sleepy", "batch-235: admitted as sleepy state predicate only; no sleep-event, lying-down, bed, or habitual-sleeper row."),
    ("wawu-mini", "adjective", None, "NA", "happy", "batch-235: admitted as happy state predicate only; no making-happy, promise, play, ceremony, or event-cause row."),
    ("wawu-buyun", "adjective", None, "NA", "worried", "batch-235: admitted as worried state predicate only; no consequence, dread-event, travel, missing, or desire row."),
    ("milka-murruji", "adjective", None, "NA", "ashamed", "batch-235: admitted as ashamed state predicate only; no theft, promise, avoidance, ear/body-part, or shaming-causative row."),
    ("ngulkurr", "adjective", None, "NA", "well", "batch-235: admitted as bodily well state predicate only; no food-good, moral-good, good-things, or comparative row."),
    ("juwamalmal", "adjective", None, "NA", "lethargic", "batch-235: admitted as lethargic state predicate only; no illness-cause, sleeping, medical, or diagnosis row."),
    ("kari", "particle", None, "NA", "not; NEG", "batch-235: retained as source-backed pre-adjectival negator for state predicates."),
    ("ngayu", "pronoun", None, "NA", "I; 1sg nominative", "batch-235: bare pronoun S in state predicates."),
    ("yundu", "pronoun", None, "NA", "you; 2sg nominative", "batch-235: bare pronoun S in negated state predicates."),
    ("nyulu", "pronoun", None, "NA", "he/she; 3sg nominative", "batch-235: bare pronoun S in negated state predicates."),
    ("jana", "pronoun", None, "NA", "they; 3pl nominative", "batch-235: bare pronoun S in state predicates."),
    ("ngana", "pronoun", None, "NA", "we; 1pl inclusive", "batch-235: bare pronoun S in negated state predicates."),
]


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-235-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 193 rows. Morphology checked bare selected state targets, no case/degree/causative/inchoative/plural/productive-reduplication forms, lexicalized compounds as dictionary heads only, and kari as NEG before the state predicate. Lexicon checked each selected sense and kept deferred verb-state candidates, body-part idiom expansions, event causes, food-good/moral-good ngulkurr readings, and Rule 191-192 perception traps closed. Syntax checked bare pronoun S plus state predicate, with kari before adjectives in negated rows. Fidelity checked no source-event import. Register stayed ordinary stative description.",
                 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 target locative/dative/ablative/perlative/ergative/instrument/comitative/possessive/privative/excess/plural/productive-reduplication/compound form, no loan token, no deferred target, no causative/inchoative event, no body-part analysis, and no source-event 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 193 lessons covering source checks, lexical scope, duplicate avoidance, deferred candidates, selected target senses, morphology, syntax, fidelity, register, and handoff.",
                 artifact_path="batch_scripts/close_235.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 193 state targets, kari, and participants.",
                 artifact_path="batch_scripts/close_235.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 235: 50 accepted Rule 193 state-predicate lexical expansion rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
                 command="python3 batch_scripts/close_235.py", artifact_path="batch_scripts/close_235.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-235%'").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, {lexeme_logs} lexeme/source-log rows, {process_events} process events, under_review={under_review_remaining}, verified corpus={verified}")
    return 0


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