from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponseForbidden
from django.urls import reverse
from django.utils import timezone
from django.db.models import Sum, Count
from .models import LeaveRequest
from .forms import LeaveRequestForm
from notifications.utils import (
    notify_leave_submission, notify_leave_hr_approval, notify_leave_hr_rejection,
    notify_leave_registrar_approval, notify_leave_registrar_rejection, notify_leave_upcoming
)

import json
from django.http import JsonResponse

@login_required
def request_leave(request):
    """Handle leave request creation for employees."""
    # Only Registrar cannot submit leave requests
    if request.user.employee.role == 'REG':
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'error': 'Registrar cannot submit leave requests.'
            }, status=403)
        messages.error(request, 'Registrar cannot submit leave requests.')
        return redirect('home')

    if request.method == 'POST':
        form = LeaveRequestForm(request.POST)
        if form.is_valid():
            leave_request = form.save(commit=False)
            leave_request.employee = request.user.employee
            
            # Calculate leave days
            days = (leave_request.end_date - leave_request.start_date).days + 1
            
            # For annual leave, check and update available days
            if leave_request.leave_type == 'ANN':
                available_days = (leave_request.employee.annual_leave_days + 
                                leave_request.employee.accumulated_leave_days)
                
                if days <= available_days:
                    leave_request.save()
                    # Send notification email
                    notify_leave_submission(leave_request, request=request)
                    success_message = f'Leave request for {days} days submitted successfully.'
                    
                    # Handle AJAX requests
                    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                        return JsonResponse({
                            'success': True,
                            'message': success_message,
                            'redirect': '/'
                        })
                    
                    messages.success(request, success_message)
                    return redirect('home')
                else:
                    error_message = f'You only have {available_days} leave days available.'
                    
                    # Handle AJAX requests
                    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                        return JsonResponse({
                            'success': False,
                            'error': error_message
                        }, status=400)
                    
                    messages.error(request, error_message)
            else:
                # For other leave types, check role
                if request.user.employee.role == 'HR':
                    # Auto-approve HR requests
                    leave_request.status = 'HR_APPROVED'
                    leave_request.hr_approved_by = request.user.employee
                    leave_request.hr_approved_at = timezone.now()
                    leave_request.hr_comment = 'Auto-approved (HR request)'
                
                leave_request.save()
                # Send notification email
                notify_leave_submission(leave_request)
                success_message = 'Leave request submitted successfully.'
                
                # Handle AJAX requests
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'success': True,
                        'message': success_message,
                        'redirect': '/'
                    })
                
                messages.success(request, success_message)
                return redirect('home')
    else:
        form = LeaveRequestForm()

    return render(request, 'leave/request_form.html', {'form': form})

@login_required
def approve_leave(request):
    """Handle leave approvals for HR and Registrar."""
    employee = request.user.employee
    
    # Only HR and Registrar can approve requests
    if employee.role not in ['HR', 'REG']:
        messages.error(request, 'You do not have permission to approve requests.')
        return redirect('home')

    if employee.role == 'HR':
        # HR sees pending requests
        requests = LeaveRequest.objects.filter(status='PENDING')
        title = 'Pending Leave Requests'
    else:
        # Registrar sees HR approved requests
        requests = LeaveRequest.objects.filter(status='HR_APPROVED')
        title = 'HR Approved Leave Requests'

    if request.method == 'POST':
        request_id = request.POST.get('request_id')
        action = request.POST.get('action')
        comment = request.POST.get('comment', '')
        
        if request_id and action:
            leave_request = get_object_or_404(LeaveRequest, id=request_id)
            
            if employee.role == 'HR':
                if action == 'approve':
                    leave_request.status = 'HR_APPROVED'
                    leave_request.hr_approved_by = employee
                    leave_request.hr_approved_at = timezone.now()
                    leave_request.hr_comment = comment
                    messages.success(request, 'Request approved and sent to Registrar.')
                    # Send notification email
                    notify_leave_hr_approval(leave_request, request=request)
                else:
                    leave_request.status = 'HR_REJECTED'
                    leave_request.hr_comment = comment
                    messages.warning(request, 'Request rejected.')
                    # Send notification email
                    notify_leave_hr_rejection(leave_request, request=request)
            
            elif employee.role == 'REG':
                if action == 'approve':
                    leave_request.status = 'REG_APPROVED'
                    leave_request.registrar_approved_by = employee
                    leave_request.registrar_approved_at = timezone.now()
                    leave_request.registrar_comment = comment
                    
                    # For annual leave, deduct days when finally approved
                    if leave_request.leave_type == 'ANN':
                        days_taken = (leave_request.end_date - leave_request.start_date).days + 1
                        employee = leave_request.employee
                        
                        # First use annual leave days
                        if days_taken <= employee.annual_leave_days:
                            employee.annual_leave_days -= days_taken
                        else:
                            # Then use accumulated days if needed
                            remaining = days_taken - employee.annual_leave_days
                            employee.accumulated_leave_days -= remaining
                            employee.annual_leave_days = 0
                        
                        employee.save()
                    messages.success(request, 'Leave request approved.')
                    # Send notification email
                    notify_leave_registrar_approval(leave_request, request=request)
                    
                    # Schedule upcoming leave reminder for 1 day before leave starts
                    # This would typically be handled by a task scheduler like Celery
                    # For now, we'll just send it immediately for demonstration purposes
                    if (leave_request.start_date - timezone.now().date()).days <= 1:
                        notify_leave_upcoming(leave_request, request=request)
                else:
                    leave_request.status = 'REG_REJECTED'
                    leave_request.registrar_comment = comment
                    messages.warning(request, 'Request rejected.')
                    # Send notification email
                    notify_leave_registrar_rejection(leave_request, request=request)
            
            leave_request.save()
            return redirect(reverse('leave:approve'))

    context = {
        'requests': requests,
        'role': employee.role,
        'title': title
    }
    return render(request, 'leave/approvals.html', context)

@login_required
def view_request(request, request_id):
    leave_request = get_object_or_404(LeaveRequest, id=request_id)
    
    # Check if the user has permission to view this request
    if request.user.employee != leave_request.employee and request.user.employee.role not in ['HR', 'REG']:
        return HttpResponseForbidden()
    
    context = {
        'title': 'Leave Request Details',
        'request': leave_request,
        'employee': leave_request.employee,
        'can_edit': request.user.employee == leave_request.employee and leave_request.status in ['REJECTED', 'PENDING'],
        'is_hr': request.user.employee.role == 'HR',
        'is_registrar': request.user.employee.role == 'REG'
    }
    
    return render(request, 'leave/view_request.html', context)


@login_required
def my_requests(request):
    """View for users to see their own leave requests"""
    # Get all leave requests for the current user
    requests = LeaveRequest.objects.filter(
        employee=request.user.employee
    ).select_related(
        'employee__user',
        'hr_approved_by__user',
        'registrar_approved_by__user'
    ).order_by('-start_date', '-created_at')
    
    # Calculate statistics
    stats = {
        'total_requests': requests.count(),
        'pending_requests': requests.filter(status='PENDING').count(),
        'hr_approved_requests': requests.filter(status='HR_APPROVED').count(),
        'reg_approved_requests': requests.filter(status='REG_APPROVED').count(),
        'rejected_requests': requests.filter(status__in=['HR_REJECTED', 'REG_REJECTED']).count(),
        'total_days': sum(request.days for request in requests.filter(status='REG_APPROVED'))
    }
    
    context = {
        'title': 'My Leave Requests',
        'requests': requests,
        'stats': stats
    }
    return render(request, 'leave/my_requests.html', context)


@login_required
def edit_request(request, request_id):
    """Allow employees to edit their rejected or pending leave requests."""
    leave_request = get_object_or_404(LeaveRequest, id=request_id)
    
    # Check if the user has permission to edit this request
    if request.user.employee != leave_request.employee:
        messages.error(request, 'You do not have permission to edit this request.')
        return redirect('leave:my_requests')
    
    # Check if the request can be edited (only pending or rejected requests)
    if leave_request.status not in ['PENDING', 'HR_REJECTED', 'REG_REJECTED']:
        messages.error(request, 'This request cannot be edited.')
        return redirect('leave:my_requests')
    
    if request.method == 'POST':
        form = LeaveRequestForm(request.POST, instance=leave_request)
        if form.is_valid():
            # Reset status to pending if it was rejected
            if leave_request.status in ['HR_REJECTED', 'REG_REJECTED']:
                leave_request.status = 'PENDING'
                leave_request.hr_approved_by = None
                leave_request.hr_approved_at = None
                leave_request.hr_comment = ''
                leave_request.registrar_approved_by = None
                leave_request.registrar_approved_at = None
                leave_request.registrar_comment = ''
            
            leave_request = form.save()
            
            # Send notification email for resubmission if it was rejected before
            if leave_request.status == 'PENDING' and form.initial.get('status') in ['HR_REJECTED', 'REG_REJECTED']:
                from notifications.utils import notify_leave_submission
                notify_leave_submission(leave_request, request=request)
                messages.success(request, 'Leave request updated successfully and resubmitted.')
            else:
                messages.success(request, 'Leave request updated successfully.')
                
            return redirect('leave:my_requests')
    else:
        form = LeaveRequestForm(instance=leave_request)
    
    context = {
        'title': 'Edit Leave Request',
        'form': form,
        'leave_request': leave_request
    }
    return render(request, 'leave/edit_request.html', context)


@login_required
def delete_request(request, request_id):
    """Allow employees to delete their rejected or pending leave requests."""
    leave_request = get_object_or_404(LeaveRequest, id=request_id)
    
    # Check if the user has permission to delete this request
    if request.user.employee != leave_request.employee:
        messages.error(request, 'You do not have permission to delete this request.')
        return redirect('leave:my_requests')
    
    # Check if the request can be deleted (only pending or rejected requests)
    if leave_request.status not in ['PENDING', 'HR_REJECTED', 'REG_REJECTED']:
        messages.error(request, 'This request cannot be deleted.')
        return redirect('leave:view_request', request_id=leave_request.id)
    
    # Handle both GET and POST requests for deletion
    leave_request.delete()
    messages.success(request, 'Leave request deleted successfully.')
    return redirect('leave:my_requests')
