from __future__ import annotations

from collections.abc import Mapping
from dataclasses import dataclass, field
from datetime import datetime
from typing import Protocol, runtime_checkable


CAPABILITY_NOTIFICATIONS_DISPATCH = "notifications.dispatch"


@dataclass(frozen=True, slots=True)
class NotificationDispatchRequest:
    tenant_id: str
    source_module: str
    source_resource_type: str
    source_resource_id: str | None
    event_kind: str
    channel: str = "inbox"
    recipient: str | None = None
    recipient_type: str | None = None
    recipient_id: str | None = None
    recipient_label: str | None = None
    subject: str | None = None
    body_text: str | None = None
    body_html: str | None = None
    action_url: str | None = None
    priority: int = 0
    not_before_at: datetime | None = None
    payload: Mapping[str, object] = field(default_factory=dict)
    metadata: Mapping[str, object] = field(default_factory=dict)


@runtime_checkable
class NotificationDispatchProvider(Protocol):
    def enqueue_notification(
        self,
        session: object,
        request: NotificationDispatchRequest,
        *,
        enqueue_delivery: bool = True,
    ) -> Mapping[str, object]:
        ...

    def deliver_notification(self, session: object, *, notification_id: str) -> Mapping[str, object]:
        ...

    def deliver_pending(
        self,
        session: object,
        *,
        tenant_id: str | None = None,
        limit: int = 50,
    ) -> Mapping[str, object]:
        ...


def notification_dispatch_provider(registry: object | None) -> NotificationDispatchProvider | None:
    if registry is None or not hasattr(registry, "has_capability"):
        return None
    if not registry.has_capability(CAPABILITY_NOTIFICATIONS_DISPATCH):
        return None
    capability = registry.capability(CAPABILITY_NOTIFICATIONS_DISPATCH)
    return capability if isinstance(capability, NotificationDispatchProvider) else None
