# app/modules/checkout/exceptions.py
"""
Checkout module exceptions.

Module-specific exceptions for the checkout process.
"""

from app.exceptions.base import (
    BusinessLogicException,
    ResourceNotFoundException,
    ValidationException,
)


class CheckoutValidationException(ValidationException):  # noqa: MOD025
    """Raised when checkout data validation fails."""

    def __init__(
        self,
        message: str = "Checkout validation failed",
        field: str | None = None,
        details: dict | None = None,
    ):
        super().__init__(
            message=message,
            field=field,
            details=details,
        )
        self.error_code = "CHECKOUT_VALIDATION_FAILED"


class CheckoutSessionNotFoundException(ResourceNotFoundException):  # noqa: MOD025
    """Raised when checkout session is not found."""

    def __init__(self, session_id: str):
        super().__init__(
            resource_type="CheckoutSession",
            identifier=session_id,
            message=f"Checkout session '{session_id}' not found",
            error_code="CHECKOUT_SESSION_NOT_FOUND",
        )


class CheckoutSessionExpiredException(BusinessLogicException):  # noqa: MOD025
    """Raised when checkout session has expired."""

    def __init__(self, session_id: str):
        super().__init__(
            message="Checkout session has expired",
            error_code="CHECKOUT_SESSION_EXPIRED",
            details={"session_id": session_id},
        )


class EmptyCheckoutException(ValidationException):  # noqa: MOD025
    """Raised when trying to checkout with empty cart."""

    def __init__(self):
        super().__init__(
            message="Cannot checkout with an empty cart",
            details={},
        )
        self.error_code = "EMPTY_CHECKOUT"


class PaymentRequiredException(BusinessLogicException):  # noqa: MOD025
    """Raised when payment is required but not provided."""

    def __init__(self, order_total: float):
        super().__init__(
            message="Payment is required to complete this order",
            error_code="PAYMENT_REQUIRED",
            details={"order_total": order_total},
        )


class PaymentFailedException(BusinessLogicException):  # noqa: MOD025
    """Raised when payment processing fails."""

    def __init__(self, reason: str, details: dict | None = None):
        super().__init__(
            message=f"Payment failed: {reason}",
            error_code="PAYMENT_FAILED",
            details={"reason": reason, **(details or {})},
        )


class InvalidShippingAddressException(ValidationException):  # noqa: MOD025
    """Raised when shipping address is invalid or missing."""

    def __init__(self, message: str = "Invalid shipping address", details: dict | None = None):
        super().__init__(
            message=message,
            field="shipping_address",
            details=details,
        )
        self.error_code = "INVALID_SHIPPING_ADDRESS"


class ShippingMethodNotAvailableException(BusinessLogicException):  # noqa: MOD025
    """Raised when selected shipping method is not available."""

    def __init__(self, shipping_method: str, reason: str | None = None):
        message = f"Shipping method '{shipping_method}' is not available"
        if reason:
            message += f": {reason}"
        super().__init__(
            message=message,
            error_code="SHIPPING_METHOD_NOT_AVAILABLE",
            details={"shipping_method": shipping_method, "reason": reason},
        )


class CheckoutInventoryException(BusinessLogicException):  # noqa: MOD025
    """Raised when inventory check fails during checkout."""

    def __init__(self, product_id: int, available: int, requested: int):
        super().__init__(
            message=f"Insufficient inventory for product {product_id}",
            error_code="CHECKOUT_INVENTORY_ERROR",
            details={
                "product_id": product_id,
                "available_quantity": available,
                "requested_quantity": requested,
            },
        )


__all__ = [
    "CheckoutInventoryException",
    "CheckoutSessionExpiredException",
    "CheckoutSessionNotFoundException",
    "CheckoutValidationException",
    "EmptyCheckoutException",
    "InvalidShippingAddressException",
    "PaymentFailedException",
    "PaymentRequiredException",
    "ShippingMethodNotAvailableException",
]
