from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404
from django.db.models import Q

from .models import Senior
from .serializers import SeniorSerializer, SeniorDetailSerializer
from calls.tasks import initiate_call_task


class SeniorViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing senior profiles.
    
    Provides CRUD operations for senior profiles and additional actions
    for initiating calls and retrieving conversation history.
    """
    
    permission_classes = []  # Remove authentication requirement for testing
    
    def get_queryset(self):
        """Return all active seniors for testing"""
        return Senior.objects.filter(is_active=True)
    
    def get_serializer_class(self):
        """Return appropriate serializer based on action"""
        if self.action == 'retrieve':
            return SeniorDetailSerializer
        return SeniorSerializer
    
    def perform_create(self, serializer):
        """Create senior with a default test user"""
        from django.contrib.auth.models import User
        test_user, created = User.objects.get_or_create(
            username='testuser',
            defaults={'email': 'test@example.com'}
        )
        serializer.save(caregiver=test_user)
    
    @action(detail=True, methods=['post'])
    def initiate_call(self, request, pk=None):
        """
        Initiate a call to the senior.
        
        POST /api/seniors/{id}/initiate_call/
        Body: {
            "purpose": "general_checkin",
            "prompt_id": 1,  // optional
            "assistant_id": 1  // optional, falls back to user preference
        }
        """
        senior = self.get_object()
        
        # Check if there's already an active call
        active_call = senior.calls.filter(
            twilio_status__in=['initiated', 'ringing', 'in-progress']
        ).first()
        
        if active_call:
            return Response(
                {'error': 'There is already an active call to this senior'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Get call purpose and prompt_id from request data
        call_purpose = request.data.get('purpose', 'general_checkin')
        prompt_id = request.data.get('prompt_id')
        assistant_id = request.data.get('assistant_id')
        
        # Validate prompt_id if provided
        if prompt_id:
            from calls.models import CallPrompt
            try:
                prompt = CallPrompt.objects.get(id=prompt_id, is_active=True)
            except CallPrompt.DoesNotExist:
                return Response(
                    {'error': f'Prompt with ID {prompt_id} not found or inactive'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # Get assistant_id from request or user preference
        if not assistant_id:
            # Try to get from user preference
            from calls.models import UserAssistantPreference
            try:
                preference = UserAssistantPreference.objects.get(user=senior.caregiver)
                assistant_id = preference.assistant.id
            except UserAssistantPreference.DoesNotExist:
                return Response(
                    {'error': 'No assistant selected. Please select an assistant first using /api/calls/set_user_preference/'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # Validate assistant_id
        from calls.models import VapiAssistant
        try:
            assistant = VapiAssistant.objects.get(id=assistant_id, is_active=True)
        except VapiAssistant.DoesNotExist:
            return Response(
                {'error': f'Assistant with ID {assistant_id} not found or inactive'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Initiate the call asynchronously with assistant_id
        task = initiate_call_task.delay(senior.id, call_purpose, senior.caregiver.id, prompt_id, assistant_id)
        
        # Get the most recent call for this senior (the one just created)
        # Note: The call is created synchronously in the task, so we need to wait a moment
        # or get it from the task result. For now, we'll return task_id and let frontend poll.
        return Response({
            'message': 'Call initiation started',
            'task_id': task.id,
            'senior_id': senior.id,
            'assistant': {'id': assistant.id, 'name': assistant.name},
            'senior': SeniorSerializer(senior).data
        }, status=status.HTTP_202_ACCEPTED)
    
    @action(detail=True, methods=['get'])
    def conversation_history(self, request, pk=None):
        """
        Get conversation history for the senior.
        
        GET /api/seniors/{id}/conversation_history/
        """
        senior = self.get_object()
        
        # Get query parameters
        limit = int(request.query_params.get('limit', 10))
        offset = int(request.query_params.get('offset', 0))
        
        # Get conversations with pagination
        conversations = senior.conversations.filter(
            call__status='completed'
        ).select_related('call').order_by('-created_at')[offset:offset + limit]
        
        # Serialize the data
        conversation_data = []
        for conv in conversations:
            conversation_data.append({
                'id': conv.id,
                'date': conv.created_at,
                'duration': conv.call.formatted_duration,
                'summary': conv.summary,
                'topics': conv.topics_discussed,
                'sentiment_score': conv.sentiment_score,
                'engagement_level': conv.engagement_level,
            })
        
        return Response({
            'conversations': conversation_data,
            'total_calls': senior.total_calls,
            'last_call_date': senior.last_call_date,
        })
    
    @action(detail=True, methods=['get'])
    def memories(self, request, pk=None):
        """
        Get memories for the senior.
        
        GET /api/seniors/{id}/memories/
        """
        senior = self.get_object()
        
        # Get query parameters
        memory_type = request.query_params.get('type')
        limit = int(request.query_params.get('limit', 20))
        
        # Filter memories
        memories_query = senior.memories.all()
        if memory_type:
            memories_query = memories_query.filter(memory_type=memory_type)
        
        memories = memories_query.order_by('-importance_score', '-created_at')[:limit]
        
        # Serialize the data
        memory_data = []
        for memory in memories:
            memory_data.append({
                'id': memory.id,
                'type': memory.memory_type,
                'title': memory.title,
                'content': memory.content,
                'importance_score': memory.importance_score,
                'tags': memory.tags,
                'times_referenced': memory.times_referenced,
                'created_at': memory.created_at,
            })
        
        return Response({
            'memories': memory_data,
            'total_memories': senior.memories.count(),
        })
    
    @action(detail=True, methods=['get'])
    def insights(self, request, pk=None):
        """
        Get insights for the senior.
        
        GET /api/seniors/{id}/insights/
        """
        senior = self.get_object()
        
        # Get query parameters
        insight_type = request.query_params.get('type')
        limit = int(request.query_params.get('limit', 10))
        
        # Filter insights
        insights_query = senior.insights.all()
        if insight_type:
            insights_query = insights_query.filter(insight_type=insight_type)
        
        insights = insights_query.order_by('-confidence_score', '-created_at')[:limit]
        
        # Serialize the data
        insight_data = []
        for insight in insights:
            insight_data.append({
                'id': insight.id,
                'type': insight.insight_type,
                'title': insight.title,
                'description': insight.description,
                'confidence_score': insight.confidence_score,
                'data': insight.data,
                'created_at': insight.created_at,
            })
        
        return Response({
            'insights': insight_data,
            'total_insights': senior.insights.count(),
        })
    
    @action(detail=False, methods=['get'])
    def search(self, request):
        """
        Search seniors by name or phone number.
        
        GET /api/seniors/search/?q=search_term
        """
        query = request.query_params.get('q', '')
        if not query:
            return Response({'error': 'Query parameter "q" is required'}, 
                          status=status.HTTP_400_BAD_REQUEST)
        
        seniors = self.get_queryset().filter(
            Q(name__icontains=query) | Q(phone_number__icontains=query)
        )
        
        serializer = self.get_serializer(seniors, many=True)
        return Response({
            'seniors': serializer.data,
            'count': seniors.count(),
        })