from channels.generic.websocket import WebsocketConsumer 
from .models import * 
import json
from django.template.loader import render_to_string
from asgiref.sync import async_to_sync
from django.shortcuts import  get_object_or_404
import requests
from django.forms.models import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Case, When, F, Max, DateTimeField
from django.db import transaction



class OsitcomVisitor(WebsocketConsumer):
    def connect(self):
        async_to_sync(self.channel_layer.group_add)(
            'ositcom_visitors', self.channel_name
        )
        self.accept()
        self.visitor = None

    def disconnect(self, close_code):
        if self.visitor:
            self.current_log.left_date = datetime.now()
            self.current_log.save()
        async_to_sync(self.channel_layer.group_discard)(
            'ositcom_visitors', self.channel_name
        )
    def receive(self, text_data): 
        text_data_json = json.loads(text_data)
        event_type = text_data_json.get('event_type')
        if event_type == 'visitor_ping': 
            session_id = text_data_json.get('session_id')
            if Visitor.objects.filter(session_id=session_id).last():
                self.visitor = Visitor.objects.filter(session_id=session_id).last()
            else:
                self.visitor = Visitor.objects.create(
                    session_id = session_id,
                    ip_address = text_data_json.get('client_ip'),
                    country = text_data_json.get('client_country'),
                    region =  text_data_json.get('client_region'),
                    browser_name = text_data_json.get('browser_name'),
                    os_name = text_data_json.get('os_name'),
                )
                
            self.current_log = VisitorLog.objects.create(
                visitor = self.visitor,
                referrer = text_data_json.get('referrer'),
                title = text_data_json.get('title'),
                url = text_data_json.get('url'),
                visit_date = datetime.now()
            )







class Osichat(WebsocketConsumer):
    def connect(self):
        async_to_sync(self.channel_layer.group_add)(
            'osichat', self.channel_name
        )
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            'osichat', self.channel_name
        )

    def receive(self, text_data):
        data = json.loads(text_data)
        event_type = data.get('event_type')
        
        if event_type == 'set_client_type':
            self.client_type = data.get('client_type')
            self.user_id =  data.get('user_id')
            event = {
                'type': 'get_chats_handler',
            }
            if data.get('whereAmI') == 'Chats':
                self.get_chats_handler(event)
            else:
                self.get_visitors_handler(event)

        if event_type == 'get_chats':
            event = {
                'type': 'get_chats_handler',
            }
            self.get_chats_handler(event)


        if event_type == 'get_dms':
            event = {
                'type': 'get_dms_handler',
            }
            self.get_chats_handler(event)


        if event_type == 'get_visitors':
            event = {
                'type': 'get_visitors_handler',
            }
            self.get_visitors_handler(event)

    
    def get_chats_handler(self, event):
        chat_rooms = ChatRoom.objects.annotate(last_update=Max('chatmessage__date_sent'),
            order_key=Case(
                When(last_update__isnull=True, then=F('date_created')),
                default=F('last_update'),
                output_field=DateTimeField(),)).filter(chatroomguest__isnull=False).order_by('-order_key')

        user = get_object_or_404(User, id=self.user_id)

        for room in chat_rooms:
            room.number_of_unread = room.unread_messages(user)
        context = {
            'chat_rooms': chat_rooms,
        }

        if self.client_type == 'mobile_admin':
            chat_rooms_data = []
            for chat_room in chat_rooms:
                last_message = ChatMessage.objects.filter(room=chat_room).last()
                room_data = model_to_dict(chat_room)
                room_data['number_of_unread'] = chat_room.unread_messages(user)
                if last_message:
                    room_data['last_message'] = model_to_dict(last_message)
                else:
                    room_data['last_message'] = None 
                if hasattr(chat_room, 'chatroomguest') and chat_room.chatroomguest.visitor:
                    visitor = chat_room.chatroomguest.visitor
                    room_data['visitor'] = {
                        'id': visitor.id,
                        'session_id': visitor.session_id,  
                        'ip': visitor.ip_address,
                        'country': visitor.country,
                        'region' : visitor.region,
                        'country_flag': visitor.flag_image_url,
                        'name': visitor.name,
                        'mobile_number': visitor.mobile_number,  
                    }
                chat_rooms_data.append(room_data)
    
            self.send(text_data=json.dumps({
                'event_type': 'get_chats',
                'chat_rooms_data': chat_rooms_data,
            }, cls=DjangoJSONEncoder))
        else:
            html = render_to_string("chat_templates/partials/rooms.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'get_chats',
                'html': html,
        }))


    def new_chat_update_handler(self, event):
        chat_room = get_object_or_404(ChatRoom, id=event['chatroom_id'])
        user = get_object_or_404(User, id=self.user_id)
        number_of_unread = ChatMessage.objects.filter(room=chat_room).exclude(member=user).exclude(chatmessageseen__member=user).count()
        last_message = ChatMessage.objects.filter(room=chat_room).last()

        context = {
            'chat_room': chat_room,
            'number_of_unread': number_of_unread
        }
        if self.client_type == 'mobile_admin':
            chat_room_data = model_to_dict(chat_room)
            if hasattr(chat_room, 'chatroomguest') and chat_room.chatroomguest.visitor:
                chat_room_data['visitor'] = model_to_dict(chat_room.chatroomguest.visitor)
            if last_message:
                chat_room_data['last_message'] = model_to_dict(last_message)
            else:
                chat_room_data['last_message'] = None 
            self.send(text_data=json.dumps({
                'event_type': 'new_chat_update',
                'chat_room_data': chat_room_data,
            }, cls=DjangoJSONEncoder))
        else:
            html = render_to_string("chat_templates/partials/new-chat-room.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'new_chat_update',
                'chatroom_id': chat_room.id,
                'user': last_message.member.id if last_message and last_message.member else None,
                'html': html,
            }))


    def get_dms_handler(self, event):
        chat_rooms = ChatRoom.objects.annotate(last_update=Max('chatmessage__date_sent'),order_key=Case(
                When(last_update__isnull=True, then=F('date_created')),
                default=F('last_update'),
                output_field=DateTimeField(),)).filter(chatroomguest__isnull=True, chatmember__member=self.scope["user"]).order_by('-order_key')
        context = {
            'chat_rooms': chat_rooms,
        }
        if self.client_type == 'mobile_admin':
            chat_rooms_data = []
            for chat_room in chat_rooms:
                chat_room_data = {
                    'id': chat_room.id,
                    'name': chat_room.name,
                    'last_update': chat_room.last_updated,
                    'date_created': chat_room.date_created,
                    'unread_messages': chat_room.unread_messages(user),
                    'last_message': model_to_dict(ChatMessage.objects.filter(room=chat_room).last())
                }
                members = chat_room.chatmember_set.all()
                member_data = []
                for member in members:
                    member_data.append({
                        'id': member.member.id,
                        'first_name': member.member.first_name,
                        'last_name': member.member.last_name,
                        'image': member.member.staffprofile.image.url if hasattr(member.member, 'staffprofile') and member.member.staffprofile.image else None,
                    })
                
                chat_room_data['members'] = member_data
                
                chat_rooms_data.append(chat_room_data)
    
            self.send(text_data=json.dumps({
                'event_type': 'get_dms',
                'chat_rooms_data': chat_rooms_data,
            }, cls=DjangoJSONEncoder))


    def get_visitors_handler(self, event):
        today = timezone.now().date()
        visitors = Visitor.objects.filter(visitorlog__visit_date__date=today).annotate(latest_visit=Max('visitorlog__visit_date')).order_by('-latest_visit')
        context = {
            'visitors': visitors,
        }
        if self.client_type == 'mobile_admin':
            visitors_data = []
            for visitor in visitors:
                visitor_data = model_to_dict(visitor)
                visitor_data['is_online'] = visitor.is_online
                visitor_data['duration'] = visitor.total_duration
                visitor_data['flag'] = visitor.flag_image_url


                visitor_logs = VisitorLog.objects.filter(visitor=visitor)
                visitor_logs_data = []
                for log in visitor_logs:
                    log_data = model_to_dict(log)
                    log_data['log_duration'] = log.log_duration  
                    visitor_logs_data.append(log_data)

                visitor_data['visitor_logs'] = visitor_logs_data    
                visitors_data.append(visitor_data)

            self.send(text_data=json.dumps({
                'event_type': 'get_visitors',
                'visitors_data': visitors_data,
            }, cls=DjangoJSONEncoder))

        else:
            html = render_to_string("chat_templates/partials/visitors.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'get_visitors',
                'html': html,
        }))    

    
    def new_visitor_update_handler(self, event):
        visitor = get_object_or_404(Visitor, id=event['visitor_id'])
        latest_log = VisitorLog.objects.filter(visitor=visitor).last()
        context = {
            'visitor': visitor,
        }
        if self.client_type == 'mobile_admin':
            visitor_data = model_to_dict(visitor)
            visitor_data['is_online'] = visitor.is_online
            visitor_data['duration'] = visitor.total_duration
            visitor_data['flag'] = visitor.flag_image_url
            if latest_log:
                latest_log_data = model_to_dict(latest_log)
                latest_log_data['log_duration'] = latest_log.log_duration
                visitor_data['latest_log'] = latest_log_data


            
            self.send(text_data=json.dumps({
                'event_type': 'new_visitor_update',
                'visitor_data': visitor_data,
                'action': event['action'],
            }, cls=DjangoJSONEncoder))
        else:
            html = render_to_string("chat_templates/partials/new-visitor.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'new_visitor_update',
                'visitor_id': visitor.id,
                'action': event['action'],
                'html': html,
            }))        





class OsichatVisitor(WebsocketConsumer):
    def connect(self):
        self.visitor_id = self.scope['url_route']['kwargs']['visitor_id']
        self.group_name = 'V' + str(self.visitor_id)
        self.visitor = get_object_or_404(Visitor, id=self.visitor_id)
        async_to_sync(self.channel_layer.group_add)(
            self.group_name, self.channel_name
        )
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.group_name, self.channel_name
        )

    def receive(self, text_data):
        data = json.loads(text_data)
        event_type = data.get('event_type')

        if event_type == 'set_client_type':
            self.client_type = data.get('client_type')
            event = {
                'type': 'get_visitor_handler',
            }

            async_to_sync(self.channel_layer.group_send)(
            self.group_name, event
            )

    def get_visitor_handler(self, event):
        if self.client_type == 'mobile_admin':
            visitor_data = model_to_dict(self.visitor)
            visitor_data['online'] = self.visitor.is_online
            visitor_data['flag'] = self.visitor.flag_image_url
            visitor_logs = VisitorLog.objects.filter(visitor=self.visitor)
            visitor_logs_data = []
            for log in visitor_logs:
                log_data = model_to_dict(log)
                log_data['log_duration'] = log.log_duration  
                visitor_logs_data.append(log_data)
                visitor_data['visitor_logs'] = visitor_logs_data    

            self.send(text_data=json.dumps({
                'event_type': 'get_visitor',
                'visitor_data': visitor_data,
            }, cls=DjangoJSONEncoder))

    def new_visitor_update_handler(self, event):
        visitor = self.visitor
        latest_log = VisitorLog.objects.filter(visitor=self.visitor).last()
        if self.client_type == 'mobile_admin':
            visitor_data = model_to_dict(visitor)
            visitor_data['is_online'] = visitor.is_online
            visitor_data['duration'] = visitor.total_duration
            visitor_data['flag'] = visitor.flag_image_url
            if latest_log:
                latest_log_data = model_to_dict(latest_log)
                latest_log_data['log_duration'] = latest_log.log_duration
                visitor_data['latest_log'] = latest_log_data
            self.send(text_data=json.dumps({
                'event_type': 'new_visitor_update',
                'visitor_data': visitor_data,
                'action': event['action'],
            }, cls=DjangoJSONEncoder))






class OsitcomChatRoom(WebsocketConsumer):
    def connect(self):
        self.domain = 'https://osina.ositcom.com'
        self.session_id = self.scope['url_route']['kwargs'].get('session_id')
        if self.session_id:
            self.visitor = Visitor.objects.filter(session_id=self.session_id).last()
        if self.session_id and not self.visitor:
            self.close()  

        if self.scope['url_route']['kwargs'].get('chat_id'): #Case where admin is accessing a specific conversation between the conversations of this visitor
            self.chat_room = get_object_or_404(ChatRoom, id=self.scope['url_route']['kwargs'].get('chat_id'))
        else:
            chat_room_guest = ChatRoomGuest.objects.filter(visitor=self.visitor).last() #Case where the visitor will always acesss his last conversation
            if chat_room_guest:
                self.chat_room = chat_room_guest.room
            else:
                self.chat_room = None

        if self.scope["user"].is_authenticated and self.chat_room: #If a user add him as a chat_member
            self.chat_member = ChatMember.objects.filter(member=self.scope["user"]).last()
            if not self.chat_member:
                self.chat_member = ChatMember.objects.create(
                    room=self.chat_room,
                    member=self.scope["user"],
                    date_joined = datetime.now()
                )

        if self.chat_room:
            self.group = f"chat_{self.chat_room.id}"
        else:
            self.group = self.session_id #Visitor hasn't started a chat yet, when he will we will remove him from this group and add it to the chat group

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


    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.group, self.channel_name
        )



    def receive(self, text_data): 
        text_data_json = json.loads(text_data)
        event_type = text_data_json.get('event_type')

        if  event_type == 'load_chat':
            self.client_type = text_data_json.get('client_type')
            event = {
                'reconnecting' : text_data_json.get('reconnecting')
            }
            self.load_chat_handler(event)
    
        if event_type == 'start_conversation':
            try:
                with transaction.atomic():
                    chat_room = ChatRoom.objects.create(
                        name=f"Support: {self.session_id}",
                        date_created = datetime.now()
                    )
                    if text_data_json.get('guest_name'):
                        self.visitor.name = text_data_json.get('guest_name')
                        self.visitor.save()
                    if  text_data_json.get('guest_mobile_number'):
                        self.visitor.mobile_number = text_data_json.get('guest_mobile_number')
                        self.visitor.save()
                    chat_room_guest = ChatRoomGuest.objects.create(
                        room=chat_room,
                        visitor=self.visitor
                    )
                self.chat_room = chat_room
                async_to_sync(self.channel_layer.group_discard)(
                self.group, self.channel_name
                )
                self.group = f"chat_{self.chat_room.id}"
                async_to_sync(self.channel_layer.group_add)(
                self.group, self.channel_name
                )
                event = {
                    'type': 'start_conversation_handler',
                    'chat_room_id':  chat_room.id
                }
                async_to_sync(self.channel_layer.group_send)(
                self.group, event
                )
            except Exception as e:
                print('Error starting conversation')


        if event_type == 'typing':
            event = {
                'type': 'typing_handler',
                'user_id': text_data_json.get('user_id'),
                'typing_status':  text_data_json.get('typing_status')
            }
            async_to_sync(self.channel_layer.group_send)(
                self.group, event
            )

        if event_type == 'send_message':
            if text_data_json.get('user_id'):
                member = get_object_or_404(User, id=text_data_json.get('user_id'))
            else:
                member = None
            chat_message = ChatMessage.objects.create(
            member = member,
            room = self.chat_room,
            content= text_data_json.get('message'),
            date_sent = datetime.now()
            )
            event = {
                'type': 'send_message_handler',
                'chat_message_id': chat_message.id
            }
            async_to_sync(self.channel_layer.group_send)(
                self.group, event
            )

        if event_type == 'uploaded_file':
            if text_data_json.get('user_id'):
                member = get_object_or_404(User, id=text_data_json.get('user_id'))
            else:
                member = None
            message = ChatMessage.objects.create(
                member = member,
                room = self.chat_room,
                date_sent = datetime.now()
            )
            message_attachment = ChatMessageAttachment.objects.create(
                message = message,
                attachment = text_data_json.get('path'),
            )
            event = {
                'type': 'uploaded_file_handler',
                'message_attachment_id': message_attachment.id,
                'file_type': text_data_json.get('file_type'),
                'file_name': text_data_json.get('file_name'),
            }
            async_to_sync(self.channel_layer.group_send)(
             self.group, event
            )

        if event_type == 'update_read_messages' and self.chat_room:
            latest_unread_message = None
            number_of_unread = 0
            if text_data_json.get('user_id'):
                member = get_object_or_404(User, id=text_data_json.get('user_id'))
                guest = None
                if text_data_json.get('chat_state') == 'open':
                    messages = ChatMessage.objects.filter(room=self.chat_room).exclude(member=member)
                    for message in messages:
                        seen_message = ChatMessageSeen.objects.filter(
                            message=message,
                            member=member
                        ).exists()

                        if not seen_message:
                            ChatMessageSeen.objects.create(
                                message=message,
                                member=member,
                                seen_date = datetime.now()
                            )
                    number_of_unread = 0
                else:
                    number_of_unread = ChatMessage.objects.filter(room=self.chat_room).exclude(member = member).exclude(hatmessageseen__member=member).count()
                    latest_unread_message  = ChatMessage.objects.filter(room=self.chat_room).exclude(chatmessageseen__member=member).last()
            else:
                member = None
                guest = self.chat_room.chatroomguest
                if text_data_json.get('chat_state') == 'open':
                    messages = ChatMessage.objects.filter(room=self.chat_room).exclude(member=None)
                    for message in messages:
                        seen_message = ChatMessageSeen.objects.filter(
                            message=message,
                            guest=guest
                        ).exists()

                        if not seen_message:
                            ChatMessageSeen.objects.create(
                                message=message,
                                guest=guest,
                                seen_date = datetime.now()
                            )

                    number_of_unread = 0
                
                else:
                    number_of_unread = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).count()
                    latest_unread_message = ChatMessage.objects.filter(room=self.chat_room, member__isnull=False).exclude(chatmessageseen__guest=guest).last()

            event = {
                'type': 'update_read_messages_handler',
                'number_of_unread': number_of_unread,
                'latest_unread_message_id': latest_unread_message.id if latest_unread_message else None
            }
            self.update_read_messages_handler(event)

        if event_type == 'end_chat':
            event = {
                'type': 'end_chat_handler',
                'user_id': text_data_json.get('user_id')
            }
            async_to_sync(self.channel_layer.group_send)(
             self.group, event
            )

        if event_type == 'submit_review':
            if ChatRoomReview.objects.filter(room=self.chat_room).last():
                review = ChatRoomReview.objects.filter(room=self.chat_room).last()
                if text_data_json.get('reaction'):
                    review.reaction = text_data_json.get('reaction')
                if text_data_json.get('details'):
                    review.details = text_data_json.get('details')
                review.save()
            else:
                review = ChatRoomReview.objects.create(
                    room = self.chat_room,
                    reaction = text_data_json.get('reaction'),
                    details = text_data_json.get('details'),
                )
            event = {
                'type': 'submit_review_handler',
                'review_id': review.id
            }
            async_to_sync(self.channel_layer.group_send)(
             self.group, event
            )





            
    def load_chat_handler(self, event):
        if self.chat_room:
            chat_room = self.chat_room
            chat_room_messages = ChatMessage.objects.filter(room=chat_room).order_by('date_sent')
            review = ChatRoomReview.objects.filter(room=chat_room).last()
            
        else:
            chat_room = None
            chat_room_messages = None
            review = None

        context = {
            'chat_room': chat_room,
            'chat_room_messages': chat_room_messages,
            'review': review,
            'domain': self.domain
        }

        if self.client_type == 'mobile_admin':
            chat_room_data = model_to_dict(chat_room)
            if hasattr(chat_room, 'chatroomguest') and chat_room.chatroomguest.visitor:
                chat_room_data['visitor'] = {
                    'id': chat_room.chatroomguest.visitor.id,
                    'country_flag': chat_room.chatroomguest.visitor.flag_image_url,
                    'is_online': chat_room.chatroomguest.visitor.is_online,
                    'ip': chat_room.chatroomguest.visitor.ip_address,
                    'name': chat_room.chatroomguest.visitor.name,
                    'mobile_number': chat_room.chatroomguest.visitor.mobile_number,
                }

            chat_members = ChatMember.objects.filter(room=chat_room)
            if chat_members.exists():
                chat_room_data['members'] = [
                    {
                        'id': member.member.id,
                        'first_name': member.member.first_name,
                        'last_name': member.member.last_name,
                        'image': member.member.staffprofile.image.url,
                    }
                    for member in chat_members
                ]
            else:
                chat_room_data['members'] = []  
            


            chat_room_messages_data = []
            for message in chat_room_messages:
                message_data = model_to_dict(message)
                attachment = getattr(message, 'chatmessageattachment', None)
                member = message.member
                if member:
                    message_data['member'] = {
                        'id': member.id,
                        'first_name': member.first_name,  
                        'last_name': member.last_name,
                        'image': member.staffprofile.image.url if member.staffprofile and member.staffprofile.image else None
                    }
                if attachment:
                    message_data['attachment'] = {
                        'attachment': attachment.attachment,
                        'is_image': attachment.is_image(),
                        'file_name': attachment.file_name,
                    }
                else:
                    message_data['attachment'] = None

                chat_room_messages_data.append(message_data)
            
            self.send(text_data=json.dumps({
                'event_type': 'load_chat',
                'chat_room_data': chat_room_data,
                'chat_room_messages_data': chat_room_messages_data,
            }, cls=DjangoJSONEncoder))

        elif self.client_type == 'website_admin':
            html = render_to_string("chat_templates/chat-room.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'load_chat',
                'html': html,
            }))
        else:
            if event.get('reconnecting') == 'False': #Connecting for the first time
              html = render_to_string("chat-widget.html", context=context)
            else:
                if chat_room:
                    if chat_room.date_terminated:
                        html = render_to_string("ended-chat.html", context=context)
                    else:
                        html = render_to_string("chat-room.html", context=context)
                else: 
                    html = render_to_string("start-chat.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'load_chat',
                'html': html,
            }))


    def start_conversation_handler(self, event):
        chat_room = get_object_or_404(ChatRoom, id=event['chat_room_id'])
        context = {
            'chat_room': chat_room,
            'session_id':self.session_id,
            'domain': self.domain
        }
        if self.client_type == 'mobile_admin':
            self.send(text_data=json.dumps({
                'event_type': 'start_conversation',
                'context': context,
            }))
        else:
            html = render_to_string("chat-room.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'start_conversation',
                'html': html,
            }))


    def typing_handler(self, event):
        if event.get('typing_status') == 'typing':
            if event.get('user_id'):
                member = get_object_or_404(User, id=event.get('user_id'))
            else:
                member = None
            
            context = {
                'member': member,
                'chat_room': self.chat_room,
                'domain': self.domain
            }
            if self.client_type == 'mobile_admin':
                member_data = None
                if member:
                    member_data = model_to_dict(member)
                    member_data['image'] = member.staffprofile.image.url if member.staffprofile and member.staffprofile.image else None
                self.send(text_data=json.dumps({
                    'event_type': 'typing',
                    'member_data': member_data,
                }, cls=DjangoJSONEncoder))
            elif self.client_type == 'website_admin':
                html = render_to_string("chat_templates/partials/typing.html", context=context)
                self.send(text_data=json.dumps({
                    'event_type': 'typing',
                    'user': member.id if member else None,
                    'html': html,
                }))
            else:
                html = render_to_string("partials/typing.html", context=context)
                self.send(text_data=json.dumps({
                    'event_type': 'typing',
                    'user': member.id if member else None,
                    'html': html,
                }))
        else:
            self.send(text_data=json.dumps({
                'event_type': 'stopped_typing',
            }))


    def send_message_handler(self, event):
        chat_message = get_object_or_404(ChatMessage, id=event['chat_message_id'])
        context = {
            'chat_message': chat_message,
            'domain': self.domain
        }
        if self.client_type == 'mobile_admin':
            chat_message_data = model_to_dict(chat_message)
            member = chat_message.member
            if member:
                chat_message_data['member'] = {
                        'id': member.id,
                        'first_name': member.first_name,  
                        'last_name': member.last_name,
                        'image': member.staffprofile.image.url if member.staffprofile and member.staffprofile.image else None
                }
            self.send(text_data=json.dumps({
                'event_type': 'send_message',
                'chat_message_data': chat_message_data,
            },cls=DjangoJSONEncoder))
        elif self.client_type == 'website_admin':
            html = render_to_string("chat_templates/partials/message.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'send_message',
                'user': chat_message.member.id if chat_message.member else None,
                'html': html,
            }))
        else:
            html = render_to_string("partials/message.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'send_message',
                'user': chat_message.member.id if chat_message.member else None,
                'html': html,
            }))


    def uploaded_file_handler(self, event):
        message_attachment = get_object_or_404(ChatMessageAttachment, id=event['message_attachment_id'])
        context = {
            'message_attachment': message_attachment,
            'file_type': event['file_type'],
            'domain': self.domain
        }
        if self.client_type == 'mobile_admin':
            message_attachment_data = model_to_dict(message_attachment)
            self.send(text_data=json.dumps({
                'event_type': 'uploaded_file',
                'message_attachment_data': message_attachment_data,
                'user': message_attachment.message.member.id if message_attachment.message.member else None,
                'file_type': event['file_type']
            },cls=DjangoJSONEncoder))
        else:
            html = render_to_string("partials/message-attachment.html", context=context)
            self.send(text_data=json.dumps({
                'event_type': 'uploaded_file',
                'file_name': event['file_name'],
                'user': message_attachment.message.member.id if message_attachment.message.member else None,
                'html': html,
            }))


    def update_read_messages_handler(self, event): 
        latest_unread_message_id = event.get('latest_unread_message_id')
        if latest_unread_message_id:
            latest_unread_message = get_object_or_404(ChatMessage, id=latest_unread_message_id)
            context = {
            'number_of_unread' : event['number_of_unread'],
            'latest_unread_message': latest_unread_message,
            'domain': self.domain
            }
            if self.client_type == 'mobile_admin':
                self.send(text_data=json.dumps({
                    'event_type': 'update_read_messages',
                    'number_of_unread': event['number_of_unread'],
                 },cls=DjangoJSONEncoder))
            else:
                html = render_to_string("partials/unread-messages.html", context=context)
                self.send(text_data=json.dumps({
                    'event_type': 'update_read_messages',
                    'html': html,
                }))
        else:
            latest_unread_message = None


    def end_chat_handler(self, event):
        if event['user_id']:
            member = get_object_or_404(User, id=event['user_id'])
        else:
            member = None
        self.chat_room.date_terminated = datetime.now()
        self.chat_room.terminated_by = member
        self.chat_room.save()
        context = {
            'chat_room': self.chat_room,
            'chat_room_messages': ChatMessage.objects.filter(room=self.chat_room).order_by('date_sent'),
            'domain': self.domain
        }
        html = render_to_string("ended-chat.html", context=context)
        self.send(text_data=json.dumps({
            'event_type': 'ended_chat',
            'html': html,
        }))

    def submit_review_handler(self, event):
        review = get_object_or_404(ChatRoomReview, id=event['review_id'])
        context = {
            'review': review,
            'chat_room': self.chat_room,
        }
        html = render_to_string("partials/submitted-review.html", context=context)
        self.send(text_data=json.dumps({
            'event_type': 'submit_review',
            'html': html,
        }))