"""Custom exception hierarchy for isard."""

from __future__ import annotations

from typing import Optional


class IsardError(Exception):
    """Base class for all isard errors."""


class NetworkError(IsardError):
    def __init__(self, message: str, cause: Optional[Exception] = None):
        super().__init__(message)
        self.cause = cause


class HttpError(IsardError):
    def __init__(self, status_code: int, message: str):
        super().__init__(f"HTTP {status_code}: {message}")
        self.status_code = status_code


class WafBlockedError(IsardError):
    def __init__(self, status_code: int):
        super().__init__(f"WAF blocked (HTTP {status_code})")
        self.status_code = status_code


class RateLimitError(IsardError):
    def __init__(self, retry_after: Optional[int] = None):
        super().__init__(
            "Rate limited" + (f"; retry after {retry_after}s" if retry_after else "")
        )
        self.retry_after = retry_after


class AzureAuthError(IsardError):
    def __init__(
        self,
        reason: str,
        error_code: Optional[str] = None,
        correlation_id: Optional[str] = None,
    ):
        super().__init__(reason)
        self.error_code = error_code
        self.correlation_id = correlation_id


class AzureFormParsingError(IsardError):
    def __init__(self, reason: str, html_snippet: Optional[str] = None):
        super().__init__(reason)
        self.html_snippet = html_snippet


class AzureRedirectError(IsardError):
    def __init__(self, reason: str, redirect_url: Optional[str] = None):
        super().__init__(reason)
        self.redirect_url = redirect_url


class SamlValidationError(IsardError):
    def __init__(self, reason: str, response_status: Optional[str] = None):
        super().__init__(reason)
        self.response_status = response_status


class SamlAssertionError(IsardError):
    pass


class SamlParseError(IsardError):
    def __init__(self, reason: str, xml_snippet: Optional[str] = None):
        super().__init__(reason)
        self.xml_snippet = xml_snippet


class SessionExpiredError(IsardError):
    pass


class TooManyRedirectsError(IsardError):
    pass


class BookingRequiredError(IsardError):
    """Raised when the server returns HTTP 428 — a booking is needed before
    the desktop can be started."""

    def __init__(self, desktop_id: str = ""):
        msg = "Desktop requires a booking before it can be started"
        if desktop_id:
            msg += f" (desktop id: {desktop_id})"
        super().__init__(msg)
        self.desktop_id = desktop_id
