from __future__ import annotations

import json
import sys
import traceback

from aegro.errors import (
    AegroAPIError,
    FarmNotFoundError,
    InvalidKeyError,
    NoFarmSelectedError,
)

EXIT_OK = 0
EXIT_ERROR = 1
EXIT_AUTH = 2
EXIT_NOT_FOUND = 3
EXIT_VALIDATION = 4


def handle_error(exc: Exception) -> None:
    """Print structured JSON error to stderr and exit with semantic code."""
    if isinstance(exc, NoFarmSelectedError):
        _exit_json("NO_FARM_SELECTED", str(exc), EXIT_AUTH)
    elif isinstance(exc, FarmNotFoundError):
        _exit_json("FARM_NOT_FOUND", str(exc), EXIT_NOT_FOUND)
    elif isinstance(exc, InvalidKeyError):
        _exit_json("INVALID_KEY", str(exc), EXIT_VALIDATION)
    elif isinstance(exc, AegroAPIError):
        if exc.status_code in (401, 403):
            _exit_json("AUTH_ERROR", exc.user_message, EXIT_AUTH, status=exc.status_code)
        else:
            _exit_json("API_ERROR", exc.user_message, EXIT_ERROR, status=exc.status_code)
    else:
        traceback.print_exc(file=sys.stderr)
        _exit_json("UNEXPECTED", str(exc), EXIT_ERROR)


def _exit_json(code: str, message: str, exit_code: int, *, status: int | None = None) -> None:
    error: dict = {"code": code, "message": message}
    if status is not None:
        error["status"] = status
    print(json.dumps({"error": error}), file=sys.stderr)
    raise SystemExit(exit_code)
