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

NOTES = (
    "PROPERTY-ADJECTIVE CONSTRUCTION CONSOLIDATION AFTER RULE 195 (Rule 196). 50 rows. RETAINED TARGETS: yalbay big, "
    "karrkay small, kalbay long, kulka short, kulngkul heavy, wuban strong, yayji thin, wumbul hot, kiway-kiway cold, "
    "and marral dry. FRAMES: bare NP ADJ yaluy, bare NP ADJ yinyay, yala NP ADJ, yala NP ADJ yaluy, and yinya NP ADJ "
    "yinyay. REVIEW: no pre-adjective kari, post-adjective -kari, general privative, case, degree, causative, "
    "inchoative, plural, target compound, productive reduplication, child-noun karrkay, pregnant kulngkul, medical/"
    "diagnosis/event reading, material-use, travel-event, ownership/country claim, or Rule 193-195 trap was opened."
)

LESSONS = [
    ("process", "Rule 196 deliberately consolidated the Rule 195 property-adjective field rather than adding targets.", "Rule 196: construction cadence after Rule 195."),
    ("process", "The source pass retained exactly ten Rule 195 adjectives and reused only sourced deictic/local support.", "Rule 196: retained target inventory."),
    ("process", "Candidate `Bayan yalbay yinyay.` was rejected because it duplicated Batch 134 row 32.", "Rule 196: duplicate avoidance."),
    ("process", "`yala`, `yinya`, `yaluy`, and `yinyay` were admitted as support heads, not new lexical targets.", "Rule 196: support-head distinction."),
    ("process", "Rule 195 post-adjective `-kari` was deliberately closed in Rule 196.", "Rule 196: no NEG/PRIV reopening."),
    ("lexicon", "`yalbay` was retained as big only; degree, comparison, and heavy-rain idiom stayed closed.", "Rule 196: yalbay retained."),
    ("lexicon", "`karrkay` was retained as small only; child-noun readings stayed closed.", "Rule 196: karrkay adjective only."),
    ("lexicon", "`kalbay` was retained as long only; route/travel events stayed closed.", "Rule 196: kalbay retained."),
    ("lexicon", "`kulka` was retained as short only; cutting, breaking, and material-use claims stayed closed.", "Rule 196: kulka retained."),
    ("lexicon", "`kulngkul` was retained as heavy only; pregnant readings stayed closed.", "Rule 196: kulngkul retained."),
    ("lexicon", "`wuban` was retained as strong only; hard-material and fighting-event extensions stayed closed.", "Rule 196: wuban retained."),
    ("lexicon", "`yayji` was retained as thin only; diagnosis and medical readings stayed closed.", "Rule 196: yayji retained."),
    ("lexicon", "`wumbul` was retained as hot only; hot-season, time, and sun-event readings stayed closed.", "Rule 196: wumbul retained."),
    ("lexicon", "`kiway-kiway` was retained as cold only; sickness and weather-event claims stayed closed.", "Rule 196: kiway-kiway retained."),
    ("lexicon", "`marral` was retained as dry only; country/ownership/land-use claims stayed closed.", "Rule 196: marral retained."),
    ("morphology", "All target adjectives stayed bare, with no case, degree, causative, inchoative, plural, compound, reduplication, or -kari.", "Rule 196: bare target morphology."),
    ("morphology", "The only added support morphology was none: `yala`, `yinya`, `yaluy`, and `yinyay` remained independent support words.", "Rule 196: support words stay separate."),
    ("syntax", "Rows 1-10 used bare NP plus adjective plus `yaluy` here.", "Rule 196: NP ADJ yaluy predicates."),
    ("syntax", "Rows 11-20 used bare NP plus adjective plus `yinyay` there.", "Rule 196: NP ADJ yinyay predicates."),
    ("syntax", "Rows 21-30 used `yala` plus NP plus adjective.", "Rule 196: yala NP ADJ predicates."),
    ("syntax", "Rows 31-40 used `yala` plus NP plus adjective plus `yaluy`.", "Rule 196: yala NP ADJ yaluy predicates."),
    ("syntax", "Rows 41-50 used `yinya` plus NP plus adjective plus `yinyay`.", "Rule 196: yinya NP ADJ yinyay predicates."),
    ("fidelity", "English stayed literal: this/that/here/there plus the selected dictionary property sense.", "Rule 196: source-fidelity guard."),
    ("register", "Rows remained plain descriptive nominal clauses, not narrative events.", "Rule 196: register restraint."),
    ("handoff", "Next cadence may return to lexical expansion after Rule 196, with Rule 195-196 property-adjective traps carried forward.", "Rule 196: next cadence."),
]

LEXEMES = [
    ("yalbay", "adjective", None, "NA", "big", "batch-238: retained as big property adjective only."),
    ("karrkay", "adjective", None, "NA", "small", "batch-238: retained as adjective small only; no child-noun reading."),
    ("kalbay", "adjective", None, "NA", "long", "batch-238: retained as long property adjective only."),
    ("kulka", "adjective", None, "NA", "short", "batch-238: retained as short property adjective only."),
    ("kulngkul", "adjective", None, "NA", "heavy", "batch-238: retained as heavy only; no pregnant reading."),
    ("wuban", "adjective", None, "NA", "strong", "batch-238: retained as strong only."),
    ("yayji", "adjective", None, "NA", "thin", "batch-238: retained as thin only; no diagnosis claim."),
    ("wumbul", "adjective", None, "NA", "hot", "batch-238: retained as hot only."),
    ("kiway-kiway", "adjective", None, "NA", "cold", "batch-238: retained as cold only."),
    ("marral", "adjective", None, "NA", "dry", "batch-238: retained as dry only."),
    ("bayan", "noun", None, "NA", "house; camp; shelter", "batch-238: subject noun for deictic property predicates."),
    ("baral", "noun", None, "NA", "road; path; track; trail", "batch-238: subject noun only; no travel event."),
    ("juku", "noun", None, "NA", "tree; wood", "batch-238: subject noun only; no material-use claim."),
    ("kulji", "noun", None, "NA", "stone; pebbles", "batch-238: subject noun for heavy property predicate."),
    ("bama", "noun", None, "NA", "person; people", "batch-238: subject noun only; no social-event claim."),
    ("wungar", "noun", None, "NA", "sun", "batch-238: subject noun for hot property predicate."),
    ("kaba", "noun", None, "NA", "rain", "batch-238: subject noun for cold property predicate."),
    ("bubu", "noun", None, "NA", "ground; earth; country", "batch-238: subject noun only; no ownership/country claim."),
    ("yala", "demonstrative", None, "NA", "this; here", "batch-238: support demonstrative only."),
    ("yinya", "demonstrative", None, "NA", "that; there", "batch-238: support demonstrative only."),
    ("yaluy", "demonstrative", None, "NA", "here; this place", "batch-238: local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-238: local demonstrative support only."),
]


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-238-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 196 rows. Morphology checked all target adjectives remained bare with no case/degree/causative/inchoative/plural/compound/reduplication/-kari. Lexicon checked selected adjective and subject senses and kept homographs, polysemy, events, uses, and diagnoses closed. Syntax checked bare NP ADJ yaluy, bare NP ADJ yinyay, yala NP ADJ, yala NP ADJ yaluy, and yinya NP ADJ yinyay frames. Fidelity checked literal deictic/location English. Register stayed plain descriptive.",
                 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/degree/causative/inchoative/plural/productive-reduplication/compound form, no free kari, no post-adjective -kari, no child-noun karrkay, no pregnant kulngkul, no material-use, no travel-event, no ownership/country claim, and no Rule 193-195 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 196 lessons covering source checks, construction scope, duplicate preflight, support heads, retained target senses, morphology, syntax, fidelity, register, and handoff.",
                 artifact_path="batch_scripts/close_238.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 196 retained property adjectives, subject nouns, yala, yinya, yaluy, and yinyay.",
                 artifact_path="batch_scripts/close_238.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 238: 50 accepted Rule 196 property-adjective construction-consolidation rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
                 command="python3 batch_scripts/close_238.py", artifact_path="batch_scripts/close_238.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-238%'").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())
