from rest_framework import viewsets, permissions, status
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import Q
from applications.models import Application
from applications.api_serializers import ApplicationSerializer, ApplicationCreateSerializer, UserApplicationSerializer
from rest_framework.permissions import IsAuthenticated, AllowAny


class ApplicationViewSet(viewsets.ModelViewSet):
    serializer_class = ApplicationSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """
        - List view: only admins can see all applications
        - Detail actions (retrieve, update, delete, withdraw): users can access their own, admins can access all
        """
        user = self.request.user
        
        # Admins always see all applications
        if user.is_staff and user.is_superuser:
            return Application.objects.all()
        
        # For detail actions, allow users to access their own applications
        if self.action in ['retrieve', 'update', 'partial_update', 'destroy', 'update_status', 'withdraw']:
            return Application.objects.filter(user=user)
        
        # For list action, return empty (admin-only)
        return Application.objects.none()
    
    def get_serializer_class(self):
        """Use different serializers for different actions"""
        if self.action == 'create':
            return ApplicationCreateSerializer
        return ApplicationSerializer
    
    def create(self, request, *args, **kwargs):
        """Apply for a job"""
        serializer = self.get_serializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        
        try:
            application = serializer.save()
            output_serializer = ApplicationSerializer(application)
            return Response(output_serializer.data, status=status.HTTP_201_CREATED)
        except Exception as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
    
    @action(detail=False, methods=['get'])
    def my_applications(self, request):
        """Get current user's applications"""
        applications = Application.objects.filter(user=request.user)
        serializer = self.get_serializer(applications, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def job_applications(self, request):
        """Get applications for a specific job (employers see their jobs, admins see all)"""
        job_id = request.query_params.get('job_id')
        
        if not job_id:
            return Response(
                {'error': 'job_id parameter is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Admins can see all applications for any job
        if request.user.is_staff and request.user.is_superuser:
            applications = Application.objects.filter(job_id=job_id)
            serializer = self.get_serializer(applications, many=True)
            return Response(serializer.data)
        
        # Employers can see applications for their own jobs
        try:
            if request.user.profile.role == 'employer':
                applications = Application.objects.filter(job_id=job_id, job__employer=request.user)
                serializer = self.get_serializer(applications, many=True)
                return Response(serializer.data)
        except:
            pass
        
        return Response(
            {'error': 'Only employers and admins can view job applications'},
            status=status.HTTP_403_FORBIDDEN
        )
    
    @action(detail=True, methods=['patch'])
    def update_status(self, request, pk=None):
        """Update application status (employer only)"""
        application = self.get_object()
        
        # Check if user is the employer of this job
        if application.job.employer != request.user:
            return Response(
                {'error': 'You can only update applications for your jobs'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        new_status = request.data.get('status')
        
        if new_status not in dict(Application.STATUS_CHOICES):
            return Response(
                {'error': f'Invalid status. Choose from: {", ".join(dict(Application.STATUS_CHOICES).keys())}'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        application.status = new_status
        application.save()
        serializer = self.get_serializer(application)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def withdraw(self, request, pk=None):
        """Withdraw application (candidate only)"""
        application = self.get_object()
        
        # Check if user is the applicant
        if application.user != request.user:
            return Response(
                {'error': 'You can only withdraw your own applications'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        if application.status == 'withdrawn':
            return Response(
                {'error': 'Application already withdrawn'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        application.status = 'withdrawn'
        application.save()
        serializer = self.get_serializer(application)
        return Response(serializer.data)
