from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


class WataError(Exception):
    """Base exception for all aiowata errors."""


class WataAPIError(WataError):
    """Non-2xx response from the WATA API.

    Attributes:
        status: HTTP status code.
        code: WATA error code (if provided).
        details: Human-readable error details from the API.
        data: Additional data returned in the error body.
        response_body: Raw parsed response body for debugging.
    """

    def __init__(
        self,
        status: int,
        message: str = "",
        *,
        code: str | None = None,
        details: str | None = None,
        data: dict[str, Any] | None = None,
        response_body: Any = None,
    ) -> None:
        self.status = status
        self.code = code
        self.details = details
        self.data = data or {}
        self.response_body = response_body
        super().__init__(message or f"HTTP {status}")

    def __str__(self) -> str:
        parts = [f"[HTTP {self.status}]"]
        base_msg = self.args[0] if self.args else ""
        if base_msg:
            parts.append(base_msg)
        if self.details:
            parts.append(self.details)
        if self.code:
            parts.append(f"(code: {self.code})")
        return " ".join(parts)


class WataAuthError(WataAPIError):
    """HTTP 401 — invalid or expired access token."""


class WataForbiddenError(WataAPIError):
    """HTTP 403 — insufficient permissions for the requested endpoint."""


class WataRateLimitError(WataAPIError):
    """HTTP 429 — rate limit exceeded.

    Attributes:
        retry_after: Seconds to wait before the next request (``None`` if
            the server did not provide a value).
    """

    def __init__(
        self,
        retry_after: float | None = None,
        **kwargs: Any,
    ) -> None:
        self.retry_after = retry_after
        super().__init__(429, **kwargs)


@dataclass(frozen=True)
class ValidationItem:
    """Single field-level validation error returned by the API."""

    message: str
    members: list[str] = field(default_factory=list)


class WataValidationError(WataAPIError):
    """HTTP 400 — request validation failure.

    Attributes:
        validation_errors: Per-field validation details.
    """

    def __init__(
        self,
        message: str = "",
        *,
        code: str | None = None,
        details: str | None = None,
        data: dict[str, Any] | None = None,
        validation_errors: list[ValidationItem] | None = None,
        response_body: Any = None,
    ) -> None:
        self.validation_errors = validation_errors or []
        super().__init__(
            400,
            message,
            code=code,
            details=details,
            data=data,
            response_body=response_body,
        )

    def __str__(self) -> str:
        parts = [f"[HTTP 400]"]
        base_msg = self.args[0] if self.args else ""
        if base_msg:
            parts.append(base_msg)
        if self.details:
            parts.append(self.details)
        if self.code:
            parts.append(f"(code: {self.code})")
        if self.validation_errors:
            field_msgs = [
                "{}: {}".format(", ".join(ve.members) if ve.members else "?", ve.message)
                for ve in self.validation_errors
            ]
            parts.append("| " + "; ".join(field_msgs))
        return " ".join(parts)


class WataServerError(WataAPIError):
    """HTTP 5xx — internal server error on the WATA side."""
