"""Native LangGraph approval tutorial. Synthetic action, local files, no API key.

Tested with langgraph==1.2.16 and langgraph-checkpoint-sqlite==3.1.2.
This demonstrates pause/resume, not authenticated approval or signed evidence.
"""

import argparse
import json
import os
from pathlib import Path
import socket
import sqlite3
from typing import TypedDict

os.environ["LANGSMITH_TRACING"] = "false"
os.environ["LANGCHAIN_TRACING_V2"] = "false"


def no_network(*args, **kwargs):
    raise RuntimeError("This local tutorial does not use the network.")


socket.socket.connect = no_network
socket.create_connection = no_network

from langgraph.checkpoint.sqlite import SqliteSaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import Command, interrupt


class State(TypedDict):
    action: dict
    status: str


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("command", choices=("start", "approve", "reject", "status"))
    parser.add_argument("--store", default="langgraph-demo")
    args = parser.parse_args()
    store = Path(args.store)
    store.mkdir(parents=True, exist_ok=True)
    config = {"configurable": {"thread_id": "synthetic-refund-001"}}

    with sqlite3.connect(store / "mock-effects.sqlite") as effects:
        effects.execute("CREATE TABLE IF NOT EXISTS effects (action TEXT NOT NULL)")
        effects.commit()

        def review(state):
            approved = interrupt({"action": state["action"], "question": "Approve this mock refund?"})
            if approved is not True:
                return {"status": "rejected"}
            # This insertion is the entire mock effect. Never put it before interrupt().
            with effects:
                effects.execute("INSERT INTO effects VALUES (?)", (json.dumps(state["action"]),))
            return {"status": "mock_recorded"}

        with SqliteSaver.from_conn_string(str(store / "checkpoints.sqlite")) as saver:
            graph = (StateGraph(State).add_node("review", review)
                     .add_edge(START, "review").add_edge("review", END)
                     .compile(checkpointer=saver))
            saved = graph.get_state(config)
            if args.command == "start":
                if saved.values:
                    parser.error("This store already contains a run. Choose a new --store directory.")
                graph.invoke({"action": {"order_id": "synthetic-order-42", "amount_cents": 12500,
                                         "currency": "USD"}, "status": "new"}, config)
            elif args.command != "status":
                if not saved.values:
                    parser.error("Start the run before submitting a decision.")
                graph.invoke(Command(resume=args.command == "approve"), config)
            saved = graph.get_state(config)
            records = [json.loads(row[0]) for row in effects.execute("SELECT action FROM effects")]
            print(json.dumps({"status": "pending" if saved.next else saved.values.get("status", "not_started"),
                              "action": saved.values.get("action"), "mock_effects": records}, indent=2))


if __name__ == "__main__":
    main()
