from __future__ import annotations

import json
import socket
import sys
from pathlib import Path

import typer

from .app import app, console
from .shared import DEFAULT_SOCKET_PATH


@app.command(name="rpc")
def rpc_command(
    method: str = typer.Argument(
        ...,
        help="RPC method to call (get_state, approve, deny, set_yolo, reset, health)",
    ),
    params: str | None = typer.Argument(
        None,
        help='JSON params for the method (e.g., \'{"request_id": "abc"}\')',
    ),
    socket_path: str | None = typer.Option(
        None,
        "--socket",
        "-s",
        help=f"Unix socket path (default: {DEFAULT_SOCKET_PATH})",
    ),
) -> None:
    sock_path = Path(socket_path) if socket_path else DEFAULT_SOCKET_PATH

    if not sock_path.exists():
        console.print(f"[red]RPC socket not found: {sock_path}[/red]")
        console.print("Is the server running? Start with: [bold]claude-board serve[/bold]")
        raise typer.Exit(1)

    parsed_params: dict[str, object] = {}
    if params:
        try:
            parsed_params = json.loads(params)
        except json.JSONDecodeError as e:
            console.print(f"[red]Invalid JSON params: {e}[/red]")
            raise typer.Exit(1) from None

    request = {"jsonrpc": "2.0", "method": method, "params": parsed_params, "id": 1}

    try:
        client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        client.connect(str(sock_path))
        client.settimeout(5.0)
        client.sendall((json.dumps(request) + "\n").encode("utf-8"))

        response_data = b""
        while True:
            chunk = client.recv(4096)
            if not chunk:
                break
            response_data += chunk
            if b"\n" in response_data:
                break

        client.close()
        response = json.loads(response_data.decode("utf-8"))
        if "error" in response:
            console.print(f"[red]Error:[/red] {response['error']['message']}")
            raise typer.Exit(1)

        result = response.get("result", {})
        console.print_json(json.dumps(result, indent=2, default=str))

    except FileNotFoundError:
        console.print(f"[red]Socket not found: {sock_path}[/red]")
        raise typer.Exit(1) from None
    except ConnectionRefusedError:
        console.print("[red]Connection refused. Is the server running?[/red]")
        raise typer.Exit(1) from None
    except (OSError, json.JSONDecodeError, KeyError, TypeError) as e:
        console.print(f"[red]RPC error: {e}[/red]")
        raise typer.Exit(1) from None


@app.command(name="hook", hidden=True)
def hook_command(
    hook_type: str = typer.Argument(
        "permission",
        help=(
            "Hook type: 'permission', 'todo', 'stop',"
            " 'session_start', or 'session_end'"
        ),
    ),
) -> None:
    if hook_type == "permission":
        from ..hooks.permission_hook import main as permission_main  # noqa: PLC0415

        permission_main()
    elif hook_type == "todo":
        from ..hooks.todo_hook import main as todo_main  # noqa: PLC0415

        todo_main()
    elif hook_type == "stop":
        from ..hooks.stop_hook import main as stop_main  # noqa: PLC0415

        stop_main()
    elif hook_type == "session_start":
        from ..hooks.session_start_hook import main as session_start_main  # noqa: PLC0415

        session_start_main()
    elif hook_type == "session_end":
        from ..hooks.session_end_hook import main as session_end_main  # noqa: PLC0415

        session_end_main()
    else:
        print(f"Unknown hook type: {hook_type}", file=sys.stderr)
        sys.exit(1)
