"""BlueSky-specific exception handling and error code mapping."""

from typing import Any

from marqetive.core.exceptions import (
    MediaUploadError,
    PlatformAuthError,
    PlatformError,
    PostNotFoundError,
    RateLimitError,
    ValidationError,
)


class BlueSkyErrorCode:
    """Known AT Protocol/BlueSky error codes."""

    INVALID_TOKEN = "InvalidToken"
    EXPIRED_TOKEN = "ExpiredToken"
    AUTH_MISSING = "AuthMissing"
    RATE_LIMIT_EXCEEDED = "RateLimitExceeded"
    RECORD_NOT_FOUND = "RecordNotFound"
    INVALID_REQUEST = "InvalidRequest"


ERROR_MESSAGES: dict[str, str] = {
    BlueSkyErrorCode.INVALID_TOKEN: "Invalid access token. Please re-authenticate.",
    BlueSkyErrorCode.EXPIRED_TOKEN: "Access token has expired. Please refresh the token.",
    BlueSkyErrorCode.AUTH_MISSING: "Authentication is missing or invalid.",
    BlueSkyErrorCode.RATE_LIMIT_EXCEEDED: "Rate limit exceeded. Please retry later.",
    BlueSkyErrorCode.RECORD_NOT_FOUND: "The requested post could not be found.",
    BlueSkyErrorCode.INVALID_REQUEST: "Invalid request payload.",
}


def map_bluesky_error(
    status_code: int | None,
    error_code: str | None = None,
    error_message: str | None = None,
    response_data: dict[str, Any] | None = None,
) -> PlatformError:
    """Map BlueSky API error payloads to typed platform exceptions."""
    if response_data:
        if not error_code:
            error_code = response_data.get("error")
        if not error_message:
            error_message = response_data.get("message")

    friendly_message = ERROR_MESSAGES.get(
        error_code or "", error_message or "An unknown BlueSky API error occurred"
    )

    if error_code in {
        BlueSkyErrorCode.INVALID_TOKEN,
        BlueSkyErrorCode.EXPIRED_TOKEN,
        BlueSkyErrorCode.AUTH_MISSING,
    } or status_code in (401, 403):
        return PlatformAuthError(
            friendly_message,
            platform="bluesky",
            status_code=status_code,
            requires_reconnection=True,
        )

    if error_code == BlueSkyErrorCode.RATE_LIMIT_EXCEEDED or status_code == 429:
        return RateLimitError(
            friendly_message,
            platform="bluesky",
            status_code=status_code or 429,
            retry_after=None,
        )

    if error_code == BlueSkyErrorCode.RECORD_NOT_FOUND or status_code == 404:
        return PostNotFoundError(
            post_id="",
            platform="bluesky",
            status_code=status_code,
            message=friendly_message,
        )

    if error_code == BlueSkyErrorCode.INVALID_REQUEST or status_code == 400:
        return ValidationError(
            friendly_message,
            platform="bluesky",
        )

    if status_code == 413:
        return MediaUploadError(
            friendly_message,
            platform="bluesky",
            status_code=status_code,
        )

    return PlatformError(
        friendly_message,
        platform="bluesky",
        status_code=status_code,
    )
