#!/usr/bin/env python3
"""Local LangGraph wiring walkthrough. Synthetic data, no model or network calls.
Requires langgraph installed in an isolated environment; see companion README.
InMemorySaver demonstrates interrupt/resume, NOT persistence across restarts.
"""
from typing import TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command, interrupt


class DraftState(TypedDict):
    source: str
    draft: str
    status: str


def draft(state: DraftState):
    return {"draft": "Operator draft: " + state["source"], "status": "awaiting_review"}


def review(state: DraftState):
    # Node re-enters on resume. Do not put external side effects before interrupt.
    decision = interrupt({"draft": state["draft"], "scope": "Accept or reject a synthetic local draft; nothing is sent."})
    if decision not in ("accepted", "rejected"):
        raise ValueError("invalid_decision")
    return {"status": decision}


def build():
    graph = StateGraph(DraftState)
    graph.add_node("draft", draft)
    graph.add_node("review", review)
    graph.add_edge(START, "draft")
    graph.add_edge("draft", "review")
    graph.add_edge("review", END)
    return graph.compile(checkpointer=InMemorySaver())


def main():
    graph = build()
    # The host must scope and authorize thread access in a deployed system.
    config = {"configurable": {"thread_id": "synthetic-north-R1"}}
    waiting = graph.invoke({"source": "Inspect the disconnected training unit.", "draft": "", "status": "new"}, config)
    assert waiting["status"] == "awaiting_review"
    assert waiting.get("__interrupt__"), "A review interrupt must be visible"
    print("Observed: awaiting_review; interrupt contains the proposed local draft.")
    accepted = graph.invoke(Command(resume="accepted"), config)
    assert accepted["status"] == "accepted"
    print("Observed: accepted after explicit scripted resume; no message was sent.")
    print("This walkthrough scripts the reviewer decision and uses process-local memory.")
    print("Use the companion SQLite reference for a separate restart experiment.")


if __name__ == "__main__":
    main()
