"""Structured output and error handling for OpenClaw Sandbox CLI."""

import json
import sys

from .const import PROVIDER_NAME

# --- Exit codes (grouped by category) ---

EXIT_OK = 0
EXIT_UNKNOWN = 1
EXIT_MISSING_API_KEY = 10
EXIT_SANDBOX_CREATE = 20
EXIT_SANDBOX_CONNECT = 21
EXIT_SANDBOX_TIMEOUT = 22
EXIT_GATEWAY_TIMEOUT = 30
EXIT_GATEWAY_FAILED = 31
EXIT_API_ERROR = 40
EXIT_OPENCLAW_NOT_INSTALLED = 50
EXIT_DOCTOR_FAILED = 60

# --- JSON mode state ---

_json_mode = False


def set_json_mode(enabled: bool):
    global _json_mode
    _json_mode = enabled


def is_json_mode() -> bool:
    return _json_mode


# --- Custom exceptions ---


class CLIError(Exception):
    """Base exception for structured CLI errors."""

    def __init__(self, message: str, error_code: str, exit_code: int = 1):
        super().__init__(message)
        self.error_code = error_code
        self.exit_code = exit_code



class MissingApiKeyError(CLIError):
    def __init__(self, message: str = None):
        if message is None:
            message = "{provider} API key is required.".format(provider=PROVIDER_NAME)
        super().__init__(message, "MISSING_API_KEY", EXIT_MISSING_API_KEY)


class SandboxCreateError(CLIError):
    def __init__(self, message: str = "Failed to create sandbox."):
        super().__init__(message, "SANDBOX_CREATE_FAILED", EXIT_SANDBOX_CREATE)


class SandboxConnectError(CLIError):
    def __init__(self, message: str = "Failed to connect to sandbox."):
        super().__init__(message, "SANDBOX_CONNECT_FAILED", EXIT_SANDBOX_CONNECT)


class GatewayTimeoutError(CLIError):
    def __init__(self, message: str = "Gateway did not start in time."):
        super().__init__(message, "GATEWAY_TIMEOUT", EXIT_GATEWAY_TIMEOUT)


class DoctorError(CLIError):
    def __init__(self, message: str = "Doctor command failed."):
        super().__init__(message, "DOCTOR_FAILED", EXIT_DOCTOR_FAILED)


# --- JSON output helpers ---


def output_success(data: dict):
    """Print JSON success payload to stdout and return."""
    payload = {"status": "ok", **data}
    print(json.dumps(payload), flush=True)


def output_error(error_code: str, message: str, exit_code: int = 1):
    """Print JSON error payload to stdout and raise SystemExit."""
    payload = {"status": "error", "error_code": error_code, "message": message}
    print(json.dumps(payload), flush=True)
    raise SystemExit(exit_code)
