"""
chat/views.py

Views for the Chat application.
"""

from django.contrib import messages
from django.db.models import Max, Q
from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.decorators.http import require_POST

from chat.forms import AddMembersForm, ChatMessageForm, ChatRoomForm, StartDirectChatForm
from chat.models import (
    ChatAttachment,
    ChatMessage,
    ChatRoom,
    ChatRoomMember,
    MessageReaction,
)
from employee.models import Employee
from horilla.decorators import hx_request_required, login_required
from notifications.signals import notify


@login_required
def chat_home(request):
    """
    Main chat page showing list of conversations.
    """
    employee = request.user.employee_get
    
    # Get all chat rooms where the user is a member
    chat_rooms = ChatRoom.objects.filter(
        members__employee_id=employee,
        is_active=True,
    ).annotate(
        last_message_time=Max("messages__created_at")
    ).order_by("-last_message_time")
    
    # Add unread count and display info for each room
    rooms_with_info = []
    for room in chat_rooms:
        rooms_with_info.append({
            "room": room,
            "display_name": room.get_display_name(employee),
            "room_image": room.get_room_image(employee),
            "last_message": room.get_last_message(),
            "unread_count": room.get_unread_count(employee),
        })
    
    # Forms for creating new chats
    direct_chat_form = StartDirectChatForm(request=request)
    group_chat_form = ChatRoomForm(request=request)
    
    context = {
        "rooms": rooms_with_info,
        "direct_chat_form": direct_chat_form,
        "group_chat_form": group_chat_form,
        "current_employee": employee,
    }
    return render(request, "chat/chat_home.html", context)


@login_required
def chat_room_list(request):
    """
    HTMX endpoint to refresh chat room list.
    """
    employee = request.user.employee_get
    
    chat_rooms = ChatRoom.objects.filter(
        members__employee_id=employee,
        is_active=True,
    ).annotate(
        last_message_time=Max("messages__created_at")
    ).order_by("-last_message_time")
    
    rooms_with_info = []
    for room in chat_rooms:
        rooms_with_info.append({
            "room": room,
            "display_name": room.get_display_name(employee),
            "room_image": room.get_room_image(employee),
            "last_message": room.get_last_message(),
            "unread_count": room.get_unread_count(employee),
        })
    
    context = {
        "rooms": rooms_with_info,
        "current_employee": employee,
    }
    return render(request, "chat/components/chat_room_list.html", context)


@login_required
def chat_room_detail(request, room_id):
    """
    View a specific chat room and its messages.
    """
    employee = request.user.employee_get
    room = get_object_or_404(ChatRoom, id=room_id, members__employee_id=employee)
    
    # Mark messages as read
    member = room.members.filter(employee_id=employee).first()
    if member:
        member.last_read_at = timezone.now()
        member.save()

    # Check if user is admin (for group chats)
    is_admin = member and member.role == "admin" if room.room_type == "group" else False

    # Get messages
    chat_messages = room.messages.select_related("sender").prefetch_related(
        "attachments", "reactions", "reactions__employee_id"
    ).order_by("created_at")

    message_form = ChatMessageForm()

    context = {
        "room": room,
        "display_name": room.get_display_name(employee),
        "room_image": room.get_room_image(employee),
        "messages": chat_messages,
        "message_form": message_form,
        "current_employee": employee,
        "members": room.members.select_related("employee_id") if room.room_type == "group" else None,
        "is_admin": is_admin,
    }
    return render(request, "chat/chat_room_detail.html", context)


@login_required
@hx_request_required
def chat_messages(request, room_id):
    """
    HTMX endpoint to refresh messages in a chat room.
    """
    employee = request.user.employee_get
    room = get_object_or_404(ChatRoom, id=room_id, members__employee_id=employee)
    
    # Get last message id to only fetch new messages
    last_message_id = request.GET.get("last_id", 0)
    
    chat_messages = room.messages.filter(id__gt=last_message_id).select_related(
        "sender"
    ).prefetch_related("attachments", "reactions").order_by("created_at")
    
    # Mark as read
    member = room.members.filter(employee_id=employee).first()
    if member:
        member.last_read_at = timezone.now()
        member.save()
    
    context = {
        "messages": chat_messages,
        "current_employee": employee,
        "room": room,
        "is_poll": True,
    }
    return render(request, "chat/components/messages.html", context)


@login_required
@hx_request_required
def send_message(request, room_id):
    """
    Send a message in a chat room.
    """
    employee = request.user.employee_get
    room = get_object_or_404(ChatRoom, id=room_id, members__employee_id=employee)

    if request.method == "POST":
        form = ChatMessageForm(request.POST, request.FILES)
        content = request.POST.get("content", "").strip()
        files = request.FILES.getlist("attachments")
        reply_to_id = request.POST.get("reply_to")

        # Create message
        message_type = "text"
        if files:
            # Check if all files are images
            all_images = all(
                f.content_type.startswith("image/") for f in files
            )
            message_type = "image" if all_images else "file"

        message = ChatMessage.objects.create(
            chat_room=room,
            sender=employee,
            content=content if content else None,
            message_type=message_type,
            reply_to_id=reply_to_id if reply_to_id else None,
        )

        # Handle file attachments
        for file in files:
            ChatAttachment.objects.create(
                message=message,
                file=file,
                file_name=file.name,
                file_size=file.size,
                file_type=file.content_type,
            )

        # Send notifications to other members
        other_members = room.members.exclude(employee_id=employee).filter(is_muted=False)
        for member in other_members:
            if member.employee_id.employee_user_id:
                notify.send(
                    employee.employee_user_id,
                    recipient=member.employee_id.employee_user_id,
                    verb=f"sent you a message in {room.get_display_name(member.employee_id)}",
                    icon="chatbubble",
                    redirect=f"/chat/room/{room.id}/",
                )

        # Return the new message
        context = {
            "messages": [message],
            "current_employee": employee,
            "room": room,
        }
        return render(request, "chat/components/messages.html", context)

    return HttpResponse(status=400)


@login_required
@hx_request_required
def start_direct_chat(request):
    """
    Start a direct chat with another employee.
    """
    employee = request.user.employee_get

    if request.method == "POST":
        form = StartDirectChatForm(request.POST, request=request)
        if form.is_valid():
            other_employee = form.cleaned_data["employee_id"]

            # Check if a direct chat already exists between these two
            existing_room = ChatRoom.objects.filter(
                room_type="direct",
                members__employee_id=employee,
            ).filter(
                members__employee_id=other_employee,
            ).first()

            if existing_room:
                room = existing_room
            else:
                # Create new direct chat room
                room = ChatRoom.objects.create(
                    room_type="direct",
                    company_id=employee.get_company(),
                )

                # Add both members
                ChatRoomMember.objects.create(
                    chat_room=room,
                    employee_id=employee,
                    role="member",
                )
                ChatRoomMember.objects.create(
                    chat_room=room,
                    employee_id=other_employee,
                    role="member",
                )

            messages.success(request, _("Chat started successfully!"))
            return HttpResponse("<script>window.location.reload();</script>")

    return HttpResponse(status=400)


@login_required
@hx_request_required
def create_group_chat(request):
    """
    Create a new group chat.
    """
    employee = request.user.employee_get

    if request.method == "POST":
        form = ChatRoomForm(request.POST, request.FILES, request=request)
        if form.is_valid():
            room = form.save(commit=False)
            room.room_type = "group"
            room.company_id = employee.get_company()
            room.save()

            # Add current user as admin
            ChatRoomMember.objects.create(
                chat_room=room,
                employee_id=employee,
                role="admin",
            )

            # Add selected members
            for member_employee in form.cleaned_data["members"]:
                ChatRoomMember.objects.create(
                    chat_room=room,
                    employee_id=member_employee,
                    role="member",
                )

            # Create system message
            ChatMessage.objects.create(
                chat_room=room,
                sender=employee,
                content=f"{employee.get_full_name()} created this group",
                message_type="system",
            )

            messages.success(request, _("Group chat created successfully!"))
            return HttpResponse("<script>window.location.reload();</script>")
        else:
            messages.error(request, _("Please correct the errors below."))

    return HttpResponse(status=400)


@login_required
@hx_request_required
def add_members_form(request, room_id):
    """
    HTMX endpoint to get the Add Members form modal.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        room_type="group",
        members__employee_id=employee,
    )

    # Check if user is admin
    member = room.members.filter(employee_id=employee).first()
    if not member or member.role != "admin":
        return HttpResponse(status=403)

    # Get employees not already in the group
    existing_member_ids = room.members.values_list("employee_id", flat=True)
    employees = Employee.objects.filter(is_active=True).exclude(id__in=existing_member_ids)

    # Filter by company if applicable
    company = employee.get_company()
    if company:
        employees = employees.filter(employee_work_info__company_id=company)

    context = {
        "room": room,
        "employees": employees,
    }
    return render(request, "chat/components/add_members_modal.html", context)


@login_required
def add_group_members(request, room_id):
    """
    Add members to a group chat.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        room_type="group",
        members__employee_id=employee,
    )

    # Check if user is admin
    member = room.members.filter(employee_id=employee).first()
    if not member or member.role != "admin":
        messages.error(request, _("Only admins can add members."))
        return redirect("chat-home")

    if request.method == "POST":
        member_ids = request.POST.getlist("members")
        if member_ids:
            added_names = []
            for member_id in member_ids:
                new_member = Employee.objects.filter(id=member_id, is_active=True).first()
                if new_member and not room.members.filter(employee_id=new_member).exists():
                    ChatRoomMember.objects.create(
                        chat_room=room,
                        employee_id=new_member,
                        role="member",
                    )
                    added_names.append(new_member.get_full_name())

            if added_names:
                # System message
                ChatMessage.objects.create(
                    chat_room=room,
                    sender=employee,
                    content=f"{employee.get_full_name()} added {', '.join(added_names)}",
                    message_type="system",
                )
                messages.success(request, _("Members added successfully!"))

    return redirect("chat-home")


@login_required
def remove_group_member(request, room_id, member_id):
    """
    Remove a member from a group chat.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        room_type="group",
        members__employee_id=employee,
    )

    # Check if user is admin
    current_member = room.members.filter(employee_id=employee).first()
    if not current_member or current_member.role != "admin":
        messages.error(request, _("Only admins can remove members."))
        return redirect("chat-home")

    member_to_remove = get_object_or_404(ChatRoomMember, id=member_id, chat_room=room)
    removed_name = member_to_remove.employee_id.get_full_name()
    member_to_remove.delete()

    # System message
    ChatMessage.objects.create(
        chat_room=room,
        sender=employee,
        content=f"{employee.get_full_name()} removed {removed_name}",
        message_type="system",
    )

    messages.success(request, _("Member removed successfully!"))
    return redirect("chat-home")


@login_required
def update_group(request, room_id):
    """
    Update group chat details (name, description, image).
    Only admins can update.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        room_type="group",
        members__employee_id=employee,
    )

    # Check if user is admin
    member = room.members.filter(employee_id=employee).first()
    if not member or member.role != "admin":
        messages.error(request, _("Only admins can update group details."))
        return redirect("chat-home")

    if request.method == "POST":
        name = request.POST.get("name", "").strip()
        description = request.POST.get("description", "").strip()
        room_image = request.FILES.get("room_image")

        if name:
            room.name = name
            room.description = description
            if room_image:
                room.room_image = room_image
            room.save()
            messages.success(request, _("Group updated successfully!"))
        else:
            messages.error(request, _("Group name is required."))

    return redirect("chat-home")


@login_required
def leave_group(request, room_id):
    """
    Leave a group chat.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        room_type="group",
        members__employee_id=employee,
    )

    member = room.members.filter(employee_id=employee).first()
    if member:
        # If admin is leaving, promote another member to admin
        if member.role == "admin":
            other_member = room.members.exclude(employee_id=employee).first()
            if other_member:
                other_member.role = "admin"
                other_member.save()

        # System message
        ChatMessage.objects.create(
            chat_room=room,
            sender=employee,
            content=f"{employee.get_full_name()} left the group",
            message_type="system",
        )

        member.delete()
        messages.success(request, _("You have left the group."))

    return redirect("chat-home")


@login_required
def delete_chat(request, room_id):
    """
    Delete a chat room (direct chat or group).
    For groups, only admins can delete.
    Deletes the chat for all participants.
    """
    employee = request.user.employee_get
    room = get_object_or_404(
        ChatRoom,
        id=room_id,
        members__employee_id=employee,
    )

    # Check permissions
    if room.room_type == "group":
        member = room.members.filter(employee_id=employee).first()
        if not member or member.role != "admin":
            messages.error(request, _("Only group admins can delete the group."))
            return redirect("chat-room-detail", room_id=room.id)

    # Delete all related data (cascade will handle messages, attachments, reactions, members)
    room_name = room.name if room.room_type == "group" else "Chat"
    room.delete()

    messages.success(request, _(f"{room_name} has been deleted."))
    return redirect("chat-home")


@login_required
@require_POST
def toggle_reaction(request, message_id):
    """
    Add or remove an emoji reaction to a message.
    """
    # Check if it's an AJAX request
    is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.headers.get('HX-Request')
    if not is_ajax:
        return HttpResponse(status=400)

    employee = request.user.employee_get
    message = get_object_or_404(
        ChatMessage,
        id=message_id,
        chat_room__members__employee_id=employee,
    )

    emoji = request.POST.get("emoji", "👍")

    # Check if reaction exists
    existing = MessageReaction.objects.filter(
        message=message,
        employee_id=employee,
        emoji=emoji,
    ).first()

    if existing:
        existing.delete()
    else:
        MessageReaction.objects.create(
            message=message,
            employee_id=employee,
            emoji=emoji,
        )

    # Return updated reactions as JSON
    message.refresh_from_db()
    reactions_data = []
    from django.db.models import Count
    reaction_groups = message.reactions.values('emoji').annotate(count=Count('id'))
    for group in reaction_groups:
        users = list(message.reactions.filter(emoji=group['emoji']).values_list('employee_id__employee_first_name', flat=True))
        reactions_data.append({
            'emoji': group['emoji'],
            'count': group['count'],
            'users': users,
        })

    return JsonResponse({'reactions': reactions_data})


@login_required
@require_POST
def delete_message(request, message_id):
    """
    Delete a message (only sender can delete their own messages).
    """
    # Check if it's an AJAX request
    if not request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        return HttpResponse(status=400)

    employee = request.user.employee_get
    message = get_object_or_404(
        ChatMessage,
        id=message_id,
        sender=employee,  # Only the sender can delete
    )

    message.delete()

    return HttpResponse("")  # Return empty response to remove the element


@login_required
def search_employees(request):
    """
    Search employees for starting a new chat.
    """
    employee = request.user.employee_get
    query = request.GET.get("q", "")

    employees = Employee.objects.filter(is_active=True).exclude(id=employee.id)

    # Filter by company
    company = employee.get_company()
    if company:
        employees = employees.filter(employee_work_info__company_id=company)

    # Search by name
    if query:
        employees = employees.filter(
            Q(employee_first_name__icontains=query) |
            Q(employee_last_name__icontains=query) |
            Q(email__icontains=query)
        )[:10]
    else:
        employees = employees[:10]

    results = [
        {
            "id": emp.id,
            "name": emp.get_full_name(),
            "avatar": emp.get_avatar(),
            "position": str(emp.get_job_position()) if emp.get_job_position() else "",
        }
        for emp in employees
    ]

    return JsonResponse({"results": results})


@login_required
@hx_request_required
def get_unread_count(request):
    """
    Get total unread message count for the current user.
    """
    employee = request.user.employee_get

    total_unread = 0
    rooms = ChatRoom.objects.filter(
        members__employee_id=employee,
        is_active=True,
    )

    for room in rooms:
        total_unread += room.get_unread_count(employee)

    return JsonResponse({"unread_count": total_unread})

