from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, View
from django.urls import reverse_lazy, reverse
from django.http import HttpResponse, Http404, FileResponse
from django.db.models import Q, Count
from django.utils import timezone
from django.core.paginator import Paginator
import csv
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from .models import JobPosting, Application
from .forms import JobPostingForm, ApplicationForm, ApplicationNotesForm, JobSearchForm


class HomeView(View):
    """Home view that redirects users based on their role"""
    
    def get(self, request):
        if request.user.is_authenticated:
            if request.user.is_admin or request.user.is_stakeholder:
                return redirect('jobs:dashboard')
            else:
                return redirect('jobs:job_list')
        else:
            return redirect('jobs:job_list')


class JobListView(ListView):
    """Public job listings view"""
    model = JobPosting
    template_name = 'jobs/job_list.html'
    context_object_name = 'jobs'
    paginate_by = 12
    
    def get_queryset(self):
        queryset = JobPosting.objects.filter(
            status='published',
            application_deadline__gte=timezone.now().date()
        ).select_related('posted_by')
        
        # Search functionality
        form = JobSearchForm(self.request.GET)
        if form.is_valid():
            search = form.cleaned_data.get('search')
            employment_type = form.cleaned_data.get('employment_type')
            experience_level = form.cleaned_data.get('experience_level')
            location = form.cleaned_data.get('location')
            
            if search:
                queryset = queryset.filter(
                    Q(title__icontains=search) |
                    Q(description__icontains=search) |
                    Q(location__icontains=search)
                )
            
            if employment_type:
                queryset = queryset.filter(employment_type=employment_type)
            
            if experience_level:
                queryset = queryset.filter(experience_level=experience_level)
            
            if location:
                queryset = queryset.filter(location__icontains=location)
        
        return queryset.order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_form'] = JobSearchForm(self.request.GET)
        context['total_jobs'] = self.get_queryset().count()
        return context


class JobDetailView(DetailView):
    """Job detail view with application form"""
    model = JobPosting
    template_name = 'jobs/job_detail.html'
    context_object_name = 'job'
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['can_apply'] = self.object.is_active and self.request.user.is_authenticated
        if self.request.user.is_authenticated:
            # Check if user already applied
            context['already_applied'] = Application.objects.filter(
                job=self.object, 
                user=self.request.user
            ).exists()
        else:
            context['already_applied'] = False
        return context


class ApplicationCreateView(LoginRequiredMixin, CreateView):
    """Create job application view - requires authentication"""
    model = Application
    form_class = ApplicationForm
    template_name = 'jobs/apply.html'
    
    def dispatch(self, request, *args, **kwargs):
        self.job = get_object_or_404(JobPosting, pk=kwargs['pk'])
        if not self.job.is_active:
            messages.error(request, 'This job posting is no longer accepting applications.')
            return redirect('jobs:job_detail', pk=self.job.pk)
        
        # Check if user already applied
        if Application.objects.filter(job=self.job, user=request.user).exists():
            messages.warning(request, 'You have already applied for this position.')
            return redirect('jobs:job_detail', pk=self.job.pk)
        
        return super().dispatch(request, *args, **kwargs)
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['job'] = self.job
        kwargs['user'] = self.request.user
        return kwargs
    
    def form_valid(self, form):
        form.instance.job = self.job
        form.instance.user = self.request.user
        response = super().form_valid(form)
        
        # Send acknowledgment email
        self.send_acknowledgment_email(form.instance)
        
        messages.success(self.request, 'Your application has been submitted successfully! You will receive a confirmation email shortly.')
        return response
    
    def send_acknowledgment_email(self, application):
        """Send acknowledgment email to applicant"""
        from django.core.mail import send_mail
        from django.conf import settings
        
        subject = f'Application Received - {application.job.title}'
        message = f"""
Dear {application.applicant_name},

Thank you for your application for the position of {application.job.title}.

We have successfully received your application and it is now being reviewed by our team. 

If you are shortlisted, you will be contacted by either ICTAZ or the respective stakeholder organization.

Application Details:
- Position: {application.job.title}
- Company: {application.job.posted_by.organization or 'ICTAZ Partner'}
- Location: {application.job.location}
- Submitted: {application.submitted_at.strftime('%B %d, %Y at %I:%M %p')}

Best regards,
ICTAZ Jobs Portal Team
        """
        
        try:
            send_mail(
                subject,
                message,
                settings.DEFAULT_FROM_EMAIL,
                [application.applicant_email],
                fail_silently=True,
            )
        except Exception:
            # Email sending failed, but don't break the application process
            pass
    
    def get_success_url(self):
        return reverse('jobs:job_detail', kwargs={'pk': self.job.pk})
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['job'] = self.job
        return context


class MyApplicationsView(LoginRequiredMixin, ListView):
    """User's applications view"""
    model = Application
    template_name = 'jobs/my_applications.html'
    context_object_name = 'applications'
    paginate_by = 10
    
    def get_queryset(self):
        return Application.objects.filter(
            user=self.request.user
        ).select_related('job').order_by('-submitted_at')


class ApplicationDetailView(DetailView):
    """Application detail view"""
    model = Application
    template_name = 'jobs/application_detail.html'
    context_object_name = 'application'
    
    def get_object(self):
        obj = super().get_object()
        user = self.request.user
        
        # Check permissions
        if not user.is_authenticated:
            raise Http404
        
        # Users can only view their own applications
        # Admins and stakeholders can view applications for their jobs
        if (obj.user == user or 
            user.is_admin or 
            (user.is_stakeholder and obj.job.posted_by == user)):
            return obj
        
        raise Http404


class DashboardView(LoginRequiredMixin, UserPassesTestMixin, ListView):
    """Dashboard for admins and stakeholders"""
    template_name = 'jobs/dashboard.html'
    context_object_name = 'jobs'
    paginate_by = 10
    
    def test_func(self):
        return self.request.user.is_admin or self.request.user.is_stakeholder or self.request.user.is_superuser
    
    def get_queryset(self):
        user = self.request.user
        if user.is_admin or user.is_superuser:
            return JobPosting.objects.all().select_related('posted_by').prefetch_related('applications').order_by('-created_at')
        else:  # stakeholder
            return JobPosting.objects.filter(posted_by=user).select_related('posted_by').prefetch_related('applications').order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        user = self.request.user
        
        if user.is_admin or user.is_superuser:
            context['total_jobs'] = JobPosting.objects.count()
            context['total_applications'] = Application.objects.count()
            context['active_jobs'] = JobPosting.objects.filter(
                status='published',
                application_deadline__gte=timezone.now().date()
            ).count()
        else:
            context['total_jobs'] = self.get_queryset().count()
            context['total_applications'] = Application.objects.filter(
                job__posted_by=user
            ).count()
            context['active_jobs'] = self.get_queryset().filter(
                status='published',
                application_deadline__gte=timezone.now().date()
            ).count()
        
        return context


class JobCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
    """Create job posting view"""
    model = JobPosting
    form_class = JobPostingForm
    template_name = 'jobs/job_form.html'
    success_url = reverse_lazy('jobs:dashboard')
    
    def test_func(self):
        return self.request.user.is_admin
    
    def form_valid(self, form):
        form.instance.posted_by = self.request.user
        messages.success(self.request, 'Job posting created successfully!')
        return super().form_valid(form)


class JobUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    """Update job posting view"""
    model = JobPosting
    form_class = JobPostingForm
    template_name = 'jobs/job_form.html'
    success_url = reverse_lazy('jobs:dashboard')
    
    def test_func(self):
        job = self.get_object()
        user = self.request.user
        return user.is_admin
    
    def form_valid(self, form):
        messages.success(self.request, 'Job posting updated successfully!')
        return super().form_valid(form)


class JobDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    """Delete job posting view"""
    model = JobPosting
    template_name = 'jobs/job_confirm_delete.html'
    success_url = reverse_lazy('jobs:dashboard')
    
    def test_func(self):
        job = self.get_object()
        user = self.request.user
        return user.is_admin
    
    def delete(self, request, *args, **kwargs):
        messages.success(request, 'Job posting deleted successfully!')
        return super().delete(request, *args, **kwargs)


class JobApplicationsView(LoginRequiredMixin, UserPassesTestMixin, ListView):
    """View applications for a specific job"""
    model = Application
    template_name = 'jobs/job_applications.html'
    context_object_name = 'applications'
    paginate_by = 20
    
    def dispatch(self, request, *args, **kwargs):
        self.job = get_object_or_404(JobPosting, pk=kwargs['pk'])
        return super().dispatch(request, *args, **kwargs)
    
    def test_func(self):
        user = self.request.user
        return user.is_admin or (user.is_stakeholder and self.job.posted_by == user)
    
    def get_queryset(self):
        return Application.objects.filter(job=self.job).order_by('-submitted_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['job'] = self.job
        return context


class DownloadResumeView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    """Secure resume download view"""
    model = Application
    
    def test_func(self):
        application = self.get_object()
        user = self.request.user
        return (user.is_admin or 
                (user.is_stakeholder and application.job.posted_by == user) or
                application.user == user)
    
    def get(self, request, *args, **kwargs):
        application = self.get_object()
        if application.resume:
            response = FileResponse(
                application.resume.open(),
                as_attachment=True,
                filename=f"{application.applicant_name}_resume.pdf"
            )
            return response
        raise Http404


class DownloadDocumentsView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    """Secure additional documents download view"""
    model = Application
    
    def test_func(self):
        application = self.get_object()
        user = self.request.user
        return (user.is_admin or 
                (user.is_stakeholder and application.job.posted_by == user) or
                application.user == user)
    
    def get(self, request, *args, **kwargs):
        application = self.get_object()
        if application.additional_documents:
            response = FileResponse(
                application.additional_documents.open(),
                as_attachment=True,
                filename=f"{application.applicant_name}_documents.pdf"
            )
            return response
        raise Http404


class ExportApplicationsView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
    """Export applications to CSV"""
    model = JobPosting
    
    def test_func(self):
        job = self.get_object()
        user = self.request.user
        return user.is_admin or (user.is_stakeholder and job.posted_by == user)
    
    def get(self, request, *args, **kwargs):
        job = self.get_object()
        applications = Application.objects.filter(job=job).order_by('-submitted_at')
        
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename="{job.title}_applications.csv"'
        
        writer = csv.writer(response)
        writer.writerow([
            'Applicant Name', 'Email', 'Phone', 'Membership Number',
            'Submitted At', 'Is Member'
        ])
        
        for app in applications:
            writer.writerow([
                app.applicant_name,
                app.applicant_email,
                app.applicant_phone,
                app.membership_number or 'N/A',
                app.submitted_at.strftime('%Y-%m-%d %H:%M'),
                'Yes' if app.is_member else 'No'
            ])
        
        return response


class ApplicationUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    """Update application view for regular users"""
    model = Application
    template_name = 'jobs/application_update.html'
    fields = ['cover_letter', 'resume', 'ictaz_certificate', 'additional_documents']
    
    def test_func(self):
        application = self.get_object()
        return self.request.user == application.user
    
    def get_success_url(self):
        return reverse('jobs:my_applications')
    
    def form_valid(self, form):
        # Preserve the original personal information
        application = form.save(commit=False)
        original = self.get_object()
        application.applicant_name = original.applicant_name
        application.applicant_email = original.applicant_email
        application.applicant_phone = original.applicant_phone
        application.membership_number = original.membership_number
        application.save()
        
        messages.success(self.request, 'Application updated successfully!')
        return super().form_valid(form)
