#!/usr/bin/env python3
"""Close batch-158 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-158"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-158-sequence-clitics-time-bridging-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "CONSTRUCTION: SEQUENCE CLITICS AND EXPLICIT TIME BRIDGING (Rule 116). 50 rows. DESIGN: hand-authored "
    "construction rows contrasting TEMP1 -da sequence close, TEMP2 -kuda meanwhile overlap, TEMP3 -(ng)Vrr first "
    "action/participant, and explicit time bridges after time gaps. SOURCE CONTROLS: Patz 3.10.1 and 5.2.2; examples "
    "631-636 plus text-line kuda examples. PROCESS STORAGE: source pass, existing-surface scan, static guards, lint, "
    "five-lens review, close, export, docs, and live verification are stored."
)

LESSONS = [
    ("syntax", "TEMP1 `-da` usually marks the final or following event in a sequence, not every verb in a list.", "Rule 116: TEMP1 sequence close."),
    ("syntax", "A sequence can contain several unmarked past events before the final `-da` event closes or advances the narrative.", "Rule 116: unmarked prior events."),
    ("fidelity", "Translate `-da` as then/and then only when the Kuku row marks sequence closure or following action.", "Rule 116: TEMP1 English."),
    ("syntax", "TEMP3 `-(ng)Vrr` marks the first action, first object, or first participant in a sequence.", "Rule 116: TEMP3 firstness."),
    ("morphology", "TEMP3 allomorphy must follow sourced hosts: `mayi-ngarr`, `kuyu-ngurr`, pronoun `-ngurr`, verb `-l-urr`, and imperative `-rr`/`-ngarr` forms.", "Rule 116: TEMP3 host shapes."),
    ("syntax", "TEMP3 on a pronoun such as `nyulu-ngurr` means that participant was first to act or be affected, not simply an emphatic pronoun.", "Rule 116: first participant."),
    ("syntax", "Imperative TEMP3 rows such as `daya-rr`, `julurri-ka-rr`, `nuka-ngarr`, and `kadayarr` carry urgency/firstness.", "Rule 116: first imperatives."),
    ("syntax", "TEMP2 `-kuda` should be used cautiously for overlapping or meanwhile action because Patz says the function is not fully transparent.", "Rule 116: TEMP2 caution."),
    ("fidelity", "Do not translate `-kuda` as definitely/for sure in this corpus without a separate source pass; Batch 158 uses the meanwhile reading only.", "Rule 116: TEMP2 English."),
    ("syntax", "TEMP2 can attach to verbs and also to nominal/location hosts such as `bana-nga-kuda` or `yarra-kuda` in sourced patterns.", "Rule 116: TEMP2 host range."),
    ("syntax", "When a narrative jumps across time, bridge it explicitly with `wunkuny`, `muduwajuny`, `wunkuwingku`, `ngadi-ngka`, or `wawu-yinya-muny`.", "Rule 116: time-gap bridge."),
    ("syntax", "`wawu-yinya-muny` is the safe after-that bridge after a completed sequence; it still requires ablative `-muny` and TEMP4 analysis.", "Rule 116: after-that bridge."),
    ("lexicon", "Rule 115 time words become discourse tools in Rule 116; their lexical meanings must stay visible in analysis.", "Rule 116: lexical carryover."),
    ("morphology", "Lexical/time `-ny` forms like `wunkuny` and `muduwajuny` remain allowed, while verbal past surfaces still end in `-n`.", "Rule 116: lexical -ny versus past -n."),
    ("process", "A construction batch can reuse old source examples, but exact prior surfaces must be scanned and avoided.", "Rule 116: exact-source variation."),
    ("process", "Static guards should match the construction: TEMP1/TEMP2/TEMP3/bridge labels are more useful here than generic string bans.", "Rule 116: construction-specific guards."),
    ("process", "Store rejected interpretations, especially for `-kuda`, so later operators do not expand a cautious form into a free marker.", "Rule 116: process memory."),
]

LEXEMES = [
    ("-da", "clitic", None, "TEMP1", "then; following/closing sequence action", "batch-158: sequence-close temporal clitic."),
    ("-kuda", "clitic", None, "TEMP2", "meanwhile; overlapping action", "batch-158: cautious Patz 5.2.2 meanwhile use."),
    ("-(ng)Vrr", "clitic", None, "TEMP3", "first of all", "batch-158: first action/participant/object clitic."),
    ("-l-urr", "verb-clitic", None, "NONPAST-TEMP3", "do first", "batch-158: source waju-l-urr first-action shape."),
    ("-ngurr", "clitic-form", None, "TEMP3 allomorph", "first participant/object", "batch-158: kuyu-ngurr, ngayu-ngurr, nyulu-ngurr rows."),
    ("-ngarr", "clitic-form", None, "TEMP3 allomorph", "first object/action", "batch-158: mayi-ngarr, bana-ngarr, nuka-ngarr rows."),
    ("-rr", "imperative-clitic", None, "TEMP3 imperative", "do first", "batch-158: daya-rr and julurri-ka-rr shapes."),
    ("wundi-l-da", "verb-form", None, "take-NONPAST-TEMP1", "then take", "batch-158: source-shaped sequence close."),
    ("dunga-ny-da", "verb-form", None, "go-PAST-TEMP1", "then went", "batch-158: movement sequence close."),
    ("wuna-ny-da", "verb-form", None, "lie-PAST-TEMP1", "then lay down", "batch-158: sleep/rest sequence close."),
    ("nuka-ny-da", "verb-form", None, "eat-PAST-TEMP1", "then ate", "batch-158: eating sequence close."),
    ("bunda-ny-da", "verb-form", None, "sit-PAST-TEMP1", "then sat", "batch-158: sitting sequence close."),
    ("dara-ny-kuda", "verb-form", None, "fall-PAST-TEMP2", "rain fell meanwhile", "batch-158: weather overlap."),
    ("julurri-ny-kuda", "verb-form", None, "wash-PAST-TEMP2", "washed meanwhile", "batch-158: overlap row."),
    ("wuna-ny-kuda", "verb-form", None, "lie/sleep-PAST-TEMP2", "slept meanwhile", "batch-158: overlap row."),
    ("bana-nga-kuda", "case-form", None, "water-LOC-TEMP2", "meanwhile in the water", "batch-158: Patz ex.630 host shape."),
    ("yarra-kuda", "directional-form", None, "that.way-TEMP2", "that way meanwhile", "batch-158: Patz text-line host shape."),
    ("wunkuny", "temporal", None, "time bridge", "next day; tomorrow", "batch-158: explicit time-gap bridge."),
    ("muduwajuny", "temporal", None, "time bridge", "at daybreak", "batch-158: explicit time-gap bridge."),
    ("wunkuwingku", "temporal", None, "time bridge", "morning", "batch-158: explicit time-gap bridge."),
    ("ngadi-ngka", "case-form", None, "long.time-DAT", "for a long time", "batch-158: long-time temporal bridge."),
    ("wawu-yinya-muny", "case-form", None, "TEMP4-that-ABL", "after that", "batch-158: after-that sequence bridge."),
    ("kadayarr", "imperative-form", None, "come-IMP-TEMP3", "come first/straight away", "batch-158: source imperative shape."),
    ("babaji-ka-rr", "imperative-form", None, "ask-IMP-TEMP3", "ask first", "batch-158: source imperative shape."),
    ("julurri-ka-rr", "imperative-form", None, "wash-IMP-TEMP3", "wash first", "batch-158: source imperative shape."),
    ("nuka-ngarr", "imperative-form", None, "eat.IMP-TEMP3", "eat first", "batch-158: source imperative shape."),
]


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-158-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 Rule 116 rows. Morphology checked TEMP1 -da, TEMP2 -kuda, "
            "TEMP3 allomorphs, TEMP4 wawu-yinya-muny, lexical -ny time forms, and past-surface -n. Lexicon checked "
            "content words against previous source-backed inventory. Syntax checked sequence close, firstness, overlap, "
            "and explicit time bridges. Fidelity checked then/first/meanwhile/after-that English. Register stayed "
            "practical narrative-style pending elder verification."
        ),
        artifact_path=PROCESS_LOG,
        created_at=NOW,
    )
    record_event(
        db,
        batch_label=LABEL,
        phase="review",
        event_type="review-detail",
        actor="claude-main",
        detail=(
            "Rejected-risk decisions retained: no free definite/for-sure reading for -kuda; no blanket -da on every "
            "verb; no unsourced TEMP3 allomorphs beyond source-shaped hosts; no implicit time gaps without a bridge."
        ),
        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 116 lessons covering TEMP1, TEMP2, TEMP3, time bridging, and process safeguards.",
        artifact_path="batch_scripts/close_158.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 116 temporal clitics, allomorphs, and bridge forms.",
        artifact_path="batch_scripts/close_158.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 158: 50 accepted Rule 116 construction rows, five-lens reviews, lessons, lexeme/source logs, and process evidence stored.",
        command="python3 batch_scripts/close_158.py",
        artifact_path="batch_scripts/close_158.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='batch-158-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, under_review={under_review_remaining}, "
        f"verified corpus={verified}"
    )
    return 0


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