"""Portal dashboard consumers - live events pushed to Operator/Admin UIs."""
import json

from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer


@database_sync_to_async
def _operator_id_of(user):
    from testing_app.models import Operator
    op = Operator.objects.filter(user=user).first()
    return op.id if op else None


class OperatorDashboardConsumer(AsyncWebsocketConsumer):
    """Group `operator_<id>`: new bookings, cancellations on their trips."""

    async def connect(self):
        user, role = self.scope.get('jwt_user'), self.scope.get('jwt_role')
        if user is None or role != 'OPERATOR':
            await self.close(code=4401)
            return
        op_id = await _operator_id_of(user)
        if op_id is None:
            await self.close(code=4403)
            return
        self.group = f'operator_{op_id}'
        await self.channel_layer.group_add(self.group, self.channel_name)
        await self.accept()

    async def disconnect(self, code):
        if hasattr(self, 'group'):
            await self.channel_layer.group_discard(self.group, self.channel_name)

    async def portal_event(self, event):
        await self.send(text_data=json.dumps(event['payload']))


class AdminDashboardConsumer(AsyncWebsocketConsumer):
    """Group `admin_portal`: platform-wide events (bookings, approvals due)."""

    async def connect(self):
        if self.scope.get('jwt_user') is None or self.scope.get('jwt_role') != 'ADMIN':
            await self.close(code=4401)
            return
        self.group = 'admin_portal'
        await self.channel_layer.group_add(self.group, self.channel_name)
        await self.accept()

    async def disconnect(self, code):
        if hasattr(self, 'group'):
            await self.channel_layer.group_discard(self.group, self.channel_name)

    async def portal_event(self, event):
        await self.send(text_data=json.dumps(event['payload']))
