from osinacore.api.utils import *
from osichat.models import *
from rest_framework.decorators import api_view
from .serializers import *
from django.shortcuts import get_object_or_404
from django.db.models import Q
from django.utils.dateparse import parse_date
from django.db.models import Count
from django.forms.models import model_to_dict

@api_view(['GET'])    
def get_chat_rooms(request):
    chat_rooms = ChatRoom.objects.annotate(last_update=Max('chatmessage__date_sent')).filter(chatroomguest__isnull=False).order_by('-last_update', '-date_created')
    chat_rooms_serializer = ChatRoomSerializer(chat_rooms, many=True)
    return successRes(chat_rooms_serializer.data)
    


@api_view(['GET'])    
def get_dms(request):
    try:
        token_data = verify(request.headers.get("Authorization"))
        user_id = token_data['userid']
        user = User.objects.get(id=user_id)
        chat_rooms = ChatRoom.objects.annotate(last_update=Max('chatmessage__date_sent')).filter(chatmember__member=user, chatroomguest__isnull=True).order_by('-last_update', '-date_created')

        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)

        return successRes(chat_rooms_data)
    except TokenError as terr:
        return errorRes(msg=str(terr), status=450)
    except Exception as e:
        return errorRes(str(e))


@api_view(['GET'])
def get_visitors(request):
    start_date = request.query_params.get("start_date")
    end_date = request.query_params.get("end_date")
    
    if start_date:
        start_date = parse_date(start_date)
    if end_date:
        end_date = parse_date(end_date)
    
    if start_date and end_date:  # Range of time
        visitors = Visitor.objects.filter(Q(visitorlog__visit_date__date__range=[start_date, end_date]) |  Q(visitorlog__left_date__date__range=[start_date, end_date])).distinct().annotate(latest_visit=Max('visitorlog__visit_date')).order_by('-latest_visit')

    elif start_date and not end_date:  # Specific date
        visitors = Visitor.objects.filter(Q(visitorlog__visit_date__date=start_date) | Q(visitorlog__left_date__date=start_date)).distinct().annotate(latest_visit=Max('visitorlog__visit_date')).order_by('-latest_visit')
        
    else:  # Active visitors
        visitors = Visitor.objects.filter(visitorlog__left_date__isnull=True).distinct().annotate(latest_visit=Max('visitorlog__visit_date')).order_by('-latest_visit')

    visitors_count = visitors.count()
    visitors_data = []
    for visitor in visitors:
        last_log_entry = VisitorLog.objects.filter(visitor=visitor).last()
        visitor_data = {
            "id": visitor.id,
            "ip": visitor.ip_address, 
            "flag": visitor.flag_image_url,  
            "is_online": visitor.is_online,
            "duration": visitor.total_duration,
            "last_log": last_log_entry.title if last_log_entry else None,
            "last_log_time": last_log_entry.visit_date if last_log_entry else None,
        }
        visitors_data.append(visitor_data)

    response_data = {
        "count": visitors_count,
        "visitors": visitors_data
    }

    return successRes(response_data)

    

@api_view(['GET'])    
def get_staffs(request):
    staffs = StaffProfile.objects.filter(user__is_active=True).all().order_by('user__first_name')
    staffs_data = []
    for staff in staffs:
        staff_data = {
            "id": staff.user.id,
            "first_name": staff.user.first_name, 
            "last_name": staff.user.last_name,  
            "image": staff.image.url,
            "last_seen": staff.get_last_seen
        }
        staffs_data.append(staff_data)
    
    return successRes(staffs_data)
    



@api_view(['POST'])    
def start_conversation(request):
    try:
        token_data = verify(request.headers.get("Authorization"))
        user_id = token_data['userid']
        user = User.objects.get(id=user_id)

        start_with_id = request.data.get('start_with')
        start_with = get_object_or_404(User, id=start_with_id)


        existing_chat_room = (
            ChatRoom.objects.annotate(member_count=Count('chatmember'))  
            .filter(member_count=2)  
            .filter(chatmember__member=user)  
            .filter(chatmember__member=start_with)  
            .distinct()
            .first()
        )
        if existing_chat_room:
            return successRes({'room_id': existing_chat_room.id})

        else:
            chat_title = (
                f"Chat created by {user.first_name} {user.last_name} "
                f"with {start_with.first_name} {start_with.last_name} "
                f"on {timezone.now()}"
            )

            room = ChatRoom.objects.create(
                name=chat_title,
                created_by=user,
                date_created=timezone.now(),
            )

            ChatMember.objects.create(
                member=user,
                room=room,
                date_joined=timezone.now()
            )
            ChatMember.objects.create(
                member=start_with,
                room=room,
                date_joined=timezone.now()
            )

            return successRes({'room_id': room.id})


    except TokenError as terr:
        return errorRes(msg=str(terr), status=450)
    except Exception as e:
        return errorRes(str(e))
