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


class InboxConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.user = self.scope["user"]
        if not self.user or not self.user.is_authenticated:
            await self.close()
            return
        self.conv_id = self.scope["url_route"]["kwargs"]["conv_id"]
        self.group = f"inbox_{self.conv_id}"

        # Verify user is participant
        is_member = await self.is_participant()
        if not is_member:
            await self.close()
            return

        await self.channel_layer.group_add(self.group, self.channel_name)
        await self.accept()

    async def disconnect(self, code):
        if hasattr(self, "group"):
            # Send stopped typing on disconnect
            await self.channel_layer.group_send(self.group, {
                "type": "typing.update",
                "user_id": self.user.id,
                "username": self.user.username,
                "is_typing": False,
            })
            await self.channel_layer.group_discard(self.group, self.channel_name)

    async def receive(self, text_data):
        data = json.loads(text_data)
        msg_type = data.get("type")

        if msg_type == "typing":
            await self.channel_layer.group_send(self.group, {
                "type": "typing.update",
                "user_id": self.user.id,
                "username": self.user.username,
                "is_typing": data.get("is_typing", False),
            })
        elif msg_type == "location":
            await self.channel_layer.group_send(self.group, {
                "type": "location.share",
                "user_id": self.user.id,
                "username": self.user.username,
                "lat": data.get("lat"),
                "lng": data.get("lng"),
                "label": data.get("label", "My Location"),
            })

    async def typing_update(self, event):
        if event["user_id"] == self.user.id:
            return  # Don't send back to self
        await self.send(text_data=json.dumps({
            "type": "typing",
            "username": event["username"],
            "is_typing": event["is_typing"],
        }))

    async def location_share(self, event):
        await self.send(text_data=json.dumps({
            "type": "location",
            "username": event["username"],
            "user_id": event["user_id"],
            "lat": event["lat"],
            "lng": event["lng"],
            "label": event["label"],
        }))

    @database_sync_to_async
    def is_participant(self):
        from .models import Conversation
        return Conversation.objects.filter(
            id=self.conv_id, participants=self.user
        ).exists()
