"""GDB client error hierarchy and AI-friendly error translation."""

from __future__ import annotations

from typing import Any

from fastmcp.exceptions import ToolError


class GDBClientError(Exception):
    """Base error for all GDB client operations."""

    def __init__(self, message: str = "", status_code: int | None = None):
        self.status_code = status_code
        super().__init__(message)


class GDBAuthError(GDBClientError):
    """401/403 — token expired or insufficient permissions."""


class GDBNotFoundError(GDBClientError):
    """404 — resource not found."""


class GDBValidationError(GDBClientError):
    """400 — field-level validation errors from DRF."""

    def __init__(self, errors: dict[str, Any] | str, status_code: int = 400):
        self.field_errors = errors if isinstance(errors, dict) else {}
        msg = _format_validation_errors(errors)
        super().__init__(msg, status_code)


class GDBServerError(GDBClientError):
    """500+ — server-side error."""


def _format_validation_errors(errors: dict[str, Any] | str) -> str:
    if isinstance(errors, str):
        return errors
    if isinstance(errors, dict):
        if "detail" in errors:
            return str(errors["detail"])
        parts = []
        for field, msgs in errors.items():
            if isinstance(msgs, list):
                parts.append(f"{field}: {', '.join(str(m) for m in msgs)}")
            else:
                parts.append(f"{field}: {msgs}")
        return "; ".join(parts)
    return str(errors)


def translate_error(
    error: Exception,
    *,
    resource_type: str | None = None,
    resource_id: str | int | None = None,
) -> ToolError:
    """Translate a GDB client error into an AI-friendly ToolError."""
    resource_desc = resource_type or "resource"
    if resource_id is not None:
        resource_desc = f"{resource_desc} {resource_id}"

    if isinstance(error, GDBNotFoundError):
        return ToolError(
            f"GDB {resource_desc} not found. "
            f"Use gdb_catalog_list to discover available databases."
        )
    if isinstance(error, GDBAuthError):
        return ToolError(
            f"GDB authentication failed for {resource_desc}. "
            f"Run auth_login (BPA MCP) to authenticate — GDB shares the same token."
        )
    if isinstance(error, GDBValidationError):
        return ToolError(f"GDB validation failed for {resource_desc}: {error}")
    if isinstance(error, GDBServerError):
        return ToolError(
            f"GDB server error for {resource_desc}: {error}. "
            f"This is a backend issue — retry or check gdb_status."
        )
    return ToolError(f"GDB error for {resource_desc}: {error}")
