"""DMS CommentsConsumer — realtime comment feed for a document.

WebSocket path: ``ws/dms/documents/{public_id}/comments/``

Channel group: ``dms_comments_{public_id}``

Events sent to the client
--------------------------
``comment.created``  — new top-level comment or reply.
    Payload: ``{id, body, author_id, created_at}``

``comment.updated``  — comment body edited.
    Payload: ``{id, body, updated_at}``

``comment.resolved`` — comment thread marked resolved.
    Payload: ``{id, resolved_by_id}``

``comment.deleted``  — comment soft-deleted.
    Payload: ``{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 comments_room

_log = structlog.get_logger("dms.consumers.comments")


class CommentsConsumer(AsyncJsonWebsocketConsumer):
    """Streams realtime comment events for a specific document."""

    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.comments.rejected", reason="unauthenticated")
            await self.close(code=4003)
            return

        self.public_id: str = self.scope["url_route"]["kwargs"]["public_id"]
        self.room: str = comments_room(self.public_id)

        await self.channel_layer.group_add(self.room, self.channel_name)
        await self.accept()
        _log.info("dms.ws.comments.connected", room=self.room, user_pk=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:
        # Read-only; client messages are ignored.
        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", {}),
            }
        )
