from django.db import models
from rest_framework import status, permissions
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from .models import Lead, LeadAttachment, LeadActivity, Meeting
from .serializers import (
    LeadListSerializer, LeadDetailSerializer, LeadCreateSerializer,
    LeadAttachmentSerializer, LeadActivitySerializer, MeetingSerializer
)
from apps.users.permissions import CanManageLeads, IsManagement
from apps.users.views import api_response
from apps.notifications.views import create_notification


class LeadListCreateView(APIView):
    def get_permissions(self):
        if self.request.method == 'POST':
            return [permissions.IsAuthenticated(), CanManageLeads()]
        return [permissions.IsAuthenticated()]

    def get(self, request):
        user = request.user

        # Role-based filtering
        if user.is_management or user.is_superuser:
            leads = Lead.objects.all()
        elif user.has_role('BD'):
            leads = Lead.objects.filter(created_by=user)
        elif user.has_role('Member'):
            leads = Lead.objects.none()
        else:
            leads = Lead.objects.all()

        # Query params filtering
        status_filter = request.query_params.get('status')
        service = request.query_params.get('service_type')
        priority = request.query_params.get('priority')
        search = request.query_params.get('search')

        if status_filter:
            leads = leads.filter(status=status_filter)
        if service:
            leads = leads.filter(service_type=service)
        if priority:
            leads = leads.filter(priority=priority)
        if search:
            leads = leads.filter(
                models.Q(title__icontains=search) |
                models.Q(client_name__icontains=search)
            )

        serializer = LeadListSerializer(leads, many=True)
        return api_response(data=serializer.data)

    def post(self, request):
        serializer = LeadCreateSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            lead = serializer.save()
            # Log activity
            LeadActivity.objects.create(
                lead=lead,
                actor=request.user,
                action='Lead Created',
                details=f'Lead "{lead.title}" created for {lead.client_name}'
            )
            # Notify assignee if not the creator
            if lead.assigned_to and lead.assigned_to != request.user:
                create_notification(
                    user=lead.assigned_to,
                    notif_type='lead_created',
                    title='New Lead Assigned',
                    message=f'New lead "{lead.title}" for {lead.client_name} assigned to you.',
                    link=f'/leads'
                )
            
            return api_response(
                data=LeadDetailSerializer(lead).data,
                message='Lead created successfully',
                status_code=status.HTTP_201_CREATED
            )
        
        # DEBUG LOGGING
        print(f"DEBUG: Lead creation failed! Errors: {serializer.errors}")
        
        return api_response(
            errors=serializer.errors,
            message='Lead creation failed',
            status_code=status.HTTP_400_BAD_REQUEST
        )


class LeadDetailView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get_object(self, pk, user):
        try:
            lead = Lead.objects.get(pk=pk)
            # Management and Superusers can see all
            if user.is_management or user.is_superuser:
                return lead
            # BD can only see own leads
            if user.has_role('BD') and lead.created_by != user:
                return None
            if user.has_role('Member'):
                return None
            return lead
        except Lead.DoesNotExist:
            return None

    def get(self, request, pk):
        lead = self.get_object(pk, request.user)
        if not lead:
            return api_response(message='Lead not found', status_code=status.HTTP_404_NOT_FOUND)
        serializer = LeadDetailSerializer(lead)
        return api_response(data=serializer.data)

    def patch(self, request, pk):
        lead = self.get_object(pk, request.user)
        if not lead:
            return api_response(message='Lead not found', status_code=status.HTTP_404_NOT_FOUND)

        old_status = lead.status
        serializer = LeadDetailSerializer(lead, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            # Log status change
            if 'status' in request.data and request.data['status'] != old_status:
                LeadActivity.objects.create(
                    lead=lead,
                    actor=request.user,
                    action='Status Changed',
                    details=f'Status changed from {old_status} to {lead.status}'
                )
            return api_response(data=serializer.data, message='Lead updated')
        return api_response(
            errors=serializer.errors,
            message='Update failed',
            status_code=status.HTTP_400_BAD_REQUEST
        )


class LeadAttachmentView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request, lead_pk):
        try:
            lead = Lead.objects.get(pk=lead_pk)
        except Lead.DoesNotExist:
            return api_response(message='Lead not found', status_code=status.HTTP_404_NOT_FOUND)

        file = request.FILES.get('file')
        if not file:
            return api_response(message='No file provided', status_code=status.HTTP_400_BAD_REQUEST)

        # Validate file type and size
        allowed_extensions = ['pdf', 'docx', 'doc', 'png', 'jpg', 'jpeg', 'xlsx', 'xls']
        ext = file.name.split('.')[-1].lower()
        if ext not in allowed_extensions:
            return api_response(
                message=f'File type .{ext} not allowed',
                status_code=status.HTTP_400_BAD_REQUEST
            )
        if file.size > 10 * 1024 * 1024:  # 10MB
            return api_response(
                message='File size exceeds 10MB limit',
                status_code=status.HTTP_400_BAD_REQUEST
            )

        attachment = LeadAttachment.objects.create(
            lead=lead, file=file, uploaded_by=request.user
        )
        LeadActivity.objects.create(
            lead=lead,
            actor=request.user,
            action='File Uploaded',
            details=f'Uploaded {attachment.file_name}'
        )
        return api_response(
            data=LeadAttachmentSerializer(attachment).data,
            message='File uploaded successfully',
            status_code=status.HTTP_201_CREATED
        )


class LeadPipelineView(APIView):
    """Kanban-style pipeline data grouped by status"""
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.is_management or user.is_superuser:
            leads = Lead.objects.all()
        elif user.has_role('BD'):
            leads = Lead.objects.filter(created_by=user)
        elif user.has_role('Member'):
            return api_response(data={})
        else:
            leads = Lead.objects.all()

        pipeline = {}
        for status_choice in Lead.STATUS_CHOICES:
            key = status_choice[0]
            stage_leads = leads.filter(status=key)
            pipeline[key] = {
                'label': status_choice[1],
                'count': stage_leads.count(),
                'leads': LeadListSerializer(stage_leads, many=True).data
            }
        return api_response(data=pipeline)


class MeetingListCreateView(APIView):
    permission_classes = [permissions.IsAuthenticated, IsManagement]

    def get(self, request):
        lead_id = request.query_params.get('lead')
        project_id = request.query_params.get('project')

        meetings = Meeting.objects.all()
        if lead_id:
            meetings = meetings.filter(lead_id=lead_id)
        if project_id:
            meetings = meetings.filter(project_id=project_id)

        serializer = MeetingSerializer(meetings, many=True)
        return api_response(data=serializer.data)

    def post(self, request):
        serializer = MeetingSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            meeting = serializer.save()

            # Log activity if linked to a lead
            if meeting.lead:
                LeadActivity.objects.create(
                    lead=meeting.lead,
                    actor=request.user,
                    action=f'{meeting.get_meeting_type_display()} Created',
                    details=f'{meeting.title} scheduled for {meeting.date}'
                )

            return api_response(
                data=MeetingSerializer(meeting).data,
                message='Meeting created successfully',
                status_code=status.HTTP_201_CREATED
            )
        return api_response(
            errors=serializer.errors,
            message='Meeting creation failed',
            status_code=status.HTTP_400_BAD_REQUEST
        )


class MeetingDetailView(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, pk):
        try:
            meeting = Meeting.objects.get(pk=pk)
        except Meeting.DoesNotExist:
            return api_response(message='Meeting not found', status_code=status.HTTP_404_NOT_FOUND)
        return api_response(data=MeetingSerializer(meeting).data)

    def patch(self, request, pk):
        try:
            meeting = Meeting.objects.get(pk=pk)
        except Meeting.DoesNotExist:
            return api_response(message='Meeting not found', status_code=status.HTTP_404_NOT_FOUND)

        serializer = MeetingSerializer(meeting, data=request.data, partial=True, context={'request': request})
        if serializer.is_valid():
            meeting = serializer.save()

            # If marked completed, update lead status
            if meeting.is_completed and meeting.lead:
                if meeting.meeting_type == 'internal' and meeting.lead.status == 'Requirements_Submitted':
                    meeting.lead.status = 'Internal_Review'
                    meeting.lead.save()
                elif meeting.meeting_type == 'client' and meeting.lead.status in ('Internal_Review', 'Client_Meeting'):
                    if meeting.outcome == 'proceed':
                        meeting.lead.status = 'Costing_In_Progress'
                        meeting.lead.save()
                    elif meeting.outcome == 'drop':
                        meeting.lead.status = 'Rejected'
                        meeting.lead.save()

                LeadActivity.objects.create(
                    lead=meeting.lead,
                    actor=request.user,
                    action=f'{meeting.get_meeting_type_display()} Completed',
                    details=f'Outcome: {meeting.get_outcome_display()}'
                )

            return api_response(data=MeetingSerializer(meeting).data, message='Meeting updated')
        return api_response(errors=serializer.errors, message='Update failed', status_code=status.HTTP_400_BAD_REQUEST)
