import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from helpdesk.services.ticket_service import TicketService # ตรวจสอบ Ticket

class ChatConsumer(AsyncWebsocketConsumer):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.ticket_id = None
        self.ticket_group_name = None

    @database_sync_to_async
    def check_ticket_and_auth(self, ticket_id, user):
        """ตรวจสอบสิทธิ์และสถานะของ Ticket ใน DB"""
        if not user.is_authenticated:
            return False

        # Business Logic Authorization:
        # ใช้ TicketService เพื่อตรวจสอบว่าผู้ใช้มีสิทธิ์เข้าถึง Ticket นี้หรือไม่
        if not TicketService().is_user_authorized(ticket_id, user):
             return False

        # สำหรับตัวอย่างนี้ให้แค่ตรวจสอบว่า Ticket มีอยู่จริงหรือไม่
        from helpdesk.models import Ticket
        return Ticket.objects.filter(pk=ticket_id).exists()

    async def connect(self):
        self.ticket_id = self.scope['url_route']['kwargs']['ticket_id']
        self.ticket_group_name = f'ticket_{self.ticket_id}'
        user = self.scope['user']

        # 1. ตรวจสอบสิทธิ์ก่อนเชื่อมต่อ
        is_allowed = await self.check_ticket_and_auth(self.ticket_id, user)

        if is_allowed:
            # Join room group
            await self.channel_layer.group_add(
                self.ticket_group_name,
                self.channel_name
            )
            await self.accept()
        else:
            await self.close()

    async def disconnect(self, close_code):
        if self.ticket_group_name:
            # Leave room group
            await self.channel_layer.group_discard(
                self.ticket_group_name,
                self.channel_name
            )

    # Receive message from WebSocket (ไคลเอนต์ส่งข้อความมา)
    async def receive(self, text_data=None, bytes_data=None):
        # Consumer ไม่ควรมี Business Logic
        # ข้อมูลขาเข้าควรถูกส่งไปให้ Service Layer ประมวลผล
        text_data_json = json.loads(text_data)
        content = text_data_json.get('content')

        # เรียก Service เพื่อสร้างและส่งข้อความ (ต้องทำแบบ sync)
        # เนื่องจาก Consumer เป็น async, เราจะส่งไปให้ Service แบบ sync/async
        await self.save_message_and_broadcast(self.ticket_id, self.scope['user'], content)

    # เมธอดที่ Service Layer เรียกผ่าน Channel Layer (group_send)
    async def chat_message(self, event):
        """ส่งข้อความที่ถูก broadcast กลับไปยัง WebSocket Client"""
        message = event['message']

        # Send message to WebSocket
        await self.send(text_data=json.dumps({
            'type': 'new_message',
            'message': message
        }))

    @database_sync_to_async
    def save_message_and_broadcast(self, ticket_id, user, content):
        """
        เมธอด sync ที่เรียก Service Layer เพื่อทำ Business Logic
        และส่ง broadcast กลับมา (ผ่าน _send_realtime_update ใน Service)
        """
        from chat.services.message_service import chat_svc # ต้องแน่ใจว่า import ถูกต้อง
        if not content:
            return

        # Service จะสร้างข้อความใน DB, อัปเดต Ticket, และส่ง broadcast
        chat_svc.create_and_send_message(
            ticket_id=ticket_id,
            sender=user,
            content=content,
            message_type='T'
        )