"""Mark a memory snapshot falsified or stale (ticket #000017 §2.3).

Falsification cascade scope (ticket §2.3 option B): falsifying a
memory snapshot does NOT auto-rerun upstream-citing records. Operator
can trigger cascade re-evaluation explicitly via a separate command
(future ticket).
"""

from __future__ import annotations

import sqlite3
import time
from typing import Optional

from arborist.store import append_audit


def falsify(
    conn: sqlite3.Connection,
    memory_root: str,
    *,
    reason: str,
    triggering_branch_id: Optional[str] = None,
    ts: Optional[int] = None,
) -> str:
    """Flip memory_root state to ``falsified``; return audit event_hash.

    Idempotent on terminal state.
    """
    row = conn.execute(
        "SELECT state FROM memory_records WHERE memory_root = ?",
        (memory_root,),
    ).fetchone()
    if row is None:
        raise KeyError(f"memory_root not found: {memory_root}")
    if row["state"] == "falsified":
        return ""

    if ts is None:
        ts = int(time.time())

    event_hash = append_audit(
        conn,
        event_type="memory_falsified",
        subject_root=memory_root,
        body={
            "memory_root": memory_root,
            "reason": reason,
            "triggering_branch_id": triggering_branch_id,
        },
        ts=ts,
    )
    conn.execute(
        "UPDATE memory_records "
        "SET state = 'falsified', falsified_at = ?, falsified_reason = ? "
        "WHERE memory_root = ?",
        (ts, reason, memory_root),
    )
    return event_hash


def mark_stale(
    conn: sqlite3.Connection,
    memory_root: str,
    *,
    reason: str,
    ts: Optional[int] = None,
) -> str:
    """Flip memory_root state to ``stale``; return audit event_hash."""
    row = conn.execute(
        "SELECT state FROM memory_records WHERE memory_root = ?",
        (memory_root,),
    ).fetchone()
    if row is None:
        raise KeyError(f"memory_root not found: {memory_root}")
    if row["state"] in ("stale", "falsified"):
        return ""

    if ts is None:
        ts = int(time.time())

    event_hash = append_audit(
        conn,
        event_type="memory_marked_stale",
        subject_root=memory_root,
        body={"memory_root": memory_root, "reason": reason},
        ts=ts,
    )
    conn.execute(
        "UPDATE memory_records SET state = 'stale' WHERE memory_root = ?",
        (memory_root,),
    )
    return event_hash
