"""DMS DmsNotificationConsumer — per-user DMS notification stream.

WebSocket path: ``ws/dms/notifications/``

Channel group: ``dms_user_{user.pk}``

This consumer subscribes each authenticated user to their personal DMS
notification room.  The server pushes structured notification events over
this channel; the client never sends messages.

Events sent to the client
--------------------------
``notification.dms``
    A DMS notification dispatched to this user.
    Payload: ``{notification_id, event_type, title, body, doc_id}``

Unauthenticated connections are rejected with close code 4003.
"""

from __future__ import annotations

import structlog
from channels.generic.websocket import AsyncJsonWebsocketConsumer

from simorgh.apps.dms.realtime import user_notifications_room

_log = structlog.get_logger("dms.consumers.notifications")


class DmsNotificationConsumer(AsyncJsonWebsocketConsumer):
    """Streams per-user DMS notifications over WebSocket."""

    async def connect(self) -> None:
        user = self.scope.get("user")
        if user is None or not getattr(user, "is_authenticated", False):
            _log.info("dms.ws.notifications.rejected", reason="unauthenticated")
            await self.close(code=4003)
            return

        self.user_pk: int = user.pk
        self.room: str = user_notifications_room(self.user_pk)

        await self.channel_layer.group_add(self.room, self.channel_name)
        await self.accept()
        _log.info("dms.ws.notifications.connected", room=self.room, user_pk=self.user_pk)

    async def disconnect(self, close_code: int) -> None:
        if hasattr(self, "room"):
            await self.channel_layer.group_discard(self.room, self.channel_name)

    async def receive_json(self, content: dict, **kwargs: object) -> None:
        pass

    async def broadcast_message(self, event: dict) -> None:
        """Forward a channel-layer message to the WebSocket client."""
        await self.send_json(
            {
                "event": event["event"],
                "payload": event.get("payload", {}),
            }
        )
