from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages, auth
from django.db.models import Count, Q, Sum
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from tasks.models import Task
from appointments.models import Appointment, Service, StaffMember, AppointmentNote
from users.models import User, Department
from django.utils import timezone
from datetime import timedelta


def is_staff_user(user):
    return user.is_authenticated and user.is_staff

def register(request):
    """Register a new user"""
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            auth.login(request, user)
            messages.success(request, 'Registration successful!')
            return redirect('home')
        else:
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f"{field}: {error}")
    else:
        form = UserCreationForm()
    
    return render(request, 'registration/register.html', {'form': form})

@login_required
def admin_dashboard(request):
    """Admin dashboard view with statistics and overview"""
    if not request.user.is_staff:
        return redirect('home')  # Redirect non-staff users to home
    
    # Calculate stats
    today = timezone.now().date()
    thirty_days_ago = today - timedelta(days=30)
    
    from appointments.models import Appointment, StaffMember, AppointmentNote
    from users.models import UserRole, Department
    
    # Check user permissions for actions
    if request.user.is_superuser:
        can_manage_users = True
        can_manage_roles = True
    else:
        can_manage_users = hasattr(request.user, 'role') and request.user.role and \
                         request.user.role.name in ['president', 'minister', 'director']
        can_manage_roles = hasattr(request.user, 'role') and request.user.role and \
                          request.user.role.name == 'president'
    
    # Get user role for display
    user_role = request.user.role.name if hasattr(request.user, 'role') and request.user.role else 'admin'
    
    # User statistics
    total_users = User.objects.count()
    active_users = User.objects.filter(is_active=True).count()
    
    # Department statistics
    department_count = Department.objects.count()
    
    # Task statistics
    from tasks.models import Task
    total_tasks = Task.objects.count()
    pending_task_count = Task.objects.filter(status__in=['todo', 'in_progress']).count()
    completed_tasks = Task.objects.filter(status='completed').count()
    
    # Appointment statistics
    stats = {
        'total_users': total_users,
        'active_user_count': active_users,
        'total_departments': department_count,
        'total_tasks': total_tasks,
        'pending_tasks': pending_task_count,
        'completed_tasks': completed_tasks,
        'total_appointments': Appointment.objects.count(),
        'pending_appointments': Appointment.objects.filter(status='pending').count(),
        'total_staff': StaffMember.objects.count(),
        'total_revenue': Appointment.objects.filter(
            status='completed',
            start_time__date__gte=thirty_days_ago
        ).aggregate(total=Sum('service__price'))['total'] or 0,
    }
    
    # Get upcoming appointments (next 7 days)
    upcoming_appointments = Appointment.objects.filter(
        start_time__date__gte=today,
        start_time__lte=today + timedelta(days=7),
        status__in=['pending', 'confirmed']
    ).order_by('start_time')[:5]
    
    # Get recent users
    recent_users = User.objects.order_by('-date_joined')[:5]
    
    # Get recent departments
    recent_departments = Department.objects.order_by('-id')[:5]
    
    # Get recent tasks
    recent_tasks = Task.objects.select_related('assigned_to', 'created_by').order_by('-created_at')[:5]
    
    # Generate recent activities
    recent_activities = []
    
    # Add recent users
    for user in recent_users:
        recent_activities.append({
            'title': f"New user registered: {user.get_full_name() or user.email}",
            'description': f"Role: {user.role.name if user.role else 'No Role'}",
            'timestamp': user.date_joined,
            'icon': 'fa-user-plus',
            'type': 'user',
            'link': reverse('users:user_detail', args=[user.id])
        })
    
    # Add recent departments
    for dept in recent_departments:
        recent_activities.append({
            'title': f"New department created: {dept.name}",
            'description': f"Parent: {dept.parent.name if dept.parent else 'None'}",
            'timestamp': timezone.now(),  # Note: Add created_at field to Department model for accurate timestamp
            'icon': 'fa-building',
            'type': 'department',
            'link': reverse('departments:department_detail', args=[dept.id])
        })
    
    # Add recent tasks
    for task in recent_tasks:
        recent_activities.append({
            'title': f"New task: {task.title}",
            'description': f"Status: {task.get_status_display()}, Priority: {task.get_priority_display()}",
            'timestamp': task.created_at,
            'icon': 'fa-tasks',
            'type': 'task',
            'link': reverse('tasks:task-detail', args=[task.id])
        })
    
    # Add recent appointments
    for appt in upcoming_appointments:
        recent_activities.append({
            'title': f"Upcoming appointment: {appt.service.name if appt.service else 'No Service'}",
            'description': f"With: {appt.staff_member.user.get_full_name() if appt.staff_member else 'No Staff'}",
            'timestamp': appt.start_time,
            'icon': 'fa-calendar-alt',
            'type': 'appointment',
            'link': reverse('appointments:appointment_detail', args=[appt.id])
        })
    
    # Sort activities by timestamp
    recent_activities.sort(key=lambda x: x['timestamp'], reverse=True)
    recent_activities = recent_activities[:10]  # Limit to 10 most recent
    
    context = {
        'stats': stats,
        'upcoming_appointments': upcoming_appointments,
        'recent_activities': recent_activities,
        'can_manage_users': can_manage_users,
        'can_manage_roles': can_manage_roles,
        'user_role': user_role,
        'total_users': total_users,
        'active_user_count': active_users,
        'department_count': department_count,
        'total_tasks': total_tasks,
        'pending_task_count': pending_task_count,
        'completed_tasks': completed_tasks,
        'recent_users': recent_users,
        'recent_departments': recent_departments,
        'recent_tasks': recent_tasks,
    }
    return render(request, 'admin_dashboard.html', context)

@csrf_exempt
@require_http_methods(["GET"])
def keep_alive(request):
    """View to keep the session alive by resetting the session expiry.
    
    This view is called via AJAX to prevent session timeout during active use.
    Returns a JSON response with the new expiry time.
    """
    if request.user.is_authenticated:
        # Update the session's modified time to reset the expiry
        request.session.modified = True
        return JsonResponse({
            'status': 'success',
            'message': 'Session extended',
            'expiry': request.session.get_expiry_age()
        })
    return JsonResponse({
        'status': 'error',
        'message': 'User not authenticated'
    }, status=401)

def home(request):
    """Home page view - shows different content based on user authentication and role"""
    # If user is not authenticated, show the public home page
    if not request.user.is_authenticated:
        return render(request, 'home.html')
        
    # Redirect superusers to admin dashboard
    if request.user.is_superuser:
        return redirect('admin_dashboard')
    
    # For authenticated users, prepare context with user-specific data
    context = {}
    
    # Get user's tasks
    tasks = Task.objects.filter(
        Q(created_by=request.user) | Q(assigned_to=request.user)
    ).order_by('-created_at')[:5]
    
    # Get upcoming appointments
    now = timezone.now()
    upcoming_appointments = Appointment.objects.filter(
        client=request.user,
        start_time__gte=now,
        status__in=['pending', 'confirmed']
    ).order_by('start_time')[:5]
    
    # Get task counts for the dashboard
    task_counts = Task.objects.filter(
        Q(created_by=request.user) | Q(assigned_to=request.user)
    ).values('status').annotate(count=Count('status'))
    
    # Format task counts for the chart
    status_order = ['todo', 'in_progress', 'in_review', 'done']
    task_status_data = []
    status_map = {item['status']: item['count'] for item in task_counts}
    
    for status in status_order:
        task_status_data.append(status_map.get(status, 0))
    
    context.update({
        'tasks': tasks,
        'upcoming_appointments': upcoming_appointments,
        'task_status_data': task_status_data,
    })
    
    # Render the home page with user-specific context
    return render(request, 'home.html', context)
    
    return render(request, 'home.html', context)

@login_required
def profile(request):
    """User profile page"""
    from django.utils import timezone
    from appointments.models import Appointment
    from tasks.models import Task
    
    # Get user's upcoming appointments (next 7 days)
    upcoming_appointments = Appointment.objects.filter(
        client=request.user,
        start_time__gte=timezone.now(),
        start_time__lte=timezone.now() + timezone.timedelta(days=7)
    ).order_by('start_time')
    
    # Get recent activities (placeholder - you can customize this)
    recent_activities = []
    
    # Add appointments to activities
    for appt in Appointment.objects.filter(client=request.user).order_by('-created_at')[:5]:
        recent_activities.append({
            'title': f'Appointment: {appt.service.name}',
            'description': f'Scheduled for {appt.start_time.strftime("%B %d, %Y at %I:%M %p")}',
            'timestamp': appt.created_at,
            'link': appt.get_absolute_url()
        })
    
    # Add tasks to activities
    for task in Task.objects.filter(assigned_to=request.user).order_by('-created_at')[:5]:
        recent_activities.append({
            'title': f'Task: {task.title}',
            'description': f'Status: {task.get_status_display()}',
            'timestamp': task.created_at,
            'link': reverse('tasks:task-detail', kwargs={'pk': task.pk})
        })
    
    # Sort activities by timestamp (newest first)
    recent_activities.sort(key=lambda x: x['timestamp'], reverse=True)
    recent_activities = recent_activities[:5]  # Limit to 5 most recent
    
    context = {
        'upcoming_appointments': upcoming_appointments,
        'recent_activities': recent_activities,
    }
    
    return render(request, 'profile.html', context)

def handler404(request, exception):
    """Custom 404 error handler"""
    return render(request, '404.html', status=404)

def handler500(request):
    """Custom 500 error handler"""
    return render(request, '500.html', status=500)

def handler403(request, exception):
    """Custom 403 error handler"""
    return render(request, '403.html', status=403)

def handler400(request, exception):
    """Custom 400 error handler"""
    return render(request, '400.html', status=400)
