# inbox/views.py
from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .models import Conversation, Message
from .serializers import ConversationListSerializer, MessageSerializer, UserMiniSerializer

User = get_user_model()


def _get_contacts(user):
    ids = set()
    try:
        from followers.models import Follow
        ids |= set(Follow.objects.filter(follower=user).values_list("following_id", flat=True))
        ids |= set(Follow.objects.filter(following=user).values_list("follower_id", flat=True))
    except Exception:
        pass
    try:
        from friends.models import Friendship
        for f in Friendship.objects.filter(Q(user1=user) | Q(user2=user)):
            ids.add(f.user2_id if f.user1 == user else f.user1_id)
    except Exception:
        pass
    try:
        from friends.models import FriendRequest
        ids |= set(FriendRequest.objects.filter(from_user=user, status="accepted").values_list("to_user_id", flat=True))
        ids |= set(FriendRequest.objects.filter(to_user=user, status="accepted").values_list("from_user_id", flat=True))
    except Exception:
        pass
    ids.discard(user.id)
    if ids:
        return User.objects.filter(id__in=ids)
    return User.objects.exclude(id=user.id)[:30]


# ── Conversations list + create ────────────────────────────────
@api_view(["GET", "POST"])
@permission_classes([IsAuthenticated])
def conversations(request):
    if request.method == "GET":
        qs = (Conversation.objects
              .filter(participants=request.user)
              .prefetch_related("participants", "messages")
              .order_by("-updated_at"))
        return Response(ConversationListSerializer(qs, many=True, context={"request": request}).data)

    # POST — find or create 1-to-1
    pid = request.data.get("participant_id")
    if not pid:
        return Response({"detail": "participant_id required."}, status=400)
    other = get_object_or_404(User, id=pid)
    if other == request.user:
        return Response({"detail": "Cannot message yourself."}, status=400)
    conv = (Conversation.objects
            .filter(participants=request.user)
            .filter(participants=other)
            .first())
    if not conv:
        conv = Conversation.objects.create()
        conv.participants.add(request.user, other)
    return Response(ConversationListSerializer(conv, context={"request": request}).data, status=201)


# ── Single conversation: GET detail OR DELETE ─────────────────
@api_view(["GET", "DELETE"])
@permission_classes([IsAuthenticated])
def conversation_detail(request, conv_id):
    # Fetch conv — don't filter by participant yet so we can give a proper 403
    try:
        conv = Conversation.objects.get(id=conv_id)
    except Conversation.DoesNotExist:
        return Response({"detail": "Conversation not found."}, status=404)

    if not conv.participants.filter(id=request.user.id).exists():
        return Response({"detail": "Not a participant."}, status=403)

    if request.method == "GET":
        return Response(ConversationListSerializer(conv, context={"request": request}).data)

    # DELETE — remove this user from the conversation
    for msg in conv.messages.all():
        msg.deleted_by.add(request.user)
    conv.participants.remove(request.user)
    if conv.participants.count() == 0:
        conv.delete()
    return Response({"detail": "Conversation deleted."}, status=200)


# ── Messages: list + send ─────────────────────────────────────
@api_view(["GET", "POST"])
@permission_classes([IsAuthenticated])
def messages(request, conv_id):
    conv = get_object_or_404(Conversation, id=conv_id, participants=request.user)

    if request.method == "GET":
        for msg in conv.messages.exclude(sender=request.user).exclude(read_by=request.user):
            msg.read_by.add(request.user)
        qs = conv.messages.exclude(deleted_by=request.user).order_by("created_at")
        return Response(MessageSerializer(qs, many=True, context={"request": request}).data)

    # POST — send
    content         = request.data.get("content", "").strip()
    reply_to_id     = request.data.get("reply_to")
    forward_from_id = request.data.get("forward_id")

    image = request.FILES.get('image')
    audio = request.FILES.get('audio')
    if not content and not forward_from_id and not image and not audio:
        return Response({"detail": "Content required."}, status=400)

    reply_obj = Message.objects.filter(id=reply_to_id, conversation=conv).first() if reply_to_id else None
    fwd_obj   = None
    if forward_from_id:
        orig = Message.objects.filter(id=forward_from_id).first()
        if orig and not orig.deleted_for_everyone:
            fwd_obj = orig
            if not content:
                content = orig.content

    msg = Message.objects.create(
        conversation=conv, sender=request.user,
        content=content, reply_to=reply_obj, forwarded_from=fwd_obj, image=image, audio=audio,
    )
    conv.save()

    # Optional notification
    try:
        from notifications.utils import create_notification
        for p in conv.participants.exclude(id=request.user.id):
            create_notification(
                recipient=p, notif_type="message",
                title=f"{request.user.username} sent you a message",
                body=content[:60], link="/user/inbox", sender=request.user,
            )
    except Exception:
        pass

    return Response(MessageSerializer(msg, context={"request": request}).data, status=201)


# ── Single message: edit or delete ───────────────────────────
@api_view(["PATCH", "DELETE"])
@permission_classes([IsAuthenticated])
def message_detail(request, conv_id, msg_id):
    conv = get_object_or_404(Conversation, id=conv_id, participants=request.user)
    msg  = get_object_or_404(Message, id=msg_id, conversation=conv)

    if request.method == "PATCH":
        if msg.sender != request.user:
            return Response({"detail": "Cannot edit others' messages."}, status=403)
        content = request.data.get("content", "").strip()
        if not content:
            return Response({"detail": "Content required."}, status=400)
        if msg.deleted_for_everyone:
            return Response({"detail": "Cannot edit deleted message."}, status=400)
        msg.content = content
        msg.edited  = True
        msg.save(update_fields=["content", "edited", "updated_at"])
        return Response(MessageSerializer(msg, context={"request": request}).data)

    # DELETE
    for_everyone = request.data.get("delete_for_everyone", False)
    if for_everyone:
        if msg.sender != request.user:
            return Response({"detail": "Only sender can delete for everyone."}, status=403)
        msg.deleted_for_everyone = True
        msg.content = ""
        msg.save(update_fields=["deleted_for_everyone", "content", "updated_at"])
    else:
        msg.deleted_by.add(request.user)
    return Response({"detail": "Deleted.", "for_everyone": for_everyone})


# ── Forward ───────────────────────────────────────────────────
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def forward_message(request, msg_id):
    target_id = request.data.get("conversation_id")
    if not target_id:
        return Response({"detail": "conversation_id required."}, status=400)
    orig   = get_object_or_404(Message, id=msg_id)
    target = get_object_or_404(Conversation, id=target_id, participants=request.user)
    if orig.deleted_for_everyone:
        return Response({"detail": "Cannot forward deleted message."}, status=400)
    msg = Message.objects.create(
        conversation=target, sender=request.user,
        content=orig.content, forwarded_from=orig,
    )
    target.save()
    return Response(MessageSerializer(msg, context={"request": request}).data, status=201)


# ── Contacts / search ─────────────────────────────────────────
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def contacts(request):
    q  = request.GET.get("q", "").strip()
    qs = _get_contacts(request.user)
    if q:
        qs = qs.filter(Q(username__icontains=q) | Q(email__icontains=q))
    return Response(UserMiniSerializer(qs, many=True, context={"request": request}).data)

@api_view(["POST"])
@permission_classes([IsAuthenticated])
def toggle_reaction(request, conv_id, msg_id):
    from .models import MessageReaction
    emoji = request.data.get("emoji", "").strip()
    if not emoji:
        return Response({"error": "Emoji required."}, status=400)
    msg = get_object_or_404(Message, id=msg_id, conversation_id=conv_id)
    reaction, created = MessageReaction.objects.get_or_create(
        message=msg, user=request.user, emoji=emoji
    )
    if not created:
        reaction.delete()
    # Return all reactions for this message
    reactions = {}
    for r in msg.reactions.all():
        reactions[r.emoji] = reactions.get(r.emoji, [])
        reactions[r.emoji].append(r.user.username)
    return Response({"reactions": reactions, "msg_id": msg_id})
