"""
Push subscription model for Web Push notifications.

Stores browser push subscriptions for portal users so the gateway can
send push notifications when an AI employee responds and the user's
WebSocket is not connected.

Push subscriptions are per-user, per-browser-endpoint. No RLS is applied
to this table — the API filters by user_id in the query (push subscriptions
are portal-user-scoped, not tenant-scoped).
"""

from __future__ import annotations

import uuid
from datetime import datetime

from pydantic import BaseModel
from sqlalchemy import DateTime, ForeignKey, String, Text, UniqueConstraint, func
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column

from shared.models.tenant import Base


class PushSubscription(Base):
    """
    Browser push subscription for a portal user.

    endpoint:  The push service URL provided by the browser.
    p256dh:    ECDH public key for message encryption.
    auth:      Auth secret for message encryption.

    Unique constraint on (user_id, endpoint) — one subscription per
    browser per user. Upsert on conflict avoids duplicates on re-subscribe.
    """

    __tablename__ = "push_subscriptions"
    __table_args__ = (
        UniqueConstraint("user_id", "endpoint", name="uq_push_user_endpoint"),
    )

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        server_default=func.gen_random_uuid(),
    )
    user_id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("portal_users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )
    tenant_id: Mapped[uuid.UUID | None] = mapped_column(
        UUID(as_uuid=True),
        ForeignKey("tenants.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
        comment="Optional tenant scope for notification routing",
    )
    endpoint: Mapped[str] = mapped_column(
        Text,
        nullable=False,
        comment="Push service URL (browser-provided)",
    )
    p256dh: Mapped[str] = mapped_column(
        Text,
        nullable=False,
        comment="ECDH public key for payload encryption",
    )
    auth: Mapped[str] = mapped_column(
        Text,
        nullable=False,
        comment="Auth secret for payload encryption",
    )
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        nullable=False,
        server_default=func.now(),
        onupdate=func.now(),
    )

    def __repr__(self) -> str:
        return f"<PushSubscription user={self.user_id} endpoint={self.endpoint[:40]!r}>"


# ---------------------------------------------------------------------------
# Pydantic schemas
# ---------------------------------------------------------------------------


class PushSubscriptionCreate(BaseModel):
    """Payload for POST /portal/push/subscribe."""

    endpoint: str
    p256dh: str
    auth: str
    tenant_id: str | None = None


class PushSubscriptionOut(BaseModel):
    """Response body for subscription operations."""

    id: str
    endpoint: str
    created_at: datetime

    model_config = {"from_attributes": True}


class PushSendRequest(BaseModel):
    """Internal payload for POST /portal/push/send."""

    user_id: str
    title: str
    body: str
    conversation_id: str | None = None
