from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.contrib import messages
from django.utils import timezone
from django.db.models import Count, Q, Sum, F, Case, When, IntegerField, Value, CharField, ExpressionWrapper, FloatField
from django.db.models.functions import TruncMonth, TruncWeek, Concat, ExtractWeek, ExtractYear
from datetime import datetime, timedelta
from tasks.models import Task
from users.models import User, Department, UserRole
import logging

# Set up logging
logger = logging.getLogger(__name__)

@login_required
def dashboard_router(request):
    """Route users to their appropriate dashboard based on role."""
    # If user is a superuser, redirect to custom admin dashboard
    if request.user.is_superuser:
        return redirect('admin_dashboard')
        
    # If user has no role but is staff, show a message but don't redirect to avoid loops
    if not hasattr(request.user, 'role') or not request.user.role:
        messages.warning(request, 'No role assigned. Please contact an administrator.')
        return render(request, 'home.html')
    
    # Route based on role
    if not request.user.role:
        messages.error(request, 'No role assigned. Please contact an administrator.')
        return render(request, 'home.html')
        
    role_name = request.user.role.name
    if role_name == 'president':
        return president_dashboard(request)
    elif role_name == 'minister':
        return minister_dashboard(request)
    elif role_name == 'director':
        return director_dashboard(request)
    elif role_name == 'head':
        return head_dashboard(request)
    else:  # secretary or any other role
        return secretary_dashboard(request)

@login_required
def president_dashboard(request):
    """Dashboard for President - Global access to all departments and tasks."""
    # Get all departments and users
    departments = Department.objects.all()
    all_users = User.objects.all()
    
    # Get all tasks with related data
    all_tasks = Task.objects.select_related('assigned_to', 'assigned_to__department', 'created_by')
    
    # Get tasks that require approval (high priority, national level, or pending approval)
    tasks_awaiting_approval = all_tasks.filter(
        Q(approval_status='pending') | 
        Q(priority='high') | 
        Q(scope='national')
    ).exclude(approval_status='approved').distinct().order_by('-created_at')
    
    # Calculate completion rate
    total_tasks_count = all_tasks.count()
    completed_tasks_count = all_tasks.filter(status='completed').count()
    completion_rate = round((completed_tasks_count / total_tasks_count * 100) if total_tasks_count > 0 else 0, 1)
    
    # Get tasks completed this week
    start_of_week = timezone.now() - timedelta(days=timezone.now().weekday())
    completed_this_week = all_tasks.filter(
        status='completed',
        updated_at__gte=start_of_week
    ).count()
    
    # Get active departments (with tasks assigned)
    active_departments = Department.objects.filter(
        user__assigned_tasks__isnull=False
    ).distinct().count()
    
    # Get high priority tasks
    high_priority_tasks = all_tasks.filter(priority='high').order_by('-created_at')
    
    # Get user counts by role
    total_ministers = User.objects.filter(role__name__iexact='minister').count()
    total_directors = User.objects.filter(role__name__iexact='director').count()
    total_heads = User.objects.filter(role__name__iexact='head').count()
    
    # Get recent tasks (limit to 10)
    recent_tasks = all_tasks.order_by('-created_at')[:10]
    
    # Department-wise task statistics
    department_stats = Department.objects.annotate(
        total_tasks=Count('user__assigned_tasks', distinct=True),
        completed_tasks=Count(
            'user__assigned_tasks', 
            filter=Q(user__assigned_tasks__status='completed'),
            distinct=True
        ),
        in_progress_tasks=Count(
            'user__assigned_tasks',
            filter=Q(user__assigned_tasks__status='in_progress'),
            distinct=True
        ),
        overdue_tasks=Count(
            'user__assigned_tasks',
            filter=Q(
                user__assigned_tasks__due_date__lt=timezone.now(),
                user__assigned_tasks__status__in=['todo', 'in_progress']
            ),
            distinct=True
        )
    ).filter(total_tasks__gt=0).order_by('-total_tasks')
    
    # Task completion rate
    total_completed = all_tasks.filter(status='completed').count()
    completion_rate = (total_completed / all_tasks.count() * 100) if all_tasks.exists() else 0
    
    # Task trend (last 6 months)
    six_months_ago = timezone.now() - timedelta(days=180)
    monthly_trend = all_tasks.filter(created_at__gte=six_months_ago).annotate(
        month=TruncMonth('created_at')
    ).values('month').annotate(
        total=Count('id'),
        completed=Count('id', filter=Q(status='completed')),
        month_name=Concat(
            F('month__year'), Value('-'), 
            F('month__month'),
            output_field=CharField()
        )
    ).order_by('month')
    
    # Top performers (users with most completed tasks)
    top_performers = User.objects.annotate(
        completed_tasks=Count(
            'assigned_tasks',
            filter=Q(assigned_tasks__status='completed'),
            distinct=True
        ),
        total_tasks=Count('assigned_tasks', distinct=True)
    ).annotate(
        completion_rate=Case(
            When(total_tasks=0, then=0),
            default=ExpressionWrapper(
                F('completed_tasks') * 100.0 / F('total_tasks'),
                output_field=FloatField()
            )
        )
    ).filter(completed_tasks__gt=0).order_by('-completed_tasks')[:5]
    
    # Prepare department data for charts
    department_task_data = []
    for dept in Department.objects.all():
        dept_tasks = all_tasks.filter(assigned_to__department=dept)
        if dept_tasks.exists():
            department_task_data.append({
                'name': dept.name,
                'total': dept_tasks.count(),
                'completed': dept_tasks.filter(status='completed').count(),
                'in_progress': dept_tasks.filter(status='in_progress').count(),
                'pending': dept_tasks.filter(status='todo').count(),
            })
    
    # Prepare monthly trend data
    monthly_data = []
    for i in range(5, -1, -1):
        month = timezone.now() - timedelta(days=30*i)
        month_start = month.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        next_month = month_start + timedelta(days=32)
        month_end = next_month.replace(day=1) - timedelta(days=1)
        
        month_tasks = all_tasks.filter(
            created_at__gte=month_start,
            created_at__lte=month_end
        )
        
        monthly_data.append({
            'month': month_start.strftime('%b %Y'),
            'total': month_tasks.count(),
            'completed': month_tasks.filter(status='completed').count(),
        })
    
    # Convert data to JSON for JavaScript
    import json
    monthly_data_json = json.dumps([{
        'month': item['month'],
        'total': item['total'],
        'completed': item['completed']
    } for item in monthly_data])
    
    department_data_json = json.dumps([{
        'name': dept['name'],
        'total': dept['total'],
        'completed': dept['completed'],
        'in_progress': dept['in_progress'],
        'pending': dept['pending']
    } for dept in department_task_data])
    
    context = {
        'user_role': 'President',
        'departments': departments,
        'total_users': User.objects.count(),
        'total_tasks': total_tasks_count,
        'pending_tasks': all_tasks.filter(status__in=['todo', 'in_progress']).count(),
        'completed_tasks': completed_tasks_count,
        'completion_rate': completion_rate,
        'completed_this_week': completed_this_week,
        'active_departments': active_departments,
        'high_priority_tasks': high_priority_tasks,
        'tasks_awaiting_approval': tasks_awaiting_approval,
        'recent_tasks': recent_tasks,
        'department_stats': department_stats,
        'department_task_data': department_task_data,
        'monthly_data': monthly_data,
        'total_ministers': total_ministers,
        'total_directors': total_directors,
        'total_heads': total_heads,
        'can_manage_users': True,
        'monthly_data_json': monthly_data_json,
        'department_data_json': department_data_json,
        'chart_data': {
            'monthly_trend': monthly_data,
            'department_distribution': department_task_data,
        },
    }
    return render(request, 'dashboards/president_dashboard.html', context)

@login_required
def minister_dashboard(request):
    """
    Dashboard for Minister - Full access to their ministry's departments, tasks, and user management.
    """
    ministry = request.user.department
    departments = Department.objects.filter(parent=ministry) if ministry else Department.objects.none()
    director_generals = User.objects.filter(
        role__name='director',
        department__in=departments
    )
    
    # Get tasks for the ministry
    ministry_tasks = Task.objects.filter(
        Q(assigned_to__department__in=departments) | 
        Q(created_by=request.user)
    )
    
    # Get high priority tasks
    high_priority_tasks = ministry_tasks.filter(priority='high', status='pending')
    
    # Task statistics
    task_status = ministry_tasks.values('status').annotate(
        count=Count('id'),
        percentage=ExpressionWrapper(
            Count('id') * 100.0 / ministry_tasks.count(),
            output_field=FloatField()
        )
    )
    
    # Department statistics
    department_stats = departments.annotate(
        total_tasks=Count('user__assigned_tasks', distinct=True),
        completed_tasks=Count(
            'user__assigned_tasks',
            filter=Q(user__assigned_tasks__status='completed'),
            distinct=True
        ),
        pending_tasks=Count(
            'user__assigned_tasks',
            filter=Q(user__assigned_tasks__status='pending'),
            distinct=True
        ),
        in_progress_tasks=Count(
            'user__assigned_tasks',
            filter=Q(user__assigned_tasks__status='in_progress'),
            distinct=True
        )
    )
    
    context = {
        'user_role': 'Minister',
        'ministry': ministry,
        'departments': departments,
        'director_generals': director_generals,
        'total_users': User.objects.filter(department__in=departments).count(),
        'total_tasks': ministry_tasks.count(),
        'pending_tasks': ministry_tasks.filter(status='pending').count(),
        'completed_tasks': ministry_tasks.filter(status='completed').count(),
        'in_progress_tasks': ministry_tasks.filter(status='in_progress').count(),
        'high_priority_tasks': high_priority_tasks,
        'recent_tasks': ministry_tasks.order_by('-created_at')[:5],
        'task_status': task_status,
        'department_stats': department_stats,
        'completion_rate': (
            (ministry_tasks.filter(status='completed').count() / ministry_tasks.count() * 100)
            if ministry_tasks.exists() else 0
        ),
        'total_departments': departments.count(),
        'department': department,
        'sections': sections,
        'total_users': department_users.count(),
        'total_tasks': total_tasks,
        'pending_tasks': pending_tasks,
        'in_progress_tasks': in_progress_tasks,
        'completed_tasks': completed_tasks,
        'completion_rate': completion_rate,
        'recent_tasks': recent_tasks,
        'department_tasks': department_tasks,
        'heads_of_sections': heads_of_sections,
        'task_status_data': task_status_data,
        'tasks_by_section': list(tasks_by_section),
        'overdue_tasks': overdue_tasks,
        'top_performers': top_performers,
    }
    
    return render(request, 'dashboards/director_dashboard.html', context)


@login_required
def director_dashboard(request):
    """
    Dashboard for Director General with the following features:
    - Manage all tasks and users within their department
    - Add and assign Heads of Sections
    - Track and monitor task progress at department level
    - Generate performance and progress reports
    """
    # Log user and department info
    logger.info(f"Director Dashboard - User: {request.user.email}, User ID: {request.user.id}")
    logger.info(f"User department: {request.user.department}")
    logger.info(f"User department ID: {request.user.department_id if request.user.department else None}")
    
    # Get director's department and related data
    department = request.user.department
    if not department:
        # Log all available departments for debugging
        all_depts = list(Department.objects.all().values('id', 'name', 'parent_id'))
        logger.warning(f"No department assigned to user. Available departments: {all_depts}")
        
        messages.error(request, 'No department assigned. Please contact an administrator.')
        return render(request, 'home.html')
    
    # Get all sections under this department
    sections = Department.objects.filter(parent=department)
    
    # Get all users in this department and its sections
    department_users = User.objects.filter(
        Q(department=department) | Q(department__in=sections)
    ).select_related('department', 'role')
    
    # Get all tasks in this department and its sections
    department_tasks = Task.objects.filter(
        Q(assigned_to__department=department) |
        Q(assigned_to__department__in=sections)
    ).select_related('assigned_to', 'assigned_to__department', 'created_by')
    
    # Get Heads of Sections
    head_role = UserRole.objects.get(name='head')
    heads_of_sections = User.objects.filter(
        role=head_role,
        department__in=sections
    ).select_related('department')
    
    # Task statistics
    total_tasks = department_tasks.count()
    pending_tasks = department_tasks.filter(status='pending').count()
    in_progress_tasks = department_tasks.filter(status='in_progress').count()
    completed_tasks = department_tasks.filter(status='completed').count()
    
    # Calculate completion rate (avoid division by zero)
    completion_rate = 0
    if total_tasks > 0:
        completion_rate = round((completed_tasks / total_tasks) * 100)
    
    # Get recent tasks (last 5)
    recent_tasks = department_tasks.order_by('-created_at')[:5]
    
    # Get overdue tasks
    overdue_tasks = department_tasks.filter(
        due_date__lt=timezone.now().date(),
        status__in=['pending', 'in_progress']
    ).order_by('due_date')[:5]
    
    # Get top performers (users with most completed tasks this month)
    top_performers = User.objects.filter(
        assigned_tasks__status='completed',
        assigned_tasks__completed_at__month=timezone.now().month,
        department__in=[department] + list(sections)
    ).annotate(
        completed_count=Count('assigned_tasks')
    ).order_by('-completed_count')[:5]
    
    # Prepare data for charts
    task_status_data = {
        'labels': ['Pending', 'In Progress', 'Completed'],
        'data': [pending_tasks, in_progress_tasks, completed_tasks],
        'colors': ['#f6c23e', '#4e73df', '#1cc88a']
    }
    
    # Get tasks by section
    tasks_by_section = department_tasks.values(
        'assigned_to__department__name'
    ).annotate(
        pending=Count('id', filter=Q(status='pending')),
        in_progress=Count('id', filter=Q(status='in_progress')),
        completed=Count('id', filter=Q(status='completed')),
        total=Count('id')
    ).order_by('-total')
    
    context = {
        'department': department,
        'sections': sections,
        'department_users': department_users,
        'department_tasks': department_tasks,
        'heads_of_sections': heads_of_sections,
        'total_tasks': total_tasks,
        'pending_tasks': pending_tasks,
        'in_progress_tasks': in_progress_tasks,
        'completed_tasks': completed_tasks,
        'completion_rate': completion_rate,
        'recent_tasks': recent_tasks,
        'overdue_tasks': overdue_tasks,
        'top_performers': top_performers,
        'task_status_data': task_status_data,
        'tasks_by_section': tasks_by_section,
    }
    
    return render(request, 'dashboards/director_dashboard.html', context)

@login_required
def head_dashboard(request):
    """Dashboard for Head of Section - Access to their section's tasks."""
    section = request.user.department
    if not section:
        messages.error(request, 'No section assigned. Please contact an administrator.')
        return render(request, 'home.html')
    
    # Get all tasks for the section
    section_tasks = Task.objects.filter(
        assigned_to__department=section
    ).select_related('assigned_to', 'created_by')
    
    # Get recent tasks (for the assign task modal)
    recent_tasks = section_tasks.order_by('-created_at')[:10]
    
    # Get task counts for stats
    total_tasks = section_tasks.count()
    pending_tasks = section_tasks.filter(status='pending').count()
    in_progress_tasks = section_tasks.filter(status='in_progress').count()
    completed_tasks = section_tasks.filter(status='completed').count()
    
    # Calculate completion percentage
    completion_percentage = 0
    if total_tasks > 0:
        completion_percentage = round((completed_tasks / total_tasks) * 100)
    
    # Get team members in the section
    team_members = User.objects.filter(department=section).select_related('role')
    
    context = {
        'user_role': 'Head of Section',
        'section': section,
        'total_tasks': total_tasks,
        'pending_tasks': pending_tasks,
        'in_progress_tasks': in_progress_tasks,
        'completed_tasks': completed_tasks,
        'completion_percentage': completion_percentage,
        'recent_tasks': recent_tasks,
        'team_members': team_members,
        'tasks': section_tasks.order_by('-created_at')[:10],  # For the main tasks table
    }
    
    return render(request, 'dashboards/head_dashboard.html', context)

@login_required
def secretary_dashboard(request):
    """
    Dashboard for Secretary with the following permissions:
    - View only tasks assigned to them
    - Update task status
    - Upload files and add comments
    - View task-related notifications
    """
    # Get tasks assigned to the secretary
    tasks = Task.objects.filter(assigned_to=request.user).order_by('-created_at')
    
    # Get task statistics
    total_tasks = tasks.count()
    completed_tasks = tasks.filter(status='completed').count()
    in_progress_tasks = tasks.filter(status='in_progress').count()
    pending_tasks = tasks.filter(status='pending').count()
    delayed_tasks = tasks.filter(
        Q(status__in=['pending', 'in_progress']) & 
        Q(due_date__lt=timezone.now().date())
    ).count()
    
    # Get recent tasks with related data
    recent_tasks = tasks.select_related('created_by').prefetch_related('attachments', 'comments')[:10]
    
    # Get notifications (simplified - you might want to use Django's messages framework or a notification app)
    notifications = {
        'overdue_tasks': delayed_tasks,
        'pending_approval': tasks.filter(approval_status='pending').count(),
        'recent_comments': sum(task.comments.count() for task in recent_tasks),
    }
    
    context = {
        'user_role': 'Secretary',
        'total_tasks': total_tasks,
        'completed_tasks': completed_tasks,
        'in_progress_tasks': in_progress_tasks,
        'pending_tasks': pending_tasks,
        'delayed_tasks': delayed_tasks,
        'recent_tasks': recent_tasks,
        'notifications': notifications,
    }
    return render(request, 'dashboards/secretary_dashboard.html', context)
