"""
acrf-turn-guardian CLI

Commands:
    acrf-turn-guardian start <intent> [--context JSON] [--id ID]
        Start a new guarded conversation.

    acrf-turn-guardian add-turn <conv-id> <role> <text>
        Append a turn to a conversation.

    acrf-turn-guardian check-action <conv-id> <action-json>
        Check a proposed action against the conversation intent.

    acrf-turn-guardian show <conv-id>
        Print the current state of a conversation.

    acrf-turn-guardian list
        List all conversations.

Set the session file path via env var:
    export ACRF_TURN_SESSION=/path/to/sessions.json
"""
import argparse
import json
import os
import sys
from pathlib import Path

from acrf_turn_guardian.exceptions import (
    ConversationNotFoundError,
    TurnGuardError,
)
from acrf_turn_guardian.session_manager import SessionManager

SESSION_ENV_VAR = "ACRF_TURN_SESSION"


def _require_session_path() -> Path:
    path = os.environ.get(SESSION_ENV_VAR)
    if not path:
        print(f"ERROR: Environment variable {SESSION_ENV_VAR} not set.", file=sys.stderr)
        print(f"Set it with: export {SESSION_ENV_VAR}=/path/to/sessions.json", file=sys.stderr)
        sys.exit(2)
    return Path(path)


def _load_manager() -> SessionManager:
    path = _require_session_path()
    if path.exists():
        return SessionManager.load(path)
    return SessionManager()


def _save_manager(manager: SessionManager) -> None:
    path = _require_session_path()
    manager.save(path)


def _parse_json(name: str, value: str | None) -> dict:
    if not value:
        return {}
    try:
        data = json.loads(value)
    except json.JSONDecodeError as exc:
        print(f"ERROR: --{name} is not valid JSON: {exc}", file=sys.stderr)
        sys.exit(1)
    if not isinstance(data, dict):
        print(f"ERROR: --{name} must be a JSON object", file=sys.stderr)
        sys.exit(1)
    return data


def cmd_start(args: argparse.Namespace) -> int:
    manager = _load_manager()
    context = _parse_json("context", args.context)
    guard = manager.start(
        initial_intent=args.intent,
        initial_context=context,
        conversation_id=args.id,
    )
    _save_manager(manager)
    print(f"Started conversation: {guard.state.conversation_id}")
    print(f"  intent: {guard.state.initial_intent}")
    if guard.intent_family:
        print(f"  intent_family: {guard.intent_family}")
    return 0


def cmd_add_turn(args: argparse.Namespace) -> int:
    manager = _load_manager()
    try:
        guard = manager.get(args.conv_id)
    except ConversationNotFoundError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1

    try:
        guard.add_turn(role=args.role, text=args.text)
    except TurnGuardError as exc:
        print(f"FAIL: {exc.__class__.__name__}: {exc}", file=sys.stderr)
        return 1

    _save_manager(manager)
    print(f"OK: turn {guard.turn_count()} added")
    return 0


def cmd_check_action(args: argparse.Namespace) -> int:
    manager = _load_manager()
    try:
        guard = manager.get(args.conv_id)
    except ConversationNotFoundError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1

    action = _parse_json("action", args.action)

    try:
        guard.check_action(action)
    except TurnGuardError as exc:
        print(f"FAIL: {exc.__class__.__name__}: {exc}", file=sys.stderr)
        return 1

    print("OK: action allowed")
    return 0


def cmd_show(args: argparse.Namespace) -> int:
    manager = _load_manager()
    try:
        guard = manager.get(args.conv_id)
    except ConversationNotFoundError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        return 1
    print(guard.to_json())
    return 0


def cmd_list(args: argparse.Namespace) -> int:
    manager = _load_manager()
    ids = manager.conversation_ids()
    print(f"Conversations ({len(ids)}):")
    for conv_id in ids:
        guard = manager.get(conv_id)
        closed = " (closed)" if guard.state.closed else ""
        print(f"  {conv_id}  intent={guard.state.initial_intent!r}  turns={guard.turn_count()}{closed}")
    return 0


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="acrf-turn-guardian",
        description="Multi-turn conversation drift detection (ACRF-07).",
    )
    sub = parser.add_subparsers(dest="command", required=True)

    p_start = sub.add_parser("start", help="Start a new guarded conversation")
    p_start.add_argument("intent")
    p_start.add_argument("--context", default=None, help="Initial context as JSON object")
    p_start.add_argument("--id", default=None, help="Optional conversation id (autogenerated if omitted)")
    p_start.set_defaults(func=cmd_start)

    p_add = sub.add_parser("add-turn", help="Append a turn to a conversation")
    p_add.add_argument("conv_id")
    p_add.add_argument("role", choices=["user", "assistant", "system"])
    p_add.add_argument("text")
    p_add.set_defaults(func=cmd_add_turn)

    p_chk = sub.add_parser("check-action", help="Check an action against the conversation")
    p_chk.add_argument("conv_id")
    p_chk.add_argument("action", help="Action as JSON object e.g. \"{\\\"action\\\":\\\"buy\\\"}\"")
    p_chk.set_defaults(func=cmd_check_action)

    p_show = sub.add_parser("show", help="Print the conversation state")
    p_show.add_argument("conv_id")
    p_show.set_defaults(func=cmd_show)

    p_list = sub.add_parser("list", help="List all conversations")
    p_list.set_defaults(func=cmd_list)

    return parser


def main(argv: list[str] | None = None) -> int:
    parser = build_parser()
    args = parser.parse_args(argv)
    return args.func(args)


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