from datetime import datetime
from enum import Enum
from typing import Optional, TypedDict, List, Literal

from pydantic import BaseModel, Field

from .base import NotchPayPaginatedResponse
from .base import NotchPayResponse

__all__ = [
    "NotchPayWebhook",
    "NotchPayWebhookCreate",
    "NotchPayWebhookUpdate",
    "NotchPayWebhookResponse",
    "WebhookEventType",
    "NotchPayWebhooksListResponse",
]


class WebhookEventType(str, Enum):
    """Available webhook event types."""

    PAYMENT_CREATED = "payment.created"
    PAYMENT_PROCESSING = "payment.processing"
    PAYMENT_COMPLETE = "payment.complete"
    PAYMENT_FAILED = "payment.failed"
    PAYMENT_CANCELED = "payment.canceled"
    PAYMENT_EXPIRED = "payment.expired"

    TRANSFER_CREATED = "transfer.created"
    TRANSFER_PROCESSING = "transfer.processing"
    TRANSFER_COMPLETE = "transfer.complete"
    TRANSFER_FAILED = "transfer.failed"

    CUSTOMER_CREATED = "customer.created"
    CUSTOMER_UPDATED = "customer.updated"

    BENEFICIARY_CREATED = "beneficiary.created"
    BENEFICIARY_UPDATED = "beneficiary.updated"
    BENEFICIARY_DELETED = "beneficiary.deleted"

    @classmethod
    def all(cls) -> List[str]:
        """Return all available event types."""
        return [
            cls.PAYMENT_CREATED,
            cls.PAYMENT_PROCESSING,
            cls.PAYMENT_COMPLETE,
            cls.PAYMENT_FAILED,
            cls.PAYMENT_CANCELED,
            cls.PAYMENT_EXPIRED,
            cls.TRANSFER_CREATED,
            cls.TRANSFER_PROCESSING,
            cls.TRANSFER_COMPLETE,
            cls.TRANSFER_FAILED,
            cls.CUSTOMER_CREATED,
            cls.CUSTOMER_UPDATED,
            cls.BENEFICIARY_CREATED,
            cls.BENEFICIARY_UPDATED,
            cls.BENEFICIARY_DELETED,
        ]

    @classmethod
    def payment_events(cls) -> List[str]:
        """Return all payment-related events."""
        return [
            cls.PAYMENT_CREATED,
            cls.PAYMENT_PROCESSING,
            cls.PAYMENT_COMPLETE,
            cls.PAYMENT_FAILED,
            cls.PAYMENT_CANCELED,
            cls.PAYMENT_EXPIRED,
        ]

    @classmethod
    def transfer_events(cls) -> List[str]:
        """Return all transfer-related events."""
        return [
            cls.TRANSFER_CREATED,
            cls.TRANSFER_PROCESSING,
            cls.TRANSFER_COMPLETE,
            cls.TRANSFER_FAILED,
        ]

    @classmethod
    def customer_events(cls) -> List[str]:
        """Return all customer-related events."""
        return [
            cls.CUSTOMER_CREATED,
            cls.CUSTOMER_UPDATED,
        ]

    @classmethod
    def beneficiary_events(cls) -> List[str]:
        """Return all beneficiary-related events."""
        return [
            cls.BENEFICIARY_CREATED,
            cls.BENEFICIARY_UPDATED,
            cls.BENEFICIARY_DELETED,
        ]


class NotchPayWebhook(BaseModel):
    """Model representing a NotchPay webhook endpoint.

    Attributes:
        id: Unique webhook identifier.
        url: URL where events will be sent.
        description: Webhook description.
        events: List of event types to subscribe to.
        status: Webhook status (active, inactive).
        sandbox: Sandbox environment indicator.
        created_at: Webhook creation date.
        updated_at: Last update date.
    """

    id: str = Field(..., description="Unique webhook identifier")
    url: Optional[str] = Field(None, description="Webhook URL")
    description: Optional[str] = Field(None, description="Webhook description")
    events: List[WebhookEventType] = Field(..., description="Event types")
    status: Optional[Literal["active", "inactive"]] = Field(None, description="Webhook status")
    sandbox: Optional[bool] = Field(None, description="Environment indicator")
    created_at: datetime = Field(..., description="Creation date")
    updated_at: datetime = Field(..., description="Update date")


class NotchPayWebhookCreate(TypedDict, total=False):
    """Model for creating a webhook.

    Attributes:
        url: URL where events will be sent (required).
        events: List of event types (required).
        description: Webhook description.
        active: Indicator if webhook is active.
    """

    url: str
    """URL where webhook events will be sent"""
    events: List[WebhookEventType]
    """List of event types to subscribe to"""
    description: Optional[str]
    """Optional webhook description"""
    active: Optional[bool]
    """Indicator if webhook should be active or inactive"""


class NotchPayWebhookUpdate(NotchPayWebhookCreate, total=False):
    """Model for updating a webhook."""
    pass


class NotchPayWebhookResponse(NotchPayResponse):
    """Webhook detail response."""

    endpoint: NotchPayWebhook = Field(..., description="Webhook details")


class NotchPayWebhooksListResponse(NotchPayPaginatedResponse):
    """Webhook list response."""
    endpoints: List[NotchPayWebhook] = Field(..., description="List of webhooks")
