from rest_framework import viewsets, permissions, serializers, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db import transaction
from django.db.models import Q
from django.contrib.auth import get_user_model
from .models import Conversation, ConversationParticipant, Message, MessageAttachment

User = get_user_model()

def is_staff_role(user):
    return user.is_authenticated and user.is_staff_member

def is_admin_role(user):
    return user.is_authenticated and user.is_admin

def is_customer_role(user):
    return user.is_authenticated and user.role == User.Role.CUSTOMER

def is_vendor_role(user):
    return user.is_authenticated and user.role == User.Role.VENDOR

def is_pair_allowed(u1, u2):
    if is_staff_role(u1) and is_staff_role(u2):
        return True
    if is_admin_role(u1) and is_staff_role(u2):
        return True
    if is_staff_role(u1) and is_admin_role(u2):
        return True
    if is_staff_role(u1) and is_customer_role(u2):
        return True
    if is_customer_role(u1) and is_staff_role(u2):
        return True
    if is_staff_role(u1) and is_vendor_role(u2):
        return True
    if is_vendor_role(u1) and is_staff_role(u2):
        return True
    return False

class ConversationParticipantSerializer(serializers.ModelSerializer):
    class Meta:
        model = ConversationParticipant
        fields = ['user', 'joined_at']

class ConversationSerializer(serializers.ModelSerializer):
    participants = ConversationParticipantSerializer(many=True, read_only=True)
    class Meta:
        model = Conversation
        fields = ['id', 'created_by', 'is_group', 'created_at', 'last_message_at', 'last_message_preview', 'participants']
        read_only_fields = ['created_by', 'created_at', 'last_message_at', 'last_message_preview']

class MessageAttachmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = MessageAttachment
        fields = ['id', 'file', 'file_name', 'content_type', 'size', 'created_at']

class MessageSerializer(serializers.ModelSerializer):
    attachments = MessageAttachmentSerializer(many=True, read_only=True)
    class Meta:
        model = Message
        fields = ['id', 'conversation', 'sender', 'body', 'created_at', 'edited_at', 'is_deleted', 'attachments']
        read_only_fields = ['sender', 'created_at', 'edited_at']

class ConversationViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = ConversationSerializer

    def get_queryset(self):
        user = self.request.user
        conv_ids = ConversationParticipant.objects.filter(user=user).values_list('conversation_id', flat=True)
        return Conversation.objects.filter(id__in=list(conv_ids)).order_by('-created_at')

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        target_id = request.data.get('target_user_id')
        if not target_id:
            return Response({'error': 'target_user_id required'}, status=400)
        try:
            target = User.objects.get(id=int(target_id))
        except Exception:
            return Response({'error': 'target user not found'}, status=404)
        me = request.user
        if me.id == target.id:
            return Response({'error': 'cannot start conversation with self'}, status=400)
        if not is_pair_allowed(me, target):
            return Response({'error': 'not allowed for these roles'}, status=403)
        existing = Conversation.objects.filter(
            is_group=False,
            participants__user=me
        ).filter(
            participants__user=target
        ).distinct().first()
        if existing:
            ser = self.get_serializer(existing)
            return Response(ser.data, status=200)
        conv = Conversation.objects.create(created_by=me, is_group=False)
        ConversationParticipant.objects.bulk_create([
            ConversationParticipant(conversation=conv, user=me),
            ConversationParticipant(conversation=conv, user=target),
        ])
        ser = self.get_serializer(conv)
        return Response(ser.data, status=201)

class MessageViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = MessageSerializer

    def get_queryset(self):
        user = self.request.user
        conv_ids = ConversationParticipant.objects.filter(user=user).values_list('conversation_id', flat=True)
        return Message.objects.filter(conversation_id__in=list(conv_ids)).order_by('created_at')

    def create(self, request, *args, **kwargs):
        conv_id = request.data.get('conversation')
        body = request.data.get('body', '').strip()
        if not conv_id or not body:
            return Response({'error': 'conversation and body required'}, status=400)
        if len(body) > 200:
            return Response({'error': 'body exceeds 200 characters'}, status=400)
        try:
            conv = Conversation.objects.get(id=int(conv_id))
        except Exception:
            return Response({'error': 'conversation not found'}, status=404)
        if not ConversationParticipant.objects.filter(conversation=conv, user=request.user).exists():
            return Response({'error': 'not a participant'}, status=403)
        if not conv.is_group:
            parts = list(conv.participants.all())
            if len(parts) == 2:
                other = parts[0].user if parts[1].user_id == request.user.id else parts[1].user
                if not is_pair_allowed(request.user, other):
                    return Response({'error': 'not allowed for these roles'}, status=403)
        msg = Message.objects.create(conversation=conv, sender=request.user, body=body)
        ser = self.get_serializer(msg)
        return Response(ser.data, status=201)
