from __future__ import annotations

"""Structured exceptions for the Autotouch CLI.

All business-logic errors raise one of these instead of calling sys.exit().
The top-level main() handler catches them and maps to exit codes.

Exit code mapping:
    1 — AutotouchAPIError      (runtime / HTTP failure)
    2 — AutotouchInputError    (bad input / validation)
    3 — AutotouchCreditError   (credit guard blocked)
    4 — AutotouchNotFoundError (resource not found)
    4 — AutotouchTimeoutError  (poll timeout)
"""

__all__ = [
    "AutotouchError",
    "AutotouchAPIError",
    "AutotouchInputError",
    "AutotouchCreditError",
    "AutotouchNotFoundError",
    "AutotouchTimeoutError",
]


class AutotouchError(Exception):
    """Base class for all Autotouch CLI errors.

    Subclasses set ``exit_code`` so the top-level handler can translate
    a caught exception into the correct process exit code.
    """

    exit_code: int = 1

    def __init__(self, message: str = "", *, exit_code: int | None = None):
        super().__init__(message)
        if exit_code is not None:
            self.exit_code = exit_code


class AutotouchAPIError(AutotouchError):
    """HTTP or runtime API failure (exit 1)."""

    exit_code = 1

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


class AutotouchInputError(AutotouchError):
    """Bad input, missing arguments, or validation failure (exit 2)."""

    exit_code = 2


class AutotouchCreditError(AutotouchError):
    """Credit guard blocked the operation (exit 3)."""

    exit_code = 3


class AutotouchNotFoundError(AutotouchError):
    """Requested resource was not found (exit 4)."""

    exit_code = 4


class AutotouchTimeoutError(AutotouchError):
    """Poll or wait timed out (exit 4)."""

    exit_code = 4
