from rest_framework import generics, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q, Count
from django.utils import timezone
from django.db import transaction
from django.core.mail import send_mail
from django.conf import settings
from django.contrib.auth import get_user_model
import logging
from .models import *
from .serializers import *


def is_system_administrator(user):
    try:
        from django.apps import apps
        UserAssignedRole = apps.get_model('users', 'UserAssignedRole')
        return UserAssignedRole.objects.filter(
            user=user,
            assigned_role__role_name__iexact='System Administrator',
            is_active=True
        ).exists() or user.is_staff or user.is_superuser
    except Exception as e:
        print(f"Error checking System Administrator role: {e}")
        return False


class ChatRoomViewSet(viewsets.ModelViewSet):
    serializer_class = ChatRoomSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['room_type', 'status', 'priority', 'organisation']
    
    def get_queryset(self):
        # Users can only see rooms they're members of or created
        return ChatRoom.objects.filter(
            Q(members__user=self.request.user) | Q(created_by=self.request.user)
        ).distinct().order_by('-created_at')
    
    def get_serializer_class(self):
        if self.action == 'create':
            return CreateChatRoomSerializer
        return ChatRoomSerializer
    
    def create(self, request, *args, **kwargs):
        """Create a new chat room and auto-add organisation members if applicable"""
        user = request.user

    # Ensure only System Admins can create organisation chat rooms
        if not is_system_administrator(user):
           return Response(
                {'error': 'Only System Administrators can create organization chat rooms'},
              status=status.HTTP_403_FORBIDDEN
          )

        room_type = request.data.get('room_type')

    # Identify the organisation
        user_org = None
        if hasattr(user, 'user_organisation_branch'):
            user_org = user.user_organisation_branch.branch_organisation

    # Prevent duplicate organisation-wide chat room
        if room_type == 'organisation' and user_org and ChatRoom.objects.filter(
            organisation=user_org,
            room_type='organisation'
        ).exists():
            return Response(
                {'error': 'Your organization already has a chat room'},
               status=status.HTTP_400_BAD_REQUEST
            )

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        with transaction.atomic():
        # Create room
            chat_room = serializer.save(created_by=user, organisation=user_org)

        # Auto-add all active staff to this room if it’s organisation-wide
            if room_type == 'organisation' and user_org:
                User = get_user_model()
                staff_members = User.objects.filter(
                    user_organisation_branch__branch_organisation=user_org,
                    is_active=True
                ).distinct()

                RoomMember.objects.bulk_create([
                    RoomMember(
                       room=chat_room,
                       user=member,
                       joined_at=timezone.now(),
                       is_active=True,
                       is_admin=(member == user)
                    )
                   for member in staff_members
                ], ignore_conflicts=True)

        # Optional: Add the creator if not part of the above list
        RoomMember.objects.get_or_create(
            room=chat_room,
            user=user,
            defaults={'is_admin': True, 'is_active': True}
        )

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
    
    @action(detail=True, methods=['post'])
    def add_member(self, request, pk=None):
        """Add a member to the chat room"""
        room = self.get_object()
        
        # Only room creator or admins can add members
        if room.created_by != request.user and not RoomMember.objects.filter(
            room=room, user=request.user, is_admin=True
        ).exists():
            return Response(
                {'error': 'Only room creator or admins can add members'}, 
                status=status.HTTP_403_FORBIDDEN
            )
        
        user_id = request.data.get('user_id')
        if not user_id:
            return Response(
                {'error': 'user_id is required'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            from django.contrib.auth import get_user_model
            User = get_user_model()
            user = User.objects.get(id=user_id)
            
            member, created = RoomMember.objects.get_or_create(
                room=room,
                user=user,
                defaults={'is_active': True}
            )
            
            if not created:
                member.is_active = True
                member.save()
                message = 'Member re-added to the room'
            else:
                message = 'Member added successfully'
            
            # Create system message
            Message.objects.create(
                room=room,
                user=request.user,
                content=f"{user.username} was added to the room",
                message_type='system'
            )
            
            return Response({
                'message': message,
                'member': RoomMemberSerializer(member).data
            })
        except User.DoesNotExist:
            return Response(
                {'error': 'User not found'}, 
                status=status.HTTP_404_NOT_FOUND
            )
    
    @action(detail=True, methods=['post'])
    def remove_member(self, request, pk=None):
        """Remove a member from the chat room"""
        room = self.get_object()
        
        # Only room creator or admins can remove members
        if room.created_by != request.user and not RoomMember.objects.filter(
            room=room, user=request.user, is_admin=True
        ).exists():
            return Response(
                {'error': 'Only room creator or admins can remove members'}, 
                status=status.HTTP_403_FORBIDDEN
            )
        
        user_id = request.data.get('user_id')
        if not user_id:
            return Response(
                {'error': 'user_id is required'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            from django.contrib.auth import get_user_model
            User = get_user_model()
            user = User.objects.get(id=user_id)
            
            member = RoomMember.objects.get(room=room, user=user)
            member.is_active = False
            member.save()
            
            # Create system message
            Message.objects.create(
                room=room,
                user=request.user,
                content=f"{user.username} was removed from the room",
                message_type='system'
            )
            
            return Response({'message': 'Member removed successfully'})
        except User.DoesNotExist:
            return Response(
                {'error': 'User not found'}, 
                status=status.HTTP_404_NOT_FOUND
            )
        except RoomMember.DoesNotExist:
            return Response(
                {'error': 'User is not a member of this room'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=True, methods=['get'])
    def members(self, request, pk=None):
        """Get all members of a chat room"""
        room = self.get_object()
        members = room.members.filter(is_active=True)
        serializer = RoomMemberSerializer(members, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def join(self, request, pk=None):
        """Join a chat room"""
        room = self.get_object()
        member, created = RoomMember.objects.get_or_create(
            room=room,
            user=request.user,
            defaults={'is_active': True}
        )
        if not created:
            member.is_active = True
            member.save()
        
        return Response({'message': 'Successfully joined the room'})
    
    @action(detail=True, methods=['post'])
    def leave(self, request, pk=None):
        """Leave a chat room"""
        room = self.get_object()
        try:
            member = RoomMember.objects.get(room=room, user=request.user)
            member.is_active = False
            member.save()
            return Response({'message': 'Successfully left the room'})
        except RoomMember.DoesNotExist:
            return Response({'error': 'You are not a member of this room'}, 
                          status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['get', 'post'])
    def messages(self, request, pk=None):
        room = self.get_object()

        if request.method == 'GET':
           messages = room.messages.all().order_by('created_at')
           serializer = MessageSerializer(messages, many=True, context={'request': request})
           return Response(serializer.data)

        elif request.method == 'POST':
           serializer = CreateMessageSerializer(data=request.data, context={'request': request})
           serializer.is_valid(raise_exception=True)
           message = serializer.save(room=room, user=request.user)

        # Serialize with full sender info
        response_serializer = MessageSerializer(message, context={'request': request})
        return Response(response_serializer.data, status=status.HTTP_201_CREATED)
    
    @action(detail=True, methods=['get'])
    def poll_messages(self, request, pk=None):
        """Poll for new messages since a given timestamp"""
        room = self.get_object()
        since = request.query_params.get('since')
        
        if since:
            try:
                since_datetime = timezone.datetime.fromisoformat(since.replace('Z', '+00:00'))
                messages = room.messages.filter(created_at__gt=since_datetime).order_by('created_at')
            except (ValueError, TypeError):
                messages = room.messages.all().order_by('created_at')
        else:
            messages = room.messages.all().order_by('created_at')
        
        serializer = MessageSerializer(messages, many=True, context={'request': request})
        return Response({
            'messages': serializer.data,
            'timestamp': timezone.now().isoformat()
        })


class MessageViewSet(viewsets.ModelViewSet):
    serializer_class = MessageSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['room', 'message_type', 'user']
    
    def get_queryset(self):
        # Users can only see messages from rooms they're members of
        return Message.objects.filter(
            room__members__user=self.request.user,
            room__members__is_active=True
        ).order_by('-created_at')
    
    def get_serializer_class(self):
        if self.action == 'create':
            return CreateMessageSerializer
        return MessageSerializer
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
    
    @action(detail=True, methods=['post'])
    def mark_read(self, request, pk=None):
        """Mark a message as read"""
        message = self.get_object()
        MessageReadStatus.objects.get_or_create(
            message=message,
            user=request.user,
            defaults={'read_at': timezone.now()}
        )
        return Response({'message': 'Message marked as read'})
    
    @action(detail=True, methods=['post'])
    def edit(self, request, pk=None):
        """Edit a message"""
        message = self.get_object()
        if message.user != request.user:
            return Response({'error': 'You can only edit your own messages'}, 
                          status=status.HTTP_403_FORBIDDEN)
        
        content = request.data.get('content')
        if content:
            message.content = content
            message.is_edited = True
            message.edited_at = timezone.now()
            message.save()
            return Response({'message': 'Message updated successfully'})
        
        return Response({'error': 'Content is required'}, 
                      status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def delete(self, request, pk=None):
        """Soft delete a message"""
        message = self.get_object()
        if message.user != request.user:
            return Response({'error': 'You can only delete your own messages'}, 
                          status=status.HTTP_403_FORBIDDEN)
        
        message.is_deleted = True
        message.deleted_at = timezone.now()
        message.save()
        return Response({'message': 'Message deleted successfully'})


class SupportTicketViewSet(viewsets.ModelViewSet):
    serializer_class = SupportTicketSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['status', 'priority', 'assigned_staff']
    
    def get_queryset(self):
        # Users can only see their own tickets or tickets assigned to them
        # Staff can see all tickets
        if self.request.user.is_staff:
            return SupportTicket.objects.all().order_by('-created_at')
        return SupportTicket.objects.filter(
            Q(customer=self.request.user) | Q(assigned_staff=self.request.user)
        ).order_by('-created_at')
    
    def get_serializer_class(self):
        if self.action == 'create':
            return CreateSupportTicketSerializer
        return SupportTicketSerializer
    
    def perform_create(self, serializer):
        ticket = serializer.save(customer=self.request.user)
        self._notify_staff_of_new_ticket(ticket)
    
    def _notify_staff_of_new_ticket(self, ticket):
        """Send notifications to QDF staff when a new ticket is created"""
        from django.contrib.auth import get_user_model
        User = get_user_model()
        
        # Get all staff users
        staff_users = User.objects.filter(is_staff=True)
        
        # Send email notifications
        if staff_users.exists():
            staff_emails = [user.email for user in staff_users if user.email]
            
            if staff_emails:
                subject = f'New Support Ticket: {ticket.ticket_id}'
                message = f"""
A new support ticket has been created:

Ticket ID: {ticket.ticket_id}
Subject: {ticket.subject}
Priority: {ticket.get_priority_display()}
Customer: {ticket.customer.get_full_name() if hasattr(ticket.customer, 'get_full_name') else ticket.customer.username}
Created: {ticket.created_at.strftime('%Y-%m-%d %H:%M:%S')}

Description:
{ticket.description}

Please log in to the system to view and respond to this ticket.
                """
                
                try:
                    send_mail(
                        subject,
                        message,
                        settings.DEFAULT_FROM_EMAIL,
                        staff_emails,
                        fail_silently=True,
                    )
                except Exception as e:
                    print(f"Failed to send email notification: {e}")
        
        # Create in-app notifications (if you have a notification model)
        # You can extend this to create database notifications
        for staff_user in staff_users:
            # Create notification record here if you have a Notification model
            pass
    
    @action(detail=True, methods=['post'])
    def assign(self, request, pk=None):
        """Assign a support ticket to staff"""
        ticket = self.get_object()
        staff_id = request.data.get('staff_id')
        
        if not staff_id:
            return Response({'error': 'staff_id is required'}, 
                          status=status.HTTP_400_BAD_REQUEST)
        
        try:
            from django.contrib.auth import get_user_model
            User = get_user_model()
            staff = User.objects.get(id=staff_id)
            ticket.assigned_staff = staff
            ticket.status = 'in_progress'
            ticket.save()
            return Response({'message': 'Ticket assigned successfully'})
        except User.DoesNotExist:
            return Response({'error': 'Staff member not found'}, 
                          status=status.HTTP_404_NOT_FOUND)
    
    @action(detail=True, methods=['post'])
    def resolve(self, request, pk=None):
        """Resolve a support ticket"""
        ticket = self.get_object()
        ticket.status = 'resolved'
        ticket.resolved_at = timezone.now()
        ticket.save()
        return Response({'message': 'Ticket resolved successfully'})


class RoomMemberViewSet(viewsets.ModelViewSet):
    serializer_class = RoomMemberSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return RoomMember.objects.filter(
            room__members__user=self.request.user,
            room__members__is_active=True
        ).order_by('joined_at')


class PollUpdatesView(generics.GenericAPIView):
    """Poll for updates across all user's rooms"""
    permission_classes = [IsAuthenticated]
    
    def get(self, request):
        since = request.query_params.get('since')
        
        # Get all rooms user is a member of
        user_rooms = ChatRoom.objects.filter(
            Q(members__user=request.user, members__is_active=True) | 
            Q(created_by=request.user)
        ).distinct()
        
        updates = []
        
        for room in user_rooms:
            if since:
                try:
                    since_datetime = timezone.datetime.fromisoformat(since.replace('Z', '+00:00'))
                    new_messages = room.messages.filter(created_at__gt=since_datetime).count()
                except (ValueError, TypeError):
                    new_messages = 0
            else:
                new_messages = 0
            
            if new_messages > 0:
                updates.append({
                    'room_id': room.id,
                    'room_name': room.name,
                    'new_messages': new_messages
                })
        
        return Response({
            'updates': updates,
            'timestamp': timezone.now().isoformat()
        })


class UserSearchView(generics.ListAPIView):
    """Search for users by name or member number"""
    permission_classes = [IsAuthenticated]
    serializer_class = GetFullUserSerializer
    
    def get_queryset(self):
        from django.contrib.auth import get_user_model
        User = get_user_model()
        
        query = self.request.query_params.get('q', '')
        
        if not query:
            return User.objects.none()
        
        # Search by username, first name, last name, email, or member number
        queryset = User.objects.filter(
            Q(username__icontains=query) |
            Q(first_name__icontains=query) |
            Q(last_name__icontains=query) |
            Q(email__icontains=query)
        )
        
        # If the user model has a member_number field, include it in search
        if hasattr(User, 'member_number'):
            queryset = queryset | User.objects.filter(member_number__icontains=query)
        
        # Exclude the current user from results
        queryset = queryset.exclude(id=self.request.user.id)
        
        # Limit results to 20
        return queryset.distinct()[:20]


logger = logging.getLogger(__name__)
User = get_user_model()


class DirectMessageViewSet(viewsets.ViewSet):
    permission_classes = [IsAuthenticated]

    def list(self, request):
        """List all direct messages for the logged-in user."""
        try:
            current_user = request.user
            messages = DirectMessage.objects.filter(
                Q(sender=current_user) | Q(recipient=current_user),
                sender__is_active=True,
                recipient__is_active=True,
            ).select_related("sender", "recipient").order_by("-created_at")

            serializer = DirectMessageSerializer(messages, many=True, context={"request": request})
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def retrieve(self, request, pk=None):
        """Retrieve all messages between the logged-in user and another user."""
        try:
            current_user = request.user
            other_user_id = int(pk)
            other_user = User.objects.get(id=other_user_id, is_active=True)

            messages = DirectMessage.objects.filter(
                sender__in=[current_user, other_user],
                recipient__in=[current_user, other_user],
                sender__is_active=True,
                recipient__is_active=True,
            ).select_related("sender", "recipient").order_by("created_at")

            serializer = DirectMessageSerializer(messages, many=True, context={"request": request})
            return Response(serializer.data, status=status.HTTP_200_OK)
        except User.DoesNotExist:
            return Response({"error": "User not found or inactive."}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

    def create(self, request):
        """Create a new direct message."""
        try:
            current_user = request.user
            recipient_id = request.data.get("recipient_id")
            if not recipient_id:
                return Response({"error": "Recipient ID is required"}, status=status.HTTP_400_BAD_REQUEST)

            recipient = User.objects.get(id=recipient_id, is_active=True)

            serializer = CreateDirectMessageSerializer(
                data=request.data,
                context={"request": request, "recipient": recipient},
            )
            serializer.is_valid(raise_exception=True)
            message = serializer.save()

            response_serializer = DirectMessageSerializer(message, context={"request": request})
            return Response(response_serializer.data, status=status.HTTP_201_CREATED)
        except User.DoesNotExist:
            return Response({"error": "Recipient not found or inactive"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'])
    def send(self, request, pk=None):
        """Optional: send DM via /direct-messages/<recipient_id>/send/"""
        try:
            current_user = request.user
            recipient = User.objects.get(id=pk, is_active=True)

            serializer = CreateDirectMessageSerializer(
                data=request.data,
                context={"request": request, "recipient": recipient},
            )
            serializer.is_valid(raise_exception=True)
            message = serializer.save()

            response_serializer = DirectMessageSerializer(message, context={"request": request})
            return Response(response_serializer.data, status=status.HTTP_201_CREATED)
        except User.DoesNotExist:
            return Response({"error": "Recipient not found or inactive"}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
