"""Correspondence domain events.

All events follow the ``correspondence.<entity>.<action>`` naming convention.
"""

from __future__ import annotations

import structlog

from simorgh.apps.events.bus import register_event, subscribe

_log = structlog.get_logger("simorgh.correspondence.events")


# ═══════════════════════════════════════════════════════════════════════════
# Event declarations
# ═══════════════════════════════════════════════════════════════════════════

LETTER_CREATED = register_event(
    "correspondence.letter.created",
    description="A new letter was created.",
    payload_keys=("letter_id", "tenant_id", "org_node_id", "letter_type", "actor_id"),
)

LETTER_UPDATED = register_event(
    "correspondence.letter.updated",
    description="A letter's fields were changed.",
    payload_keys=("letter_id", "tenant_id", "changed_fields", "actor_id"),
)

LETTER_REGISTERED = register_event(
    "correspondence.letter.registered",
    description="A letter was registered with its registration number.",
    payload_keys=("letter_id", "tenant_id", "registration_number", "actor_id"),
)

LETTER_SENT = register_event(
    "correspondence.letter.sent",
    description="A letter was sent to recipients.",
    payload_keys=("letter_id", "tenant_id", "sent_date", "actor_id"),
)

LETTER_RECEIVED = register_event(
    "correspondence.letter.received",
    description="An incoming letter was received and registered.",
    payload_keys=("letter_id", "tenant_id", "received_date", "actor_id"),
)

LETTER_ARCHIVED = register_event(
    "correspondence.letter.archived",
    description="A letter was archived.",
    payload_keys=("letter_id", "tenant_id", "actor_id"),
)

LETTER_CANCELLED = register_event(
    "correspondence.letter.cancelled",
    description="A letter was cancelled.",
    payload_keys=("letter_id", "tenant_id", "reason", "actor_id"),
)

LETTER_STATUS_CHANGED = register_event(
    "correspondence.letter.status_changed",
    description="A letter's status was changed.",
    payload_keys=("letter_id", "tenant_id", "from_status", "to_status", "actor_id"),
)

REPLY_ADDED = register_event(
    "correspondence.reply.added",
    description="A reply letter was linked to a parent letter.",
    payload_keys=("letter_id", "parent_id", "tenant_id", "actor_id"),
)


# ═══════════════════════════════════════════════════════════════════════════
# Notification subscribers
# ═══════════════════════════════════════════════════════════════════════════


@subscribe("correspondence.letter.created")
def _notify_letter_created(payload: dict) -> None:
    """Notify relevant users about a newly created letter."""
    try:
        from simorgh.apps.app_settings.services import resolve as resolve_setting
        from simorgh.apps.notifications import services as notif_svc

        tenant_id = payload["tenant_id"]
        if not resolve_setting("correspondence.enable_notifications", tenant_id=tenant_id):
            return

        notif_svc.dispatch(
            "correspondence.letter.created",
            recipients=[payload["actor_id"]] if payload.get("actor_id") else [],
            context={
                "letter_id": payload["letter_id"],
                "letter_type": payload.get("letter_type", ""),
            },
            tenant_id=tenant_id,
            channels=("inbox",),
        )
    except Exception:
        _log.exception("correspondence.notify_letter_created.error", payload=payload)


@subscribe("correspondence.letter.sent")
def _notify_letter_sent(payload: dict) -> None:
    """Notify recipients when a letter is sent."""
    try:
        from simorgh.apps.app_settings.services import resolve as resolve_setting
        from simorgh.apps.correspondence.models import Letter, LetterRecipient
        from simorgh.apps.notifications import services as notif_svc

        tenant_id = payload["tenant_id"]
        if not resolve_setting("correspondence.enable_notifications", tenant_id=tenant_id):
            return

        letter = Letter.objects.get(pk=payload["letter_id"])
        recipient_ids = list(
            LetterRecipient.objects.filter(
                letter_id=payload["letter_id"], recipient__isnull=False
            ).values_list("recipient_id", flat=True)
        )

        if recipient_ids:
            notif_svc.dispatch(
                "correspondence.letter.sent",
                recipients=recipient_ids,
                context={
                    "letter_id": str(letter.public_id),
                    "subject": letter.subject,
                    "registration_number": letter.registration_number,
                },
                tenant_id=tenant_id,
                organization_node_id=letter.organization_node_id,
                channels=("inbox",),
            )
    except Exception:
        _log.exception("correspondence.notify_letter_sent.error", payload=payload)
