"""Typed exception hierarchy for the Skytale SDK.

All exceptions extend ``RuntimeError`` for backward compatibility —
existing ``except RuntimeError`` handlers continue to work.

Each exception carries structured attributes for programmatic handling:

- ``code`` — machine-readable error code (e.g. ``"auth_failed"``)
- ``http_status`` — HTTP status that triggered the error (if applicable)
- ``doc_url`` — link to troubleshooting documentation

Usage::

    from skytale_sdk.errors import ChannelError, AuthError

    try:
        mgr.create("bad-name")
    except ChannelError as e:
        print(f"channel problem: {e}")
        print(f"error code: {e.code}")
        print(f"docs: {e.doc_url}")
    except RuntimeError:
        print("still works as a catch-all")
"""


class SkytaleError(RuntimeError):
    """Base exception for all Skytale SDK errors."""

    def __init__(self, message, *, code="unknown_error", http_status=None, doc_url=None):
        super().__init__(message)
        self.code = code
        self.http_status = http_status
        self.doc_url = doc_url or f"https://skytale.sh/docs/sdk/errors#{code}"


class AuthError(SkytaleError):
    """Invalid or expired API key / JWT."""

    def __init__(self, message, *, code="auth_failed", http_status=None, doc_url=None):
        super().__init__(message, code=code, http_status=http_status, doc_url=doc_url)


class TransportError(SkytaleError):
    """Relay connection failure or transport-level error."""

    def __init__(self, message, *, code="transport_error", http_status=None, doc_url=None):
        super().__init__(message, code=code, http_status=http_status, doc_url=doc_url)


class ChannelError(SkytaleError):
    """Invalid channel name, MLS group error, or message size limit."""

    def __init__(self, message, *, code="channel_error", http_status=None, doc_url=None):
        super().__init__(message, code=code, http_status=http_status, doc_url=doc_url)


class QuotaExceededError(SkytaleError):
    """Monthly message quota exceeded."""

    def __init__(self, message, *, code="quota_exceeded", http_status=None, doc_url=None):
        super().__init__(message, code=code, http_status=http_status, doc_url=doc_url)


class MlsError(SkytaleError):
    """MLS encryption or decryption failure."""

    def __init__(self, message, *, code="mls_error", http_status=None, doc_url=None):
        super().__init__(message, code=code, http_status=http_status, doc_url=doc_url)
