"""Webhook ORM models for event delivery system."""

from __future__ import annotations

from datetime import datetime
from typing import TYPE_CHECKING
from uuid import UUID as PyUUID
from uuid import uuid4

from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.dialects.postgresql import ARRAY, JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from noteflow.domain.utils.time import utc_now
from noteflow.domain.webhooks.constants import (
    DEFAULT_WEBHOOK_MAX_RETRIES,
    DEFAULT_WEBHOOK_TIMEOUT_MS,
)

from .._base import Base

if TYPE_CHECKING:
    from noteflow.infrastructure.persistence.models.identity.identity import (
        WorkspaceModel,
    )


class WebhookConfigModel(Base):
    """Webhook configuration for event delivery.

    Defines endpoint URL, subscribed events, authentication secrets,
    and delivery settings for a workspace.
    """

    __tablename__ = "webhook_configs"
    __table_args__: dict[str, str] = {"schema": "noteflow"}

    id: Mapped[PyUUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        default=uuid4,
    )
    workspace_id: Mapped[PyUUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("noteflow.workspaces.id", ondelete="CASCADE"),
        nullable=False,
    )
    name: Mapped[str] = mapped_column(String(255), nullable=False, default="Webhook")
    url: Mapped[str] = mapped_column(Text, nullable=False)
    events: Mapped[list[str]] = mapped_column(
        ARRAY(Text),
        nullable=False,
        default=list,
    )
    secret: Mapped[str | None] = mapped_column(Text, nullable=True)
    enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    timeout_ms: Mapped[int] = mapped_column(
        Integer, nullable=False, default=DEFAULT_WEBHOOK_TIMEOUT_MS
    )
    max_retries: Mapped[int] = mapped_column(
        Integer, nullable=False, default=DEFAULT_WEBHOOK_MAX_RETRIES
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        default=utc_now,
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        default=utc_now,
        onupdate=utc_now,
    )

    # Relationships
    workspace: Mapped[WorkspaceModel] = relationship(
        "WorkspaceModel",
        back_populates="webhook_configs",
    )
    deliveries: Mapped[list[WebhookDeliveryModel]] = relationship(
        "WebhookDeliveryModel",
        back_populates="webhook",
        cascade="all, delete-orphan",
    )


class WebhookDeliveryModel(Base):
    """Webhook delivery attempt record.

    Tracks each delivery attempt including status, response,
    and timing information for debugging and retries.
    """

    __tablename__ = "webhook_deliveries"
    __table_args__: dict[str, str] = {"schema": "noteflow"}

    id: Mapped[PyUUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        default=uuid4,
    )
    webhook_id: Mapped[PyUUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("noteflow.webhook_configs.id", ondelete="CASCADE"),
        nullable=False,
    )
    event_type: Mapped[str] = mapped_column(Text, nullable=False)
    payload: Mapped[dict[str, object]] = mapped_column(
        JSONB,
        nullable=False,
        default=dict,
    )
    status_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
    response_body: Mapped[str | None] = mapped_column(Text, nullable=True)
    error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
    attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    duration_ms: Mapped[int | None] = mapped_column(Integer, nullable=True)
    delivered_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        default=utc_now,
    )

    # Relationships
    webhook: Mapped[WebhookConfigModel] = relationship(
        "WebhookConfigModel",
        back_populates="deliveries",
    )
