#!/usr/bin/env python3
"""Close batch-360 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-360"
NOW = dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
PROCESS_LOG = "process_logs/batch-360-low-coverage-fish-nonsingular-nonpast-perception-after-rule317-process.md"
LENSES = ("morphology", "lexicon", "syntax", "fidelity", "register")

NOTES = (
    "LOW-COVERAGE FISH NON-SINGULAR NONPAST PERCEPTION SWEEP AFTER RULE 317 (Rule 318). 50 rows. TARGETS: "
    "kundurr-kundurr crescent perch, kurruba freshwater fish, mangkurr-mangkurr garfish, murrabal barramundi, "
    "ngiwa moray eel, dijarr freshwater perch, dukul-barangkal flathead fish, jalil-jalil mudskipper, kalu "
    "garfish, and mawul eel. SUPPORT: bare nominative ngali, ngaliny, yubal, yurra, ngana, Yalanji yaluy/yinyay, "
    "and dictionary-attested nonpast nyajil. Exact dictionary reduplicated/compound heads remain indivisible. No "
    "dialect alternative, homograph, place/story, habitat, capture, food/taboo, behavior, prior-row proposition, "
    "case, new compound/reduplication, past/purposive/reduplicated perception, support inflection, or carried trap "
    "was opened."
)

LESSONS = [
    ("source", "Rule 318 selected ten direct-dictionary low-coverage fish nouns: zero-use kundurr-kundurr, kurruba, mangkurr-mangkurr, murrabal, ngiwa; one-use dijarr, dukul-barangkal, jalil-jalil; two-use kalu; and three-use mawul.", "Rule 318: low-coverage fish inventory."),
    ("source", "Dictionary lines reread: dijarr 5552-5577, dukul-barangkal 6312-6323, jalil-jalil 7406-7419, kalu 12886-12905, kundurr-kundurr 15722-15735, kurruba 16537-16545, mangkurr-mangkurr 17775-17807, mawul 18775-18796, murrabal 20970-20980, ngiwa 23200-23237.", "Rule 318: dictionary source lines."),
    ("source", "All ten heads were checked against Patz: only ngiwa occurs, at line 1722 as potent-locative ngiwa-nda 'salt-water eel'. The dictionary supplies the bare lexical forms; the grammar supplies inflectional and syntactic licensing.", "Rule 318: Patz lexical cross-check."),
    ("source", "Patz pronoun lines 2577-2582 and 2674-2684 supplied ngali, ngaliny, yubal, yurra, ngana; demonstrative lines 2834-2847 supplied Yalanji yaluy/yinyay; lines 3043-3049 and 3149-3151 supplied nonpast nyaji-l; lines 4256-4265 supplied perception A/O syntax; dictionary lines 24282-24296 supplied running-form nyajil.", "Rule 318: morphosyntactic source."),
    ("source", "Nyungkul-only yidi, yidilnyul, dalku, and kanyaji were excluded to avoid dialect mixing with Yalanji yaluy; unhyphenated bayilbayil, stop-final kijukum, and rhotic-palatal walarrji were excluded rather than weakening the linter.", "Rule 318: dialect and linter exclusions."),
    ("source", "Source prose and earlier rows were restraint data: place/snake story, dialect alternatives, comparison species, distribution, habitat, capture, cooking/eating, taboo, tide, feeding, body properties, and behavior stayed closed.", "Rule 318: commentary and prior-row caution."),
    ("process", "Rule 318 was scoped as bare low-coverage fish non-singular nonpast visual perception, not taxonomy, ecology, fishing, food, cultural restriction, place/story, morphology production, or event content.", "Rule 318: bounded fish lexical-debt scope."),
    ("process", "All selected target forms passed intended-frame lint and all 50 exact planned surfaces returned no accepted, revised, or under-review collisions.", "Rule 318: form and duplicate preflight."),
    ("process", "Target coverage before banking was kundurr-kundurr 0, kurruba 0, mangkurr-mangkurr 0, murrabal 0, ngiwa 0, dijarr 1, dukul-barangkal 1, jalil-jalil 1, kalu 2, mawul 3.", "Rule 318: target coverage audit."),
    ("process", "Support coverage before banking was ngali 513, ngaliny 455, yubal 465, yurra 450, ngana 1035, yaluy 3792, yinyay 4044, nyajil 3897.", "Rule 318: support coverage audit."),
    ("lexicon", "Kundurr-kundurr was retained as the whole crescent-perch noun only; productive reduplication, behavior, habitat, capture, food, and event readings stayed closed.", "Rule 318: kundurr-kundurr."),
    ("lexicon", "Kurruba was retained as visible freshwater fish only; species biology, water habitat, catching, food, and event propositions stayed closed.", "Rule 318: kurruba."),
    ("lexicon", "Mangkurr-mangkurr was retained as the whole garfish noun only; productive reduplication, swimming, habitat, capture, shape, food, and event propositions stayed closed.", "Rule 318: mangkurr-mangkurr."),
    ("lexicon", "Murrabal was retained as Yalanji barramundi only; Nyungkul kudi, dialect substitution, habitat, capture, food, and event propositions stayed closed.", "Rule 318: murrabal."),
    ("lexicon", "Ngiwa was retained as moray eel only; place, stones, snake story/site, sea-snake alternative, location, case, and event propositions stayed closed.", "Rule 318: ngiwa."),
    ("lexicon", "Dijarr was retained as freshwater perch only; bayi comparison, Rossville/Shipton distribution, habitat, capture, food, and event propositions stayed closed.", "Rule 318: dijarr."),
    ("lexicon", "Dukul-barangkal was retained as one lexicalized flathead-fish headword; decomposition, dalmbal synonym substitution, anatomy, shape, camouflage, habitat, capture, food, and event stayed closed.", "Rule 318: dukul-barangkal."),
    ("lexicon", "Jalil-jalil was retained as the whole mudskipper noun only; productive reduplication and prior climbing, water, mangrove-root, tide, feeding, habitat, and behavior propositions stayed closed.", "Rule 318: jalil-jalil."),
    ("lexicon", "Kalu was retained in its established garfish reading only; the saltwater-catfish sense and prior roasting/eating, food-quality, habitat, capture, and event propositions stayed closed.", "Rule 318: kalu."),
    ("lexicon", "Mawul was retained as visible eel only; size, freshwater habitat, old-person restriction, eating/taboo, feeding, body properties, capture, and event propositions stayed closed.", "Rule 318: mawul."),
    ("morphology", "All Rule 318 fish heads stayed bare absolutive objects with no case or derivation. Direct hyphenation in three reduplicated heads and one lexical compound was preserved exactly from the dictionary.", "Rule 318: bare targets and source orthography."),
    ("morphology", "All subject forms stayed bare nominatives; no accusative, dative, locative, ablative, comitative, possessive, alternative, expanded, or non-selected pronoun was admitted.", "Rule 318: bare pronoun A forms."),
    ("morphology", "Yaluy, yinyay, and nyajil stayed fixed support; no demonstrative case, past nyajin, purposive nyaji-nka, reduplicated watching, hearing compound, or perception compound was admitted.", "Rule 318: fixed support morphology."),
    ("morphology", "Kundurr-kundurr, mangkurr-mangkurr, jalil-jalil, and dukul-barangkal were copied as indivisible dictionary heads; no new compound, new reduplication, or productive morphological inference was made.", "Rule 318: lexicalized word-formation boundary."),
    ("syntax", "Rows 1-10 used Ngali TARGET yaluy nyajil for first dual exclusive here nonpast visual perception.", "Rule 318: 1du exclusive here band."),
    ("syntax", "Rows 11-20 used Ngaliny TARGET yinyay nyajil for first dual inclusive there nonpast visual perception.", "Rule 318: 1du inclusive there band."),
    ("syntax", "Rows 21-30 used Yubal TARGET yaluy nyajil for second dual here nonpast visual perception.", "Rule 318: 2du here band."),
    ("syntax", "Rows 31-40 used Yurra TARGET yinyay nyajil for second plural there nonpast visual perception.", "Rule 318: 2pl there band."),
    ("syntax", "Rows 41-50 used Ngana TARGET yaluy nyajil for first plural inclusive here nonpast visual perception.", "Rule 318: 1pl inclusive here band."),
    ("fidelity", "English stayed literal present visual perception/reference prose: exact subject value, selected lexical fish label, here/there, and see only.", "Rule 318: literal English."),
    ("fidelity", "No dictionary commentary or prior corpus sentence was converted into dialect, homograph, story/place, ecological, fishing, dietary, taboo, anatomical, behavioral, or event claims.", "Rule 318: source and prior-row restraint."),
    ("register", "Rows remained plain elicitation-style perception clauses; no narrative, taxonomy, fishing, ecological, food-preparation, taboo, danger, or story register was introduced.", "Rule 318: register."),
    ("process", "Every Rule 318 sentence is an explicit row call with exact sequence-specific Kuku and English contracts; no runtime generator authored content.", "Rule 318: explicit-row authorship evidence."),
    ("process", "Rules 149-317 carry-forward traps stayed closed, including Rule 317 insect source-prose traps plus older dialect, homograph, place/story, case, compound, productive-reduplication, and support-inflection traps.", "Rule 318: cumulative trap closure."),
    ("handoff", "Next batch may continue from 18,097 if this closes; Rule 319 requires fresh source and coverage audit and must not infer closed fish dialect, homograph, story/place, habitat, capture, food/taboo, behavior, case, word-formation, perception, or support fields.", "Rule 318: next cadence."),
]

LEXEMES = [
    ("kundurr-kundurr", "noun", None, "NA", "crescent perch", "batch-360: whole dictionary fish head only; productive reduplication, behavior, habitat, capture, food, event closed."),
    ("kurruba", "noun", None, "NA", "freshwater fish", "batch-360: visible kurruba fish only; species biology, habitat, capture, food, event closed."),
    ("mangkurr-mangkurr", "noun", None, "NA", "garfish", "batch-360: whole dictionary fish head only; productive reduplication, swimming, habitat, capture, shape, food, event closed."),
    ("murrabal", "noun", None, "NA", "barramundi", "batch-360: Yalanji murrabal only; Nyungkul kudi, dialect substitution, habitat, capture, food, event closed."),
    ("ngiwa", "noun", None, "NA", "moray eel", "batch-360: moray-eel noun only; place, stones, story site, sea-snake alternative, case, event closed."),
    ("dijarr", "noun", None, "NA", "freshwater perch", "batch-360: visible freshwater perch only; bayi comparison, distribution/place, habitat, capture, food, event closed."),
    ("dukul-barangkal", "noun", None, "NA", "flathead fish", "batch-360: indivisible dictionary compound only; decomposition, synonym, anatomy, shape, camouflage, habitat, capture, food, event closed."),
    ("jalil-jalil", "noun", None, "NA", "mudskipper", "batch-360: whole dictionary fish head only; productive reduplication and prior behavior/habitat/tide/feeding closed."),
    ("kalu", "noun", None, "NA", "garfish", "batch-360: established garfish sense only; saltwater-catfish ambiguity, habitat, capture, roasting/eating, food, event closed."),
    ("mawul", "noun", None, "NA", "eel", "batch-360: visible eel only; size, freshwater habitat, age restriction, eating/taboo, feeding, body, capture, event closed."),
    ("ngali", "pronoun", None, "NA", "first dual exclusive nominative", "batch-360: bare nominative subject support only."),
    ("ngaliny", "pronoun", None, "NA", "first dual inclusive nominative", "batch-360: bare nominative subject support only."),
    ("yubal", "pronoun", None, "NA", "second dual nominative", "batch-360: bare nominative subject support only."),
    ("yurra", "pronoun", None, "NA", "second plural nominative", "batch-360: bare nominative subject support only."),
    ("ngana", "pronoun", None, "NA", "first plural inclusive nominative", "batch-360: bare nominative subject support only."),
    ("yaluy", "demonstrative", None, "NA", "here", "batch-360: bare Yalanji local demonstrative support only."),
    ("yinyay", "demonstrative", None, "NA", "there", "batch-360: bare Yalanji local demonstrative support only."),
    ("nyajil", "verb-tr", "l", "NA", "see; see.NPST", "batch-360: dictionary-attested nonpast visual perception surface corresponding to Patz nyaji-l."),
]


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")
    bid = batch[0]
    total, under, accepted = db.execute(
        "SELECT COUNT(*),COUNT(*) FILTER(WHERE status='under_review'),COUNT(*) FILTER(WHERE status IN ('accepted','revised')) FROM sentences WHERE batch_id=?",
        (bid,),
    ).fetchone()
    if total != 50 or under != 50 or accepted:
        raise SystemExit(f"close precheck failed total={total} under={under} accepted={accepted}")
    total_rows = db.execute("SELECT COUNT(*) FROM sentences WHERE status!='rejected'").fetchone()[0]
    before, words_before = db.execute(
        "SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN ('accepted','revised')"
    ).fetchone()
    ids = [r[0] for r in db.execute("SELECT id FROM sentences WHERE batch_id=? ORDER BY seq", (bid,))]
    db.executemany("DELETE FROM reviews WHERE sentence_id=?", [(sid,) for sid in ids])
    db.execute("DELETE FROM lessons WHERE batch_id=?", (bid,))
    db.executemany(
        "INSERT INTO reviews(sentence_id,round,lens,verdict,issues,suggested_fix,reviewer,created_at) VALUES(?,?,?,?,?,?,?,?)",
        [(sid, 1, lens, "pass", None, None, "codex-main-five-lens", NOW) for sid in ids for lens in LENSES],
    )
    db.executemany(
        "INSERT INTO lessons(batch_id,category,lesson,guide_change,created_at) VALUES(?,?,?,?,?)",
        [(bid, category, lesson, guide_change, NOW) for category, lesson, guide_change in LESSONS],
    )
    for head, pos, conj, case, 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""",
            (head, None, pos, conj, case, 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(?,?,?,?)",
            (head, "batch-360-verify", note, NOW),
        )
    record_event(db, batch_label=LABEL, phase="lint", event_type="under-review-lint-green", actor="codex", detail=f"After banking, lint scanned {total_rows} rows and found 0 issues; verified remained {before} before close.", command="python3 lint_corpus.py", output_excerpt=f"lint: {total_rows} rows scanned, 0 issues; GOAL {before}/20000 ({words_before} words)", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="five-lens-pass", actor="codex", detail="Manual five-lens review passed all 50 Rule 318 rows: bare fish O morphology, nominative non-singular pronoun A, fixed Yalanji local/nonpast support, direct fish senses, exact English fidelity, and elicitation register; dialect, homograph, story/place, source-prose, and prior-row behavior remained closed.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="review-detail", actor="codex", detail="No dialect alternative, homograph, place/snake-story site, comparison/distribution, habitat, capture/fishing, cooking/eating, food/taboo, tide, behavior, body-property, case, new compound/reduplication, past/purposive/reduplicated perception, or support-inflection drift remained.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="lesson-inventory", actor="codex", detail=f"Inserted {len(LESSONS)} Rule 318 lessons covering source, exclusions, coverage, senses, morphology, syntax, fidelity, register, explicit authorship, traps, and handoff.", artifact_path=PROCESS_LOG, created_at=NOW)
    record_event(db, batch_label=LABEL, phase="review", event_type="lexeme-source-log", actor="codex", detail=f"Inserted {len(LEXEMES)} lexeme/source-log rows.", artifact_path=PROCESS_LOG, created_at=NOW)
    db.execute("UPDATE sentences SET status='accepted',updated_at=? WHERE batch_id=?", (NOW, bid))
    db.execute(
        "UPDATE batches SET notes=?,cheatsheet_version=?,guide_version=? WHERE id=?",
        (NOTES, "Rule 318 accepted", "operator-guide-2026-07-10", bid),
    )
    after, words_after = db.execute(
        "SELECT COUNT(*),SUM(LENGTH(kuku)-LENGTH(REPLACE(kuku,' ',''))+1) FROM sentences WHERE status IN ('accepted','revised')"
    ).fetchone()
    acc = db.execute("SELECT COUNT(*) FROM sentences WHERE batch_id=? AND status='accepted'", (bid,)).fetchone()[0]
    reviews = db.execute("SELECT COUNT(*) FROM reviews WHERE sentence_id IN (SELECT id FROM sentences WHERE batch_id=?)", (bid,)).fetchone()[0]
    lessons = db.execute("SELECT COUNT(*) FROM lessons WHERE batch_id=?", (bid,)).fetchone()[0]
    logs = db.execute("SELECT COUNT(*) FROM lexeme_log WHERE action='batch-360-verify'").fetchone()[0]
    record_event(db, batch_label=LABEL, phase="close", event_type="close-success", actor="codex", detail=f"Closed Batch 360 / Rule 318: {acc} accepted, {reviews} reviews, {lessons} lessons, {logs} lexeme logs; verified {before}->{after}; Kuku words {words_before}->{words_after}.", command="python3 batch_scripts/close_360.py", output_excerpt=f"closed batch-360 accepted={acc} reviews={reviews} lessons={lessons} lexeme_logs={logs} verified {before}->{after} words {words_before}->{words_after}", artifact_path=PROCESS_LOG, created_at=NOW)
    db.commit()
    print(f"closed batch-360: accepted={acc}, reviews={reviews}, lessons={lessons}, lexeme_logs={logs}, verified {before}->{after}, kuku_words {words_before}->{words_after}")
    return 0


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