"""
Dashboard views - PX Command Center and analytics dashboards
"""

import json
from datetime import timedelta, datetime

from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator
from django.db.models import Avg, Count, Q, Sum
from django.http import JsonResponse
from django.shortcuts import redirect, render, reverse
from django.utils import timezone
from django.views.generic import TemplateView
from django.utils.translation import gettext_lazy as _
from django.contrib import messages


class CommandCenterView(LoginRequiredMixin, TemplateView):
    """
    PX Command Center Dashboard - Real-time control panel.

    Shows:
    - Red Alert Banner (urgent items requiring immediate attention)
    - Top KPI cards (complaints, actions, surveys, etc.) with drill-down
    - Charts (trends, satisfaction, leaderboards)
    - Live feed (latest complaints, actions, events)
    - Enhanced modules (Inquiries, Observations)
    - Filters (date range, hospital, department)

    Follows the "5-Second Rule": Critical signals dominant and comprehensible within 5 seconds.
    Uses modular tile/card system with 30-60 second auto-refresh capability.
    """

    template_name = "dashboard/command_center.html"

    def dispatch(self, request, *args, **kwargs):
        """Check user type and redirect accordingly"""
        if request.user.is_authenticated and request.user.is_source_user():
            return redirect("px_sources:source_user_dashboard")

        if request.user.is_authenticated and request.user.is_basic_staff():
            if hasattr(request.user, "department") and request.user.department:
                return redirect("organizations:department_detail", pk=request.user.department.pk)

        if request.user.is_authenticated and request.user.is_champion() and request.user.department:
            return redirect("organizations:department_detail", pk=request.user.department.pk)

        if request.user.is_authenticated and request.user.is_department_manager() and request.user.department:
            return redirect("organizations:department_detail", pk=request.user.department.pk)

        if request.user.is_authenticated and request.user.is_px_admin() and not request.tenant_hospital:
            return redirect("core:select_hospital")

        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        user = self.request.user

        # Import models
        from apps.complaints.models import Complaint, Inquiry
        from apps.px_action_center.models import PXAction
        from apps.surveys.models import SurveyInstance
        from apps.callcenter.models import CallCenterInteraction
        from apps.integrations.models import InboundEvent
        from apps.physicians.models import PhysicianMonthlyRating
        from apps.organizations.models import Staff
        from apps.observations.models import Observation

        # Date filters
        now = timezone.now()
        last_24h = now - timedelta(hours=24)
        last_7d = now - timedelta(days=7)
        last_30d = now - timedelta(days=30)
        last_60d = now - timedelta(days=60)

        # Base querysets (filtered by user role and tenant_hospital)
        if user.is_px_admin():
            # PX Admins use their selected hospital from session
            hospital = self.request.tenant_hospital
            complaints_qs = Complaint.objects.filter(hospital=hospital) if hospital else Complaint.objects.none()
            inquiries_qs = Inquiry.objects.filter(hospital=hospital) if hospital else Inquiry.objects.none()
            actions_qs = PXAction.objects.filter(hospital=hospital) if hospital else PXAction.objects.none()
            surveys_qs = (
                SurveyInstance.objects.filter(hospital=hospital) if hospital else SurveyInstance.objects.none()
            )  # Filter by tenant hospital
            calls_qs = (
                CallCenterInteraction.objects.filter(hospital=hospital)
                if hospital
                else CallCenterInteraction.objects.none()
            )
            observations_qs = Observation.objects.filter(hospital=hospital) if hospital else Observation.objects.none()
        elif user.is_hospital_admin() and user.hospital:
            complaints_qs = Complaint.objects.filter(hospital=user.hospital)
            inquiries_qs = Inquiry.objects.filter(hospital=user.hospital)
            actions_qs = PXAction.objects.filter(hospital=user.hospital)
            surveys_qs = SurveyInstance.objects.filter(hospital=user.hospital)
            calls_qs = CallCenterInteraction.objects.filter(hospital=user.hospital)
            observations_qs = Observation.objects.filter(hospital=user.hospital)
        elif user.is_department_manager() and user.department:
            complaints_qs = Complaint.objects.filter(department=user.department)
            inquiries_qs = Inquiry.objects.filter(department=user.department)
            actions_qs = PXAction.objects.filter(department=user.department)
            surveys_qs = SurveyInstance.objects.filter(journey_instance__department=user.department)
            calls_qs = CallCenterInteraction.objects.filter(department=user.department)
            observations_qs = Observation.objects.filter(assigned_department=user.department)
        elif user.is_champion() and user.department:
            complaints_qs = Complaint.objects.filter(department=user.department)
            inquiries_qs = Inquiry.objects.filter(
                Q(department=user.department) | Q(outgoing_department=user.department)
            )
            actions_qs = PXAction.objects.filter(department=user.department)
            surveys_qs = SurveyInstance.objects.filter(journey_instance__department=user.department)
            calls_qs = CallCenterInteraction.objects.filter(department=user.department)
            observations_qs = Observation.objects.filter(assigned_department=user.department)
        elif user.is_director():
            directed_depts = user.get_directed_departments()
            if directed_depts.exists():
                complaints_qs = Complaint.objects.filter(department__in=directed_depts)
                inquiries_qs = Inquiry.objects.filter(department__in=directed_depts)
                actions_qs = PXAction.objects.filter(department__in=directed_depts)
                surveys_qs = SurveyInstance.objects.filter(journey_instance__department__in=directed_depts)
                calls_qs = CallCenterInteraction.objects.filter(department__in=directed_depts)
                observations_qs = Observation.objects.filter(assigned_department__in=directed_depts)
            else:
                complaints_qs = Complaint.objects.none()
                inquiries_qs = Inquiry.objects.none()
                actions_qs = PXAction.objects.none()
                surveys_qs = SurveyInstance.objects.none()
                calls_qs = CallCenterInteraction.objects.none()
                observations_qs = Observation.objects.none()
        elif user.is_executive():
            if user.hospital:
                complaints_qs = Complaint.objects.filter(hospital=user.hospital)
                inquiries_qs = Inquiry.objects.filter(hospital=user.hospital)
                actions_qs = PXAction.objects.filter(hospital=user.hospital)
                surveys_qs = SurveyInstance.objects.filter(journey_instance__department__hospital=user.hospital)
                calls_qs = CallCenterInteraction.objects.filter(department__hospital=user.hospital)
                observations_qs = Observation.objects.filter(hospital=user.hospital)
            else:
                complaints_qs = Complaint.objects.none()
                inquiries_qs = Inquiry.objects.none()
                actions_qs = PXAction.objects.none()
                surveys_qs = SurveyInstance.objects.none()
                calls_qs = CallCenterInteraction.objects.none()
                observations_qs = Observation.objects.none()
        else:
            complaints_qs = Complaint.objects.none()
            inquiries_qs = Inquiry.objects.none()
            actions_qs = PXAction.objects.none()
            surveys_qs = SurveyInstance.objects.none()
            calls_qs = CallCenterInteraction.objects.none()
            observations_qs = Observation.objects.none()

        # ========================================
        # RED ALERT ITEMS (5-Second Rule)
        # ========================================
        red_alerts = []

        # Critical complaints
        critical_complaints = complaints_qs.filter(severity="critical", status__in=["open", "in_progress"]).count()
        if critical_complaints > 0:
            red_alerts.append(
                {
                    "type": "critical_complaints",
                    "label": _("Critical Complaints"),
                    "value": critical_complaints,
                    "icon": "alert-octagon",
                    "color": "red",
                    "url": f"{reverse('complaints:complaint_list')}?severity=critical&status=open,in_progress",
                    "priority": 1,
                }
            )

        # Overdue complaints
        overdue_complaints = complaints_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count()
        if overdue_complaints > 0:
            red_alerts.append(
                {
                    "type": "overdue_complaints",
                    "label": _("Overdue Complaints"),
                    "value": overdue_complaints,
                    "icon": "clock",
                    "color": "orange",
                    "url": f"{reverse('complaints:complaint_list')}?is_overdue=true&status=open,in_progress",
                    "priority": 2,
                }
            )

        # Escalated actions
        escalated_actions = actions_qs.filter(escalation_level__gt=0, status__in=["open", "in_progress"]).count()
        if escalated_actions > 0:
            red_alerts.append(
                {
                    "type": "escalated_actions",
                    "label": _("Escalated Actions"),
                    "value": escalated_actions,
                    "icon": "arrow-up-circle",
                    "color": "red",
                    "url": reverse("actions:action_list"),
                    "priority": 3,
                }
            )

        # Negative surveys in last 24h
        negative_surveys_24h = surveys_qs.filter(is_negative=True, completed_at__gte=last_24h).count()
        if negative_surveys_24h > 0:
            red_alerts.append(
                {
                    "type": "negative_surveys",
                    "label": _("Negative Surveys (24h)"),
                    "value": negative_surveys_24h,
                    "icon": "frown",
                    "color": "yellow",
                    "url": reverse("surveys:instance_list"),
                    "priority": 4,
                }
            )

        # Sort by priority
        red_alerts.sort(key=lambda x: x["priority"])
        context["red_alerts"] = red_alerts
        context["has_red_alerts"] = len(red_alerts) > 0

        # ========================================
        # COMPLAINTS MODULE DATA
        # ========================================
        complaints_current = complaints_qs.filter(created_at__gte=last_30d).count()
        complaints_previous = complaints_qs.filter(created_at__gte=last_60d, created_at__lt=last_30d).count()
        complaints_variance = 0
        if complaints_previous > 0:
            complaints_variance = round(((complaints_current - complaints_previous) / complaints_previous) * 100, 1)

        # Resolution time calculation
        resolved_complaints = complaints_qs.filter(status="closed", closed_at__isnull=False, created_at__gte=last_30d)
        avg_resolution_hours = 0
        if resolved_complaints.exists():
            total_hours = sum((c.closed_at - c.created_at).total_seconds() / 3600 for c in resolved_complaints)
            avg_resolution_hours = round(total_hours / resolved_complaints.count(), 1)

        # Complaints by severity for donut chart
        complaints_by_severity = {
            "critical": complaints_qs.filter(severity="critical", status__in=["open", "in_progress"]).count(),
            "high": complaints_qs.filter(severity="high", status__in=["open", "in_progress"]).count(),
            "medium": complaints_qs.filter(severity="medium", status__in=["open", "in_progress"]).count(),
            "low": complaints_qs.filter(severity="low", status__in=["open", "in_progress"]).count(),
        }

        # Complaints by department for heatmap
        complaints_by_department = list(
            complaints_qs.filter(status__in=["open", "in_progress"], department__isnull=False)
            .values("department__name")
            .annotate(count=Count("id"))
            .order_by("-count")[:10]
        )

        context["complaints_module"] = {
            "total_active": complaints_qs.filter(status__in=["open", "in_progress"]).count(),
            "current_period": complaints_current,
            "previous_period": complaints_previous,
            "variance": complaints_variance,
            "variance_direction": "up" if complaints_variance > 0 else "down" if complaints_variance < 0 else "neutral",
            "avg_resolution_hours": avg_resolution_hours,
            "overdue": complaints_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count(),
            "by_severity": complaints_by_severity,
            "by_department": complaints_by_department,
            "critical_new": complaints_qs.filter(severity="critical", created_at__gte=last_24h).count(),
        }

        # ========================================
        # SURVEY INSIGHTS MODULE DATA
        # ========================================
        surveys_completed_30d = surveys_qs.filter(completed_at__gte=last_30d)
        total_surveys_30d = surveys_completed_30d.count()

        # Calculate average satisfaction
        avg_satisfaction = (
            surveys_completed_30d.filter(total_score__isnull=False).aggregate(Avg("total_score"))["total_score__avg"]
            or 0
        )

        # NPS-style calculation (promoters - detractors)
        positive_count = surveys_completed_30d.filter(is_negative=False).count()
        negative_count = surveys_completed_30d.filter(is_negative=True).count()
        nps_score = 0
        if total_surveys_30d > 0:
            nps_score = round(((positive_count - negative_count) / total_surveys_30d) * 100)

        # Response rate (completed vs sent in last 30 days)
        surveys_sent_30d = surveys_qs.filter(sent_at__gte=last_30d).count()
        response_rate = 0
        if surveys_sent_30d > 0:
            response_rate = round((total_surveys_30d / surveys_sent_30d) * 100, 1)

        context["survey_module"] = {
            "avg_satisfaction": round(avg_satisfaction, 1),
            "nps_score": nps_score,
            "response_rate": response_rate,
            "total_completed": total_surveys_30d,
            "positive_count": positive_count,
            "negative_count": negative_count,
            "neutral_count": total_surveys_30d - positive_count - negative_count,
            "negative_24h": surveys_qs.filter(is_negative=True, completed_at__gte=last_24h).count(),
        }

        # ========================================
        # PX ACTIONS MODULE DATA
        # ========================================
        actions_open = actions_qs.filter(status="open").count()
        actions_in_progress = actions_qs.filter(status="in_progress").count()
        actions_pending_approval = actions_qs.filter(status="pending_approval").count()
        actions_closed_30d = actions_qs.filter(status="closed", closed_at__gte=last_30d).count()

        # Time to close calculation
        closed_actions = actions_qs.filter(status="closed", closed_at__isnull=False, created_at__gte=last_30d)
        avg_time_to_close_hours = 0
        if closed_actions.exists():
            total_hours = sum((a.closed_at - a.created_at).total_seconds() / 3600 for a in closed_actions)
            avg_time_to_close_hours = round(total_hours / closed_actions.count(), 1)

        # Actions by source for breakdown
        actions_by_source = list(
            actions_qs.filter(status__in=["open", "in_progress"])
            .values("source_type")
            .annotate(count=Count("id"))
            .order_by("-count")
        )

        context["actions_module"] = {
            "open": actions_open,
            "in_progress": actions_in_progress,
            "pending_approval": actions_pending_approval,
            "overdue": actions_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count(),
            "escalated": actions_qs.filter(escalation_level__gt=0, status__in=["open", "in_progress"]).count(),
            "closed_30d": actions_closed_30d,
            "avg_time_to_close_hours": avg_time_to_close_hours,
            "by_source": actions_by_source,
            "new_today": actions_qs.filter(created_at__gte=last_24h).count(),
        }

        # ========================================
        # INQUIRIES MODULE DATA
        # ========================================
        inquiries_open = inquiries_qs.filter(status="open").count()
        inquiries_in_progress = inquiries_qs.filter(status="in_progress").count()
        inquiries_resolved_30d = inquiries_qs.filter(status="resolved", updated_at__gte=last_30d).count()

        context["inquiries_module"] = {
            "open": inquiries_open,
            "in_progress": inquiries_in_progress,
            "total_active": inquiries_open + inquiries_in_progress,
            "resolved_30d": inquiries_resolved_30d,
            "new_24h": inquiries_qs.filter(created_at__gte=last_24h).count(),
        }

        # ========================================
        # OBSERVATIONS MODULE DATA
        # ========================================
        observations_new = observations_qs.filter(status="new").count()
        observations_in_progress = observations_qs.filter(status="in_progress").count()
        observations_critical = observations_qs.filter(
            severity="critical", status__in=["new", "triaged", "assigned", "in_progress"]
        ).count()

        # Observations by category
        observations_by_category = list(
            observations_qs.filter(status__in=["new", "triaged", "assigned", "in_progress"])
            .values("category__name_en")
            .annotate(count=Count("id"))
            .order_by("-count")[:5]
        )

        context["observations_module"] = {
            "new": observations_new,
            "in_progress": observations_in_progress,
            "critical": observations_critical,
            "total_active": observations_new + observations_in_progress,
            "resolved_30d": observations_qs.filter(status="resolved", resolved_at__gte=last_30d).count(),
            "by_category": observations_by_category,
        }

        # ========================================
        # COMMUNICATION/CALL CENTER MODULE DATA
        # ========================================
        calls_7d = calls_qs.filter(call_started_at__gte=last_7d)
        total_calls = calls_7d.count()
        low_rating_calls = calls_7d.filter(is_low_rating=True).count()

        context["calls_module"] = {
            "total_7d": total_calls,
            "low_ratings": low_rating_calls,
            "satisfaction_rate": round(((total_calls - low_rating_calls) / total_calls * 100), 1)
            if total_calls > 0
            else 0,
        }

        # ========================================
        # LEGACY STATS (for backward compatibility)
        # ========================================
        context["stats"] = {
            "total_complaints": context["complaints_module"]["total_active"],
            "avg_resolution_time": f"{avg_resolution_hours}h",
            "satisfaction_score": round(avg_satisfaction, 0),
            "active_actions": context["actions_module"]["open"] + context["actions_module"]["in_progress"],
            "new_today": context["actions_module"]["new_today"],
        }

        # ========================================
        # LATEST ITEMS FOR LIVE FEED
        # ========================================
        # Latest high severity complaints
        context["latest_complaints"] = (
            complaints_qs.filter(severity__in=["high", "critical"])
            .select_related("patient", "hospital", "department")
            .order_by("-created_at")[:5]
        )

        # Latest escalated actions
        context["latest_actions"] = (
            actions_qs.filter(escalation_level__gt=0)
            .select_related("hospital", "assigned_to")
            .order_by("-escalated_at")[:5]
        )

        # Latest inquiries
        context["latest_inquiries"] = (
            inquiries_qs.filter(status__in=["open", "in_progress"])
            .select_related("patient", "hospital", "department")
            .order_by("-created_at")[:5]
        )

        # Latest observations
        context["latest_observations"] = (
            observations_qs.filter(status__in=["new", "triaged", "assigned"])
            .select_related("hospital", "category")
            .order_by("-created_at")[:5]
        )

        # Latest integration events
        context["latest_events"] = (
            InboundEvent.objects.filter(status="processed").select_related().order_by("-processed_at")[:10]
        )

        # ========================================
        # PHYSICIAN LEADERBOARD
        # ========================================
        current_month_ratings = PhysicianMonthlyRating.objects.filter(year=now.year, month=now.month).select_related(
            "staff", "staff__hospital", "staff__department"
        )

        # Filter by user role
        if user.is_hospital_admin() and user.hospital:
            current_month_ratings = current_month_ratings.filter(staff__hospital=user.hospital)
        elif user.is_department_manager() and user.department:
            current_month_ratings = current_month_ratings.filter(staff__department=user.department)
        elif user.is_director():
            directed_depts = user.get_directed_departments()
            if directed_depts.exists():
                current_month_ratings = current_month_ratings.filter(staff__department__in=directed_depts)
            else:
                current_month_ratings = current_month_ratings.none()

        # Top 5 staff this month
        context["top_physicians"] = current_month_ratings.order_by("-average_rating")[:5]

        # Staff stats
        physician_stats = current_month_ratings.aggregate(
            total_physicians=Count("id"), avg_rating=Avg("average_rating"), total_surveys=Count("total_surveys")
        )
        context["physician_stats"] = physician_stats

        # ========================================
        # CHART DATA
        # ========================================
        context["chart_data"] = {
            "complaints_trend": json.dumps(self.get_complaints_trend(complaints_qs, last_30d)),
            "complaints_by_severity": json.dumps(complaints_by_severity),
            "survey_satisfaction": avg_satisfaction,
            "nps_trend": json.dumps(self.get_nps_trend(surveys_qs, last_30d)),
            "actions_funnel": json.dumps(
                {
                    "open": actions_open,
                    "in_progress": actions_in_progress,
                    "pending_approval": actions_pending_approval,
                    "closed": actions_closed_30d,
                }
            ),
        }

        # Add hospital context
        context["current_hospital"] = self.request.tenant_hospital
        context["is_px_admin"] = user.is_px_admin()

        # Last updated timestamp
        context["last_updated"] = now.strftime("%Y-%m-%d %H:%M:%S")

        return context

    def get_complaints_trend(self, queryset, start_date):
        """Get complaints trend data for chart"""
        # Group by day for last 30 days
        data = []
        for i in range(30):
            date = start_date + timedelta(days=i)
            count = queryset.filter(created_at__date=date.date()).count()
            data.append({"date": date.strftime("%Y-%m-%d"), "count": count})
        return data

    def get_nps_trend(self, queryset, start_date):
        """Get NPS trend data for chart"""
        data = []
        for i in range(30):
            date = start_date + timedelta(days=i)
            day_surveys = queryset.filter(completed_at__date=date.date())
            total = day_surveys.count()
            if total > 0:
                positive = day_surveys.filter(is_negative=False).count()
                negative = day_surveys.filter(is_negative=True).count()
                nps = round(((positive - negative) / total) * 100)
            else:
                nps = 0
            data.append({"date": date.strftime("%Y-%m-%d"), "nps": nps})
        return data

    def get_survey_satisfaction(self, queryset, start_date):
        """Get survey satisfaction averages"""
        return (
            queryset.filter(completed_at__gte=start_date, total_score__isnull=False).aggregate(Avg("total_score"))[
                "total_score__avg"
            ]
            or 0
        )


@login_required
def my_dashboard(request):
    """
    My Dashboard - Personal view of all assigned items.

    Shows:
    - Summary cards with statistics
    - Tabbed interface for 6 model types:
      * Complaints
      * Inquiries
      * Observations
      * PX Actions
      * Tasks (QI Project Tasks)
      * Feedback
    - Date range filtering
    - Search and filter controls
    - Export functionality (CSV/Excel)
    - Bulk actions support
    - Charts showing trends
    """
    # Redirect Source Users to their dashboard
    if request.user.is_source_user():
        return redirect("px_sources:source_user_dashboard")

    user = request.user

    # Get selected hospital for PX Admins (from middleware)
    selected_hospital = getattr(request, "tenant_hospital", None)

    # Get date range filter
    date_range_days = int(request.GET.get("date_range", 30))
    if date_range_days == -1:  # All time
        start_date = None
    else:
        start_date = timezone.now() - timedelta(days=date_range_days)

    # Get active tab
    active_tab = request.GET.get("tab", "complaints")

    # Get search query
    search_query = request.GET.get("search", "")

    # Get status filter
    status_filter = request.GET.get("status", "")

    # Get priority/severity filter
    priority_filter = request.GET.get("priority", "")

    # Build querysets for all models
    querysets = {}

    # 1. Complaints
    from apps.complaints.models import Complaint

    complaints_qs = Complaint.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins
    if selected_hospital:
        complaints_qs = complaints_qs.filter(hospital=selected_hospital)
    if start_date:
        complaints_qs = complaints_qs.filter(created_at__gte=start_date)
    if search_query:
        complaints_qs = complaints_qs.filter(Q(title__icontains=search_query) | Q(description__icontains=search_query))
    if status_filter:
        complaints_qs = complaints_qs.filter(status=status_filter)
    if priority_filter:
        complaints_qs = complaints_qs.filter(severity=priority_filter)
    querysets["complaints"] = complaints_qs.select_related(
        "patient", "hospital", "department", "source", "created_by"
    ).order_by("-created_at")

    # 2. Inquiries
    from apps.complaints.models import Inquiry

    inquiries_qs = Inquiry.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins
    if selected_hospital:
        inquiries_qs = inquiries_qs.filter(hospital=selected_hospital)
    if start_date:
        inquiries_qs = inquiries_qs.filter(created_at__gte=start_date)
    if search_query:
        inquiries_qs = inquiries_qs.filter(Q(subject__icontains=search_query) | Q(message__icontains=search_query))
    if status_filter:
        inquiries_qs = inquiries_qs.filter(status=status_filter)
    querysets["inquiries"] = inquiries_qs.select_related("patient", "hospital", "department").order_by("-created_at")

    # 3. Observations
    from apps.observations.models import Observation

    observations_qs = Observation.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins
    if selected_hospital:
        observations_qs = observations_qs.filter(hospital=selected_hospital)
    if start_date:
        observations_qs = observations_qs.filter(created_at__gte=start_date)
    if search_query:
        observations_qs = observations_qs.filter(
            Q(title__icontains=search_query) | Q(description__icontains=search_query)
        )
    if status_filter:
        observations_qs = observations_qs.filter(status=status_filter)
    if priority_filter:
        observations_qs = observations_qs.filter(severity=priority_filter)
    querysets["observations"] = observations_qs.select_related("hospital", "assigned_department").order_by(
        "-created_at"
    )

    # 4. PX Actions
    from apps.px_action_center.models import PXAction

    actions_qs = PXAction.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins
    if selected_hospital:
        actions_qs = actions_qs.filter(hospital=selected_hospital)
    if start_date:
        actions_qs = actions_qs.filter(created_at__gte=start_date)
    if search_query:
        actions_qs = actions_qs.filter(Q(title__icontains=search_query) | Q(description__icontains=search_query))
    if status_filter:
        actions_qs = actions_qs.filter(status=status_filter)
    if priority_filter:
        actions_qs = actions_qs.filter(severity=priority_filter)
    querysets["actions"] = actions_qs.select_related("hospital", "department", "approved_by").order_by("-created_at")

    # 5. QI Project Tasks
    from apps.projects.models import QIProjectTask

    tasks_qs = QIProjectTask.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins (via project)
    if selected_hospital:
        tasks_qs = tasks_qs.filter(project__hospital=selected_hospital)
    if start_date:
        tasks_qs = tasks_qs.filter(created_at__gte=start_date)
    if search_query:
        tasks_qs = tasks_qs.filter(Q(title__icontains=search_query) | Q(description__icontains=search_query))
    if status_filter:
        tasks_qs = tasks_qs.filter(status=status_filter)
    querysets["tasks"] = tasks_qs.select_related("project").order_by("-created_at")

    # 6. Feedback
    from apps.feedback.models import Feedback

    feedback_qs = Feedback.objects.filter(assigned_to=user)
    # Filter by selected hospital for PX Admins
    if selected_hospital:
        feedback_qs = feedback_qs.filter(hospital=selected_hospital)
    if start_date:
        feedback_qs = feedback_qs.filter(created_at__gte=start_date)
    if search_query:
        feedback_qs = feedback_qs.filter(Q(title__icontains=search_query) | Q(message__icontains=search_query))
    if status_filter:
        feedback_qs = feedback_qs.filter(status=status_filter)
    if priority_filter:
        feedback_qs = feedback_qs.filter(priority=priority_filter)
    querysets["feedback"] = feedback_qs.select_related("hospital", "department", "patient").order_by("-created_at")

    # Calculate statistics
    stats = {}
    total_stats = {"total": 0, "open": 0, "in_progress": 0, "resolved": 0, "closed": 0, "overdue": 0}

    # Complaints stats
    complaints_open = querysets["complaints"].filter(status="open").count()
    complaints_in_progress = querysets["complaints"].filter(status="in_progress").count()
    complaints_resolved = querysets["complaints"].filter(status="resolved").count()
    complaints_closed = querysets["complaints"].filter(status="closed").count()
    complaints_overdue = querysets["complaints"].filter(is_overdue=True).count()
    stats["complaints"] = {
        "total": querysets["complaints"].count(),
        "open": complaints_open,
        "in_progress": complaints_in_progress,
        "resolved": complaints_resolved,
        "closed": complaints_closed,
        "overdue": complaints_overdue,
    }
    total_stats["total"] += stats["complaints"]["total"]
    total_stats["open"] += complaints_open
    total_stats["in_progress"] += complaints_in_progress
    total_stats["resolved"] += complaints_resolved
    total_stats["closed"] += complaints_closed
    total_stats["overdue"] += complaints_overdue

    # Inquiries stats
    inquiries_open = querysets["inquiries"].filter(status="open").count()
    inquiries_in_progress = querysets["inquiries"].filter(status="in_progress").count()
    inquiries_resolved = querysets["inquiries"].filter(status="resolved").count()
    inquiries_closed = querysets["inquiries"].filter(status="closed").count()
    stats["inquiries"] = {
        "total": querysets["inquiries"].count(),
        "open": inquiries_open,
        "in_progress": inquiries_in_progress,
        "resolved": inquiries_resolved,
        "closed": inquiries_closed,
        "overdue": 0,
    }
    total_stats["total"] += stats["inquiries"]["total"]
    total_stats["open"] += inquiries_open
    total_stats["in_progress"] += inquiries_in_progress
    total_stats["resolved"] += inquiries_resolved
    total_stats["closed"] += inquiries_closed

    # Observations stats
    observations_open = querysets["observations"].filter(status="open").count()
    observations_in_progress = querysets["observations"].filter(status="in_progress").count()
    observations_closed = querysets["observations"].filter(status="closed").count()
    # Observations don't have is_overdue field - set to 0
    observations_overdue = 0
    stats["observations"] = {
        "total": querysets["observations"].count(),
        "open": observations_open,
        "in_progress": observations_in_progress,
        "resolved": 0,
        "closed": observations_closed,
        "overdue": observations_overdue,
    }
    total_stats["total"] += stats["observations"]["total"]
    total_stats["open"] += observations_open
    total_stats["in_progress"] += observations_in_progress
    total_stats["closed"] += observations_closed
    total_stats["overdue"] += observations_overdue

    # PX Actions stats
    actions_open = querysets["actions"].filter(status="open").count()
    actions_in_progress = querysets["actions"].filter(status="in_progress").count()
    actions_closed = querysets["actions"].filter(status="closed").count()
    actions_overdue = querysets["actions"].filter(is_overdue=True).count()
    stats["actions"] = {
        "total": querysets["actions"].count(),
        "open": actions_open,
        "in_progress": actions_in_progress,
        "resolved": 0,
        "closed": actions_closed,
        "overdue": actions_overdue,
    }
    total_stats["total"] += stats["actions"]["total"]
    total_stats["open"] += actions_open
    total_stats["in_progress"] += actions_in_progress
    total_stats["closed"] += actions_closed
    total_stats["overdue"] += actions_overdue

    # Tasks stats
    tasks_open = querysets["tasks"].filter(status="open").count()
    tasks_in_progress = querysets["tasks"].filter(status="in_progress").count()
    tasks_closed = querysets["tasks"].filter(status="closed").count()
    stats["tasks"] = {
        "total": querysets["tasks"].count(),
        "open": tasks_open,
        "in_progress": tasks_in_progress,
        "resolved": 0,
        "closed": tasks_closed,
        "overdue": 0,
    }
    total_stats["total"] += stats["tasks"]["total"]
    total_stats["open"] += tasks_open
    total_stats["in_progress"] += tasks_in_progress
    total_stats["closed"] += tasks_closed

    # Feedback stats
    feedback_open = querysets["feedback"].filter(status="submitted").count()
    feedback_in_progress = querysets["feedback"].filter(status="reviewed").count()
    feedback_acknowledged = querysets["feedback"].filter(status="acknowledged").count()
    feedback_closed = querysets["feedback"].filter(status="closed").count()
    stats["feedback"] = {
        "total": querysets["feedback"].count(),
        "open": feedback_open,
        "in_progress": feedback_in_progress,
        "resolved": feedback_acknowledged,
        "closed": feedback_closed,
        "overdue": 0,
    }
    total_stats["total"] += stats["feedback"]["total"]
    total_stats["open"] += feedback_open
    total_stats["in_progress"] += feedback_in_progress
    total_stats["resolved"] += feedback_acknowledged
    total_stats["closed"] += feedback_closed

    # Paginate all querysets
    page_size = int(request.GET.get("page_size", 25))
    paginated_data = {}

    for tab_name, qs in querysets.items():
        paginator = Paginator(qs, page_size)
        page_number = request.GET.get(f"page_{tab_name}", 1)
        paginated_data[tab_name] = paginator.get_page(page_number)

    # Get chart data
    chart_data = get_dashboard_chart_data(user, start_date, selected_hospital)

    from apps.accounts.models import StaffActivityLog
    activity_logs = StaffActivityLog.objects.filter(user=user).select_related("content_type")
    if start_date:
        activity_logs = activity_logs.filter(created_at__gte=start_date)
    activity_logs = activity_logs[:50]

    context = {
        "stats": stats,
        "total_stats": total_stats,
        "paginated_data": paginated_data,
        "active_tab": active_tab,
        "date_range": date_range_days,
        "search_query": search_query,
        "status_filter": status_filter,
        "priority_filter": priority_filter,
        "chart_data": chart_data,
        "selected_hospital": selected_hospital,
        "activity_logs": activity_logs,
    }

    return render(request, "dashboard/my_dashboard.html", context)


def get_dashboard_chart_data(user, start_date=None, selected_hospital=None):
    """
    Get chart data for dashboard trends.

    Returns JSON-serializable data for ApexCharts.
    """
    from apps.complaints.models import Complaint
    from apps.px_action_center.models import PXAction
    from apps.observations.models import Observation
    from apps.feedback.models import Feedback
    from apps.complaints.models import Inquiry
    from apps.projects.models import QIProjectTask

    # Default to last 30 days if no start_date
    if not start_date:
        start_date = timezone.now() - timedelta(days=30)

    # Get completion trends
    completion_data = []
    labels = []

    # Group by day for last 30 days
    for i in range(30):
        date = start_date + timedelta(days=i)
        date_str = date.strftime("%Y-%m-%d")
        labels.append(date.strftime("%b %d"))

        completed_count = 0
        # Check each model for completions on this date
        # Apply hospital filter for PX Admins
        complaint_qs = Complaint.objects.filter(assigned_to=user, status="closed", closed_at__date=date.date())
        if selected_hospital:
            complaint_qs = complaint_qs.filter(hospital=selected_hospital)
        completed_count += complaint_qs.count()

        inquiry_qs = Inquiry.objects.filter(assigned_to=user, status="closed", updated_at__date=date.date())
        if selected_hospital:
            inquiry_qs = inquiry_qs.filter(hospital=selected_hospital)
        completed_count += inquiry_qs.count()

        observation_qs = Observation.objects.filter(assigned_to=user, status="closed", updated_at__date=date.date())
        if selected_hospital:
            observation_qs = observation_qs.filter(hospital=selected_hospital)
        completed_count += observation_qs.count()

        action_qs = PXAction.objects.filter(assigned_to=user, status="closed", closed_at__date=date.date())
        if selected_hospital:
            action_qs = action_qs.filter(hospital=selected_hospital)
        completed_count += action_qs.count()

        task_qs = QIProjectTask.objects.filter(assigned_to=user, status="closed", completed_date=date.date())
        if selected_hospital:
            task_qs = task_qs.filter(project__hospital=selected_hospital)
        completed_count += task_qs.count()

        feedback_qs = Feedback.objects.filter(assigned_to=user, status="closed", closed_at__date=date.date())
        if selected_hospital:
            feedback_qs = feedback_qs.filter(hospital=selected_hospital)
        completed_count += feedback_qs.count()

        completion_data.append(completed_count)

    return {"completion_trend": {"labels": labels, "data": completion_data}}


@login_required
def dashboard_bulk_action(request):
    """
    Handle bulk actions on dashboard items.

    Supported actions:
    - bulk_assign: Assign to user
    - bulk_status: Change status
    """
    if request.method != "POST":
        return JsonResponse({"success": False, "error": "POST required"}, status=405)

    import json

    try:
        data = json.loads(request.body)
        action = data.get("action")
        tab_name = data.get("tab")
        item_ids = data.get("item_ids", [])

        if not action or not tab_name:
            return JsonResponse({"success": False, "error": "Missing required fields"}, status=400)

        # Route to appropriate handler based on tab
        if tab_name == "complaints":
            from apps.complaints.models import Complaint

            queryset = Complaint.objects.filter(id__in=item_ids, assigned_to=request.user)
        elif tab_name == "inquiries":
            from apps.complaints.models import Inquiry

            queryset = Inquiry.objects.filter(id__in=item_ids, assigned_to=request.user)
        elif tab_name == "observations":
            from apps.observations.models import Observation

            queryset = Observation.objects.filter(id__in=item_ids, assigned_to=request.user)
        elif tab_name == "actions":
            from apps.px_action_center.models import PXAction

            queryset = PXAction.objects.filter(id__in=item_ids, assigned_to=request.user)
        elif tab_name == "tasks":
            from apps.projects.models import QIProjectTask

            queryset = QIProjectTask.objects.filter(id__in=item_ids, assigned_to=request.user)
        elif tab_name == "feedback":
            from apps.feedback.models import Feedback

            queryset = Feedback.objects.filter(id__in=item_ids, assigned_to=request.user)
        else:
            return JsonResponse({"success": False, "error": "Invalid tab"}, status=400)

        # Apply bulk action
        if action == "bulk_status":
            new_status = data.get("new_status")
            if not new_status:
                return JsonResponse({"success": False, "error": "Missing new_status"}, status=400)

            count = queryset.update(status=new_status)
            return JsonResponse({"success": True, "updated_count": count})

        elif action == "bulk_assign":
            user_id = data.get("user_id")
            if not user_id:
                return JsonResponse({"success": False, "error": "Missing user_id"}, status=400)

            from apps.accounts.models import User

            assignee = User.objects.get(id=user_id)
            count = queryset.update(assigned_to=assignee, assigned_at=timezone.now())
            return JsonResponse({"success": True, "updated_count": count})

        else:
            return JsonResponse({"success": False, "error": "Invalid action"}, status=400)

    except json.JSONDecodeError:
        return JsonResponse({"success": False, "error": "Invalid JSON"}, status=400)
    except Exception as e:
        return JsonResponse({"success": False, "error": str(e)}, status=500)


@login_required
def admin_evaluation(request):
    """
    Admin Evaluation Dashboard - Staff performance analysis.

    Shows:
    - Performance metrics for all staff members
    - Complaints: Source breakdown, status distribution, response time, activation time
    - Inquiries: Status distribution, response time
    - Multi-staff comparison
    - Date range filtering
    - Hospital/department filtering

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    from apps.accounts.models import User
    from apps.organizations.models import Hospital, Department

    user = request.user

    # Only PX Admins and Hospital Admins can access
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access the Admin Evaluation dashboard.")

    # Get date range filter
    date_range = request.GET.get("date_range", "30d")
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")

    # Parse custom dates if provided
    if custom_start:
        from datetime import datetime

        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime

        custom_end = datetime.fromisoformat(custom_end)

    # Get hospital and department filters
    hospital_id = request.GET.get("hospital_id")
    department_id = request.GET.get("department_id")

    # Get selected staff IDs for comparison
    selected_staff_ids = request.GET.getlist("staff_ids")

    status_filter = request.GET.get("status", "active")

    # Get available hospitals (for PX Admins)
    if user.is_px_admin():
        hospitals = Hospital.objects.filter(status="active")
    elif user.is_hospital_admin() and user.hospital:
        hospitals = Hospital.objects.filter(id=user.hospital.id)
        hospital_id = hospital_id or user.hospital.id  # Default to user's hospital
    else:
        hospitals = Hospital.objects.none()

    # Get available departments based on hospital filter
    if hospital_id:
        departments = Department.objects.filter(hospital_id=hospital_id, status="active")
    elif user.hospital:
        departments = Department.objects.filter(hospital=user.hospital, status="active")
    else:
        departments = Department.objects.none()

    # Get staff performance metrics
    performance_data = UnifiedAnalyticsService.get_staff_performance_metrics(
        user=user,
        date_range=date_range,
        hospital_id=hospital_id,
        department_id=department_id,
        staff_ids=selected_staff_ids if selected_staff_ids else None,
        custom_start=custom_start,
        custom_end=custom_end,
    )

    # Get all staff for the dropdown
    staff_queryset = User.objects.filter(groups__name="PX Employee")

    if user.is_px_admin():
        # PX Admins MUST filter by tenant_hospital
        if request.tenant_hospital:
            staff_queryset = staff_queryset.filter(hospital=request.tenant_hospital)
            hospital_id = hospital_id or request.tenant_hospital.id
        else:
            staff_queryset = User.objects.none()  # No access without selected hospital
    elif user.is_hospital_admin() and user.hospital:
        staff_queryset = staff_queryset.filter(hospital=user.hospital)
        hospital_id = hospital_id or user.hospital.id

    if department_id:
        staff_queryset = staff_queryset.filter(department_id=department_id)

    if status_filter == "active":
        staff_queryset = staff_queryset.filter(is_active=True)
    elif status_filter == "inactive":
        staff_queryset = staff_queryset.filter(is_active=False)

    # Only staff with assigned complaints or inquiries
    staff_queryset = (
        staff_queryset.filter(Q(assigned_complaints__isnull=False) | Q(assigned_inquiries__isnull=False))
        .distinct()
        .select_related("hospital", "department")
    )

    context = {
        "departments": departments,
        "staff_list": staff_queryset,
        "selected_hospital_id": hospital_id,
        "selected_department_id": department_id,
        "selected_staff_ids": selected_staff_ids,
        "date_range": date_range,
        "custom_start": custom_start,
        "custom_end": custom_end,
        "performance_data": performance_data,
        "status_filter": status_filter,
    }

    return render(request, "dashboard/admin_evaluation.html", context)


@login_required
def admin_evaluation_chart_data(request):
    """
    API endpoint to get chart data for admin evaluation dashboard.

    Access: PX Admin and Hospital Admin only
    """
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService

    if request.method != "GET":
        return JsonResponse({"success": False, "error": "GET required"}, status=405)

    user = request.user

    # Only PX Admins and Hospital Admins can access
    if not (user.is_px_admin() or user.is_hospital_admin()):
        return JsonResponse({"success": False, "error": "Permission denied"}, status=403)

    chart_type = request.GET.get("chart_type")
    date_range = request.GET.get("date_range", "30d")
    hospital_id = request.GET.get("hospital_id")
    department_id = request.GET.get("department_id")
    staff_ids = request.GET.getlist("staff_ids")

    # For PX Admins without explicit hospital_id, use tenant_hospital
    if user.is_px_admin() and not hospital_id and request.tenant_hospital:
        hospital_id = str(request.tenant_hospital.id)

    # Parse custom dates if provided
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")
    if custom_start:
        from datetime import datetime

        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime

        custom_end = datetime.fromisoformat(custom_end)

    try:
        if chart_type == "staff_performance":
            data = UnifiedAnalyticsService.get_staff_performance_metrics(
                user=user,
                date_range=date_range,
                hospital_id=hospital_id,
                department_id=department_id,
                staff_ids=staff_ids if staff_ids else None,
                custom_start=custom_start,
                custom_end=custom_end,
            )
        else:
            data = {"error": f"Unknown chart type: {chart_type}"}

        return JsonResponse({"success": True, "data": data})

    except Exception as e:
        return JsonResponse({"success": False, "error": str(e)}, status=500)


# ============================================================================
# ENHANCED ADMIN EVALUATION VIEWS
# ============================================================================


@login_required
def staff_performance_detail(request, staff_id):
    """
    Detailed performance view for a single staff member.

    Shows:
    - Performance score with breakdown
    - Daily workload trends
    - Recent complaints and inquiries
    - Performance metrics

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService

    # Only PX Admins and Hospital Admins can access
    if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access staff performance details.")
    from apps.accounts.models import User

    user = request.user

    # Get date range
    date_range = request.GET.get("date_range", "30d")

    try:
        staff = User.objects.select_related("hospital", "department").get(id=staff_id)

        # Check permissions
        if not user.is_px_admin():
            if user.hospital and staff.hospital != user.hospital:
                messages.error(request, "You don't have permission to view this staff member's performance.")
                return redirect("dashboard:admin_evaluation")

        # Get detailed performance
        performance = UnifiedAnalyticsService.get_staff_detailed_performance(
            staff_id=staff_id, user=user, date_range=date_range
        )

        # Get trends
        trends = UnifiedAnalyticsService.get_staff_performance_trends(staff_id=staff_id, user=user, months=6)

        context = {
            "staff": performance["staff"],
            "performance": performance,
            "trends": trends,
            "date_range": date_range,
        }

        return render(request, "dashboard/staff_performance_detail.html", context)

    except User.DoesNotExist:
        messages.error(request, "Staff member not found.")
        return redirect("dashboard:admin_evaluation")
    except PermissionError:
        messages.error(request, "You don't have permission to view this staff member.")
        return redirect("dashboard:admin_evaluation")


@login_required
def staff_performance_trends(request, staff_id):
    """
    API endpoint to get staff performance trends as JSON.

    Access: PX Admin and Hospital Admin only
    """
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    from apps.accounts.models import User

    # Only PX Admins and Hospital Admins can access
    if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
        return JsonResponse({"success": False, "error": "Permission denied"}, status=403)

    user = request.user
    months = int(request.GET.get("months", 6))

    try:
        trends = UnifiedAnalyticsService.get_staff_performance_trends(staff_id=staff_id, user=user, months=months)
        return JsonResponse({"success": True, "trends": trends})
    except Exception as e:
        return JsonResponse({"success": False, "error": str(e)}, status=400)


@login_required
def department_benchmarks(request):
    """
    Department benchmarking view comparing all staff.

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService

    # Only PX Admins and Hospital Admins can access
    if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access department benchmarks.")

    user = request.user

    # Get filters
    department_id = request.GET.get("department_id")
    date_range = request.GET.get("date_range", "30d")

    # If user is department manager, use their department
    if user.is_department_manager() and user.department and not department_id:
        department_id = str(user.department.id)

    try:
        benchmarks = UnifiedAnalyticsService.get_department_benchmarks(
            user=user, department_id=department_id, date_range=date_range
        )

        context = {"benchmarks": benchmarks, "date_range": date_range}

        return render(request, "dashboard/department_benchmarks.html", context)

    except Exception as e:
        messages.error(request, f"Error loading benchmarks: {str(e)}")
        return redirect("dashboard:admin_evaluation")


@login_required
def export_staff_performance(request):
    """
    Export staff performance report in various formats.

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    import csv
    import json
    from django.http import HttpResponse

    # Only PX Admins and Hospital Admins can access
    if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can export staff performance.")

    user = request.user

    if request.method != "POST":
        return JsonResponse({"error": "POST required"}, status=405)

    try:
        data = json.loads(request.body)
        staff_ids = data.get("staff_ids", [])
        date_range = data.get("date_range", "30d")
        format_type = data.get("format", "csv")

        # Generate report
        report = UnifiedAnalyticsService.export_staff_performance_report(
            staff_ids=staff_ids, user=user, date_range=date_range, format_type=format_type
        )

        if format_type == "csv":
            response = HttpResponse(content_type="text/csv")
            response["Content-Disposition"] = (
                f'attachment; filename="staff_performance_{timezone.now().strftime("%Y%m%d")}.csv"'
            )

            if report["data"]:
                writer = csv.DictWriter(response, fieldnames=report["data"][0].keys())
                writer.writeheader()
                writer.writerows(report["data"])

            return response

        elif format_type == "json":
            return JsonResponse(report)

        else:
            return JsonResponse({"error": f"Unsupported format: {format_type}"}, status=400)

    except Exception as e:
        return JsonResponse({"error": str(e)}, status=500)


@login_required
def command_center_api(request):
    """
    API endpoint for Command Center live data updates.

    Returns JSON with all module data for AJAX refresh without page reload.
    Enables true real-time updates every 30-60 seconds.
    """
    from apps.complaints.models import Complaint, Inquiry
    from apps.px_action_center.models import PXAction
    from apps.surveys.models import SurveyInstance
    from apps.physicians.models import PhysicianMonthlyRating
    from apps.observations.models import Observation

    user = request.user
    now = timezone.now()
    last_24h = now - timedelta(hours=24)
    last_30d = now - timedelta(days=30)
    last_60d = now - timedelta(days=60)

    # Build querysets based on user role
    if user.is_px_admin():
        hospital = request.tenant_hospital
        complaints_qs = Complaint.objects.filter(hospital=hospital) if hospital else Complaint.objects.none()
        inquiries_qs = Inquiry.objects.filter(hospital=hospital) if hospital else Inquiry.objects.none()
        actions_qs = PXAction.objects.filter(hospital=hospital) if hospital else PXAction.objects.none()
        surveys_qs = SurveyInstance.objects.all()
        observations_qs = Observation.objects.filter(hospital=hospital) if hospital else Observation.objects.none()
    elif user.is_hospital_admin() and user.hospital:
        complaints_qs = Complaint.objects.filter(hospital=user.hospital)
        inquiries_qs = Inquiry.objects.filter(hospital=user.hospital)
        actions_qs = PXAction.objects.filter(hospital=user.hospital)
        surveys_qs = SurveyInstance.objects.filter(survey_template__hospital=user.hospital)
        observations_qs = Observation.objects.filter(hospital=user.hospital)
    elif user.is_department_manager() and user.department:
        complaints_qs = Complaint.objects.filter(department=user.department)
        inquiries_qs = Inquiry.objects.filter(department=user.department)
        actions_qs = PXAction.objects.filter(department=user.department)
        surveys_qs = SurveyInstance.objects.filter(journey_instance__department=user.department)
        observations_qs = Observation.objects.filter(assigned_department=user.department)
    elif user.is_champion() and user.department:
        complaints_qs = Complaint.objects.filter(department=user.department)
        inquiries_qs = Inquiry.objects.filter(
            Q(department=user.department) | Q(outgoing_department=user.department)
        )
        actions_qs = PXAction.objects.filter(department=user.department)
        surveys_qs = SurveyInstance.objects.filter(journey_instance__department=user.department)
        observations_qs = Observation.objects.filter(assigned_department=user.department)
    elif user.is_director():
        directed_depts = user.get_directed_departments()
        if directed_depts.exists():
            complaints_qs = Complaint.objects.filter(department__in=directed_depts)
            inquiries_qs = Inquiry.objects.filter(department__in=directed_depts)
            actions_qs = PXAction.objects.filter(department__in=directed_depts)
            surveys_qs = SurveyInstance.objects.filter(journey_instance__department__in=directed_depts)
            observations_qs = Observation.objects.filter(assigned_department__in=directed_depts)
        else:
            complaints_qs = Complaint.objects.none()
            inquiries_qs = Inquiry.objects.none()
            actions_qs = PXAction.objects.none()
            surveys_qs = SurveyInstance.objects.none()
            observations_qs = Observation.objects.none()
    elif user.is_executive():
        if user.hospital:
            complaints_qs = Complaint.objects.filter(hospital=user.hospital)
            inquiries_qs = Inquiry.objects.filter(hospital=user.hospital)
            actions_qs = PXAction.objects.filter(hospital=user.hospital)
            surveys_qs = SurveyInstance.objects.filter(survey_template__hospital=user.hospital)
            observations_qs = Observation.objects.filter(hospital=user.hospital)
        else:
            complaints_qs = Complaint.objects.none()
            inquiries_qs = Inquiry.objects.none()
            actions_qs = PXAction.objects.none()
            surveys_qs = SurveyInstance.objects.none()
            observations_qs = Observation.objects.none()
    else:
        complaints_qs = Complaint.objects.none()
        inquiries_qs = Inquiry.objects.none()
        actions_qs = PXAction.objects.none()
        surveys_qs = SurveyInstance.objects.none()
        observations_qs = Observation.objects.none()

    # Calculate all module data
    # Complaints
    complaints_current = complaints_qs.filter(created_at__gte=last_30d).count()
    complaints_previous = complaints_qs.filter(created_at__gte=last_60d, created_at__lt=last_30d).count()
    complaints_variance = (
        round(((complaints_current - complaints_previous) / complaints_previous) * 100, 1)
        if complaints_previous > 0
        else 0
    )

    # Surveys
    surveys_completed_30d = surveys_qs.filter(completed_at__gte=last_30d)
    total_surveys_30d = surveys_completed_30d.count()
    positive_count = surveys_completed_30d.filter(is_negative=False).count()
    negative_count = surveys_completed_30d.filter(is_negative=True).count()
    nps_score = round(((positive_count - negative_count) / total_surveys_30d) * 100) if total_surveys_30d > 0 else 0
    avg_satisfaction = (
        surveys_completed_30d.filter(total_score__isnull=False).aggregate(Avg("total_score"))["total_score__avg"] or 0
    )
    surveys_sent_30d = surveys_qs.filter(sent_at__gte=last_30d).count()
    response_rate = round((total_surveys_30d / surveys_sent_30d) * 100, 1) if surveys_sent_30d > 0 else 0

    # Actions
    actions_open = actions_qs.filter(status="open").count()
    actions_in_progress = actions_qs.filter(status="in_progress").count()
    actions_pending_approval = actions_qs.filter(status="pending_approval").count()
    actions_closed_30d = actions_qs.filter(status="closed", closed_at__gte=last_30d).count()

    # Red alerts
    red_alerts = []
    critical_complaints = complaints_qs.filter(severity="critical", status__in=["open", "in_progress"]).count()
    if critical_complaints > 0:
        red_alerts.append({"type": "critical_complaints", "value": critical_complaints})
    overdue_complaints = complaints_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count()
    if overdue_complaints > 0:
        red_alerts.append({"type": "overdue_complaints", "value": overdue_complaints})
    escalated_actions = actions_qs.filter(escalation_level__gt=0, status__in=["open", "in_progress"]).count()
    if escalated_actions > 0:
        red_alerts.append({"type": "escalated_actions", "value": escalated_actions})
    negative_surveys_24h = surveys_qs.filter(is_negative=True, completed_at__gte=last_24h).count()
    if negative_surveys_24h > 0:
        red_alerts.append({"type": "negative_surveys", "value": negative_surveys_24h})

    return JsonResponse(
        {
            "success": True,
            "timestamp": now.isoformat(),
            "last_updated": now.strftime("%Y-%m-%d %H:%M:%S"),
            "red_alerts": {"has_alerts": len(red_alerts) > 0, "count": len(red_alerts), "items": red_alerts},
            "modules": {
                "complaints": {
                    "total_active": complaints_qs.filter(status__in=["open", "in_progress"]).count(),
                    "variance": complaints_variance,
                    "variance_direction": "up"
                    if complaints_variance > 0
                    else "down"
                    if complaints_variance < 0
                    else "neutral",
                    "overdue": complaints_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count(),
                    "critical": complaints_qs.filter(severity="critical", status__in=["open", "in_progress"]).count(),
                    "by_severity": {
                        "critical": complaints_qs.filter(
                            severity="critical", status__in=["open", "in_progress"]
                        ).count(),
                        "high": complaints_qs.filter(severity="high", status__in=["open", "in_progress"]).count(),
                        "medium": complaints_qs.filter(severity="medium", status__in=["open", "in_progress"]).count(),
                        "low": complaints_qs.filter(severity="low", status__in=["open", "in_progress"]).count(),
                    },
                },
                "surveys": {
                    "nps_score": nps_score,
                    "avg_satisfaction": round(avg_satisfaction, 1),
                    "response_rate": response_rate,
                    "total_completed": total_surveys_30d,
                    "negative_24h": surveys_qs.filter(is_negative=True, completed_at__gte=last_24h).count(),
                },
                "actions": {
                    "open": actions_open,
                    "in_progress": actions_in_progress,
                    "pending_approval": actions_pending_approval,
                    "closed_30d": actions_closed_30d,
                    "overdue": actions_qs.filter(is_overdue=True, status__in=["open", "in_progress"]).count(),
                    "escalated": actions_qs.filter(escalation_level__gt=0, status__in=["open", "in_progress"]).count(),
                },
                "inquiries": {
                    "open": inquiries_qs.filter(status="open").count(),
                    "in_progress": inquiries_qs.filter(status="in_progress").count(),
                    "total_active": inquiries_qs.filter(status__in=["open", "in_progress"]).count(),
                    "new_24h": inquiries_qs.filter(created_at__gte=last_24h).count(),
                },
                "observations": {
                    "new": observations_qs.filter(status="new").count(),
                    "in_progress": observations_qs.filter(status="in_progress").count(),
                    "total_active": observations_qs.filter(status__in=["new", "in_progress"]).count(),
                    "critical": observations_qs.filter(
                        severity="critical", status__in=["new", "triaged", "assigned", "in_progress"]
                    ).count(),
                },
            },
        }
    )


@login_required
def performance_analytics_api(request):
    """
    API endpoint for various performance analytics.

    Access: PX Admin and Hospital Admin only
    """
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService

    # Only PX Admins and Hospital Admins can access
    if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
        return JsonResponse({"success": False, "error": "Permission denied"}, status=403)

    user = request.user
    chart_type = request.GET.get("chart_type")

    try:
        if chart_type == "staff_trends":
            staff_id = request.GET.get("staff_id")
            months = int(request.GET.get("months", 6))

            data = UnifiedAnalyticsService.get_staff_performance_trends(staff_id=staff_id, user=user, months=months)

        elif chart_type == "department_benchmarks":
            department_id = request.GET.get("department_id")
            date_range = request.GET.get("date_range", "30d")

            data = UnifiedAnalyticsService.get_department_benchmarks(
                user=user, department_id=department_id, date_range=date_range
            )

        else:
            return JsonResponse({"error": f"Unknown chart type: {chart_type}"}, status=400)

        return JsonResponse({"success": True, "data": data})

    except Exception as e:
        return JsonResponse({"success": False, "error": str(e)}, status=500)


@login_required
def employee_evaluation(request):
    """
    Employee Evaluation Dashboard - PAD Department Weekly Dashboard.

    Shows comprehensive performance metrics for all staff members side-by-side.
    Based on the employee_evaluation.md specification.

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    from apps.accounts.models import User
    from apps.organizations.models import Hospital, Department

    user = request.user

    # Only PX Admins and Hospital Admins can access
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access the Employee Evaluation dashboard.")

    # Get date range filter - default to last 7 days (weekly)
    date_range = request.GET.get("date_range", "7d")
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")

    # Parse custom dates if provided
    if custom_start:
        from datetime import datetime

        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime

        custom_end = datetime.fromisoformat(custom_end)

    # Get hospital and department filters
    hospital_id = request.GET.get("hospital_id")
    department_id = request.GET.get("department_id")

    # Get selected staff IDs for comparison
    selected_staff_ids = request.GET.getlist("staff_ids")

    status_filter = request.GET.get("status", "active")

    # Get available hospitals (for PX Admins)
    if user.is_px_admin():
        hospitals = Hospital.objects.filter(status="active")
    elif user.is_hospital_admin() and user.hospital:
        hospitals = Hospital.objects.filter(id=user.hospital.id)
        hospital_id = hospital_id or user.hospital.id  # Default to user's hospital
    else:
        hospitals = Hospital.objects.none()

    # Get available departments based on hospital filter
    if hospital_id:
        departments = Department.objects.filter(hospital_id=hospital_id, status="active")
    elif user.hospital:
        departments = Department.objects.filter(hospital=user.hospital, status="active")
    else:
        departments = Department.objects.none()

    # Get employee evaluation metrics
    evaluation_data = UnifiedAnalyticsService.get_employee_evaluation_metrics(
        user=user,
        date_range=date_range,
        hospital_id=hospital_id,
        department_id=department_id,
        staff_ids=selected_staff_ids if selected_staff_ids else None,
        custom_start=custom_start,
        custom_end=custom_end,
    )

    # Get all staff for the dropdown
    staff_queryset = User.objects.filter(groups__name="PX Employee")

    if user.is_px_admin():
        if hospital_id:
            staff_queryset = staff_queryset.filter(hospital_id=hospital_id)
        elif request.tenant_hospital:
            staff_queryset = staff_queryset.filter(hospital=request.tenant_hospital)
            hospital_id = hospital_id or request.tenant_hospital.id
    elif user.is_hospital_admin() and user.hospital:
        staff_queryset = staff_queryset.filter(hospital=user.hospital)
        hospital_id = hospital_id or user.hospital.id

    if department_id:
        staff_queryset = staff_queryset.filter(department_id=department_id)

    if status_filter == "active":
        staff_queryset = staff_queryset.filter(is_active=True)
    elif status_filter == "inactive":
        staff_queryset = staff_queryset.filter(is_active=False)

    # Only staff with assigned complaints or inquiries
    staff_queryset = (
        staff_queryset.filter(Q(assigned_complaints__isnull=False) | Q(assigned_inquiries__isnull=False))
        .distinct()
        .select_related("hospital", "department")
    )

    context = {
        "departments": departments,
        "staff_list": staff_queryset,
        "selected_hospital_id": hospital_id,
        "selected_department_id": department_id,
        "selected_staff_ids": selected_staff_ids,
        "date_range": date_range,
        "custom_start": custom_start,
        "custom_end": custom_end,
        "evaluation_data": evaluation_data,
        "status_filter": status_filter,
    }

    return render(request, "dashboard/employee_evaluation.html", context)


@login_required
def employee_evaluation_charts(request):
    """
    Employee Evaluation Charts page — comparison table + visual charts.

    Access: PX Admin and Hospital Admin only
    """
    from django.core.exceptions import PermissionDenied
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    from apps.accounts.models import User
    from apps.organizations.models import Hospital, Department

    user = request.user

    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access this page.")

    date_range = request.GET.get("date_range", "7d")
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")

    if custom_start:
        from datetime import datetime
        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime
        custom_end = datetime.fromisoformat(custom_end)

    hospital_id = request.GET.get("hospital_id")
    department_id = request.GET.get("department_id")
    selected_staff_ids = request.GET.getlist("staff_ids")
    status_filter = request.GET.get("status", "active")

    if user.is_px_admin():
        hospitals = Hospital.objects.filter(status="active")
    elif user.is_hospital_admin() and user.hospital:
        hospitals = Hospital.objects.filter(id=user.hospital.id)
        hospital_id = hospital_id or user.hospital.id
    else:
        hospitals = Hospital.objects.none()

    if hospital_id:
        departments = Department.objects.filter(hospital_id=hospital_id, status="active")
    elif user.hospital:
        departments = Department.objects.filter(hospital=user.hospital, status="active")
    else:
        departments = Department.objects.none()

    evaluation_data = UnifiedAnalyticsService.get_employee_evaluation_metrics(
        user=user,
        date_range=date_range,
        hospital_id=hospital_id,
        department_id=department_id,
        staff_ids=selected_staff_ids if selected_staff_ids else None,
        custom_start=custom_start,
        custom_end=custom_end,
    )

    staff_queryset = User.objects.filter(groups__name="PX Employee")

    if user.is_px_admin():
        if hospital_id:
            staff_queryset = staff_queryset.filter(hospital_id=hospital_id)
        elif request.tenant_hospital:
            staff_queryset = staff_queryset.filter(hospital=request.tenant_hospital)
            hospital_id = hospital_id or request.tenant_hospital.id
    elif user.is_hospital_admin() and user.hospital:
        staff_queryset = staff_queryset.filter(hospital=user.hospital)
        hospital_id = hospital_id or user.hospital.id

    if department_id:
        staff_queryset = staff_queryset.filter(department_id=department_id)

    if status_filter == "active":
        staff_queryset = staff_queryset.filter(is_active=True)
    elif status_filter == "inactive":
        staff_queryset = staff_queryset.filter(is_active=False)

    staff_queryset = (
        staff_queryset.filter(Q(assigned_complaints__isnull=False) | Q(assigned_inquiries__isnull=False))
        .distinct()
        .select_related("hospital", "department")
    )

    context = {
        "departments": departments,
        "staff_list": staff_queryset,
        "selected_hospital_id": hospital_id,
        "selected_department_id": department_id,
        "selected_staff_ids": selected_staff_ids,
        "date_range": date_range,
        "custom_start": custom_start,
        "custom_end": custom_end,
        "evaluation_data": evaluation_data,
        "hospitals": hospitals,
        "status_filter": status_filter,
    }

    return render(request, "dashboard/employee_evaluation_charts.html", context)


@login_required
def employee_evaluation_data(request):
    """
    API endpoint to get employee evaluation data for charts and tables.

    Access: PX Admin and Hospital Admin only
    """
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService

    if request.method != "GET":
        return JsonResponse({"success": False, "error": "GET required"}, status=405)

    user = request.user

    # Only PX Admins and Hospital Admins can access
    if not (user.is_px_admin() or user.is_hospital_admin()):
        return JsonResponse({"success": False, "error": "Permission denied"}, status=403)

    date_range = request.GET.get("date_range", "7d")
    hospital_id = request.GET.get("hospital_id")
    department_id = request.GET.get("department_id")
    staff_ids = request.GET.getlist("staff_ids")

    # For PX Admins without explicit hospital_id, use tenant_hospital
    if user.is_px_admin() and not hospital_id and request.tenant_hospital:
        hospital_id = str(request.tenant_hospital.id)

    # Parse custom dates if provided
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")
    if custom_start:
        from datetime import datetime

        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime

        custom_end = datetime.fromisoformat(custom_end)

    try:
        # Get employee evaluation metrics
        evaluation_data = UnifiedAnalyticsService.get_employee_evaluation_metrics(
            user=user,
            date_range=date_range,
            hospital_id=hospital_id,
            department_id=department_id,
            staff_ids=staff_ids if staff_ids else None,
            custom_start=custom_start,
            custom_end=custom_end,
        )

        return JsonResponse({"success": True, "data": evaluation_data})

    except Exception as e:
        return JsonResponse({"success": False, "error": str(e)}, status=500)
        return JsonResponse({"success": False, "error": str(e)}, status=500)


@login_required
def complaint_request_list(request):
    """
    Step 0 — Complaint Request List view.

    Shows all complaint requests (filled, not filled, on hold)
    with filters for month, staff, status. Includes export button.
    """
    from django.core.exceptions import PermissionDenied
    from apps.dashboard.models import ComplaintRequest

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access.")

    qs = ComplaintRequest.objects.select_related("staff", "hospital", "complained_department", "complaint")

    if user.is_hospital_admin() and user.hospital:
        qs = qs.filter(hospital=user.hospital)
    elif user.is_px_admin() and request.tenant_hospital:
        qs = qs.filter(hospital=request.tenant_hospital)

    month = request.GET.get("month")
    year = request.GET.get("year")
    staff_id = request.GET.get("staff_id")
    status = request.GET.get("status")

    if year and month:
        qs = qs.filter(request_date__year=int(year), request_date__month=int(month))
    elif year:
        qs = qs.filter(request_date__year=int(year))

    if staff_id:
        qs = qs.filter(staff_id=staff_id)

    if status == "filled":
        qs = qs.filter(filled=True)
    elif status == "not_filled":
        qs = qs.filter(not_filled=True)
    elif status == "on_hold":
        qs = qs.filter(on_hold=True)
    elif status == "barcode":
        qs = qs.filter(from_barcode=True)

    qs = qs.order_by("-request_date", "-created_at")

    paginator = Paginator(qs, 50)
    page_number = request.GET.get("page", 1)
    page_obj = paginator.get_page(page_number)

    from apps.accounts.models import User

    staff_members = User.objects.filter(complaint_requests_sent__isnull=False)

    # Filter by hospital based on user role
    if user.is_hospital_admin() and user.hospital:
        staff_members = staff_members.filter(hospital=user.hospital)
    elif user.is_px_admin() and request.tenant_hospital:
        staff_members = staff_members.filter(hospital=request.tenant_hospital)

    staff_members = staff_members.distinct().order_by("first_name", "last_name")

    context = {
        "page_obj": page_obj,
        "staff_members": staff_members,
        "selected_year": year,
        "selected_month": month,
        "selected_staff": staff_id,
        "selected_status": status,
        "years_range": range(2024, timezone.now().year + 1),
        "months_range": range(1, 13),
    }

    return render(request, "dashboard/complaint_request_list.html", context)


@login_required
def complaint_request_export(request):
    """
    Step 0 — Export complaint requests to Excel.
    """
    from django.core.exceptions import PermissionDenied
    from apps.dashboard.models import ComplaintRequest
    from apps.complaints.utils import export_requests_report

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can export.")

    qs = ComplaintRequest.objects.select_related("staff", "hospital", "complained_department", "complaint")

    if user.is_hospital_admin() and user.hospital:
        qs = qs.filter(hospital=user.hospital)
    elif user.is_px_admin() and request.tenant_hospital:
        qs = qs.filter(hospital=request.tenant_hospital)

    year = request.GET.get("year")
    month = request.GET.get("month")

    if year and month:
        qs = qs.filter(request_date__year=int(year), request_date__month=int(month))
    elif year:
        qs = qs.filter(request_date__year=int(year))

    return export_requests_report(
        qs,
        year=int(year) if year else None,
        month=int(month) if month else None,
    )


@login_required
def census_report(request):
    import json

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.census import CensusService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    year = request.GET.get("year")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/census_report.html", {"no_data": True})

    year = int(year) if year else timezone.now().year

    service = CensusService(hospital_id=hospital_id, year=year)
    monthly_counts = service.get_monthly_counts(year)
    quarterly_data = service.get_quarterly_data(year)
    year_totals = service.get_year_totals(year)
    available_years = service.get_available_years()
    chart_data = service.get_chart_data(years=[year - 2, year - 1, year])

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "selected_year": year,
        "available_years": available_years,
        "monthly_counts": monthly_counts,
        "quarterly_data": quarterly_data,
        "year_totals": year_totals,
        "chart_data_json": json.dumps(chart_data),
    }
    return render(request, "dashboard/census_report.html", context)


@login_required
def inquiry_report(request):
    import json

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.inquiry_report import InquiryReportService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    year = request.GET.get("year")
    month = request.GET.get("month")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/inquiry_report.html", {"no_data": True})

    year = int(year) if year else timezone.now().year
    month = int(month) if month else timezone.now().month

    service = InquiryReportService(hospital_id=hospital_id, year=year, month=month)
    available_months = service.get_available_months()
    incoming_summary = service.get_summary(is_outgoing=False)
    outgoing_summary = service.get_summary(is_outgoing=True)
    chart_data = service.get_chart_data()
    employee_breakdown = service.get_employee_breakdown()
    department_breakdown = service.get_department_breakdown()

    fmt = lambda n: f"{n:,}"

    for bd in employee_breakdown + department_breakdown:
        bd["total_fmt"] = fmt(bd["total"])

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "selected_year": year,
        "selected_month": month,
        "available_months": available_months,
        "incoming": incoming_summary,
        "outgoing": outgoing_summary,
        "incoming_total_fmt": fmt(incoming_summary["total"]),
        "outgoing_total_fmt": fmt(outgoing_summary["total"]),
        "chart_data_json": json.dumps(chart_data),
        "employee_breakdown": employee_breakdown,
        "department_breakdown": department_breakdown,
    }
    return render(request, "dashboard/inquiry_report.html", context)


@login_required
def census_report_export(request):
    from django.core.exceptions import PermissionDenied
    from django.http import HttpResponse
    from apps.dashboard.services.census import CensusService
    from apps.dashboard.services.census_export import generate_census_excel
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access.")

    hospital_id = request.GET.get("hospital")
    year = request.GET.get("year")
    month = request.GET.get("month")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        return HttpResponse("Hospital parameter required", status=400)

    year = int(year) if year else timezone.now().year
    month = int(month) if month else timezone.now().month

    service = CensusService(hospital_id=hospital_id, year=year, month=month)
    buf = generate_census_excel(service)

    month_label = f"{year}-{month:02d}"
    response = HttpResponse(
        buf.getvalue(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = f'attachment; filename="census_{month_label}.xlsx"'
    return response


@login_required
def observation_report(request):
    import json

    from datetime import date

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.observation_report import ObservationReportService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    date_from_str = request.GET.get("date_from")
    date_to_str = request.GET.get("date_to")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/observation_report.html", {"no_data": True})

    today = timezone.now().date()
    if date_from_str:
        date_from = date.fromisoformat(date_from_str)
    else:
        date_from = today.replace(day=1)

    if date_to_str:
        date_to = date.fromisoformat(date_to_str)
    else:
        date_to = today

    service = ObservationReportService(hospital_id=hospital_id, date_from=date_from, date_to=date_to)
    summary = service.get_summary()
    chart_data = service.get_chart_data()
    employee_breakdown = service.get_employee_breakdown()
    department_breakdown = service.get_department_breakdown()
    category_breakdown = service.get_category_breakdown()

    fmt = lambda n: f"{n:,}"

    for bd in employee_breakdown + department_breakdown:
        bd["total_fmt"] = fmt(bd["total"])

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "date_from": date_from.isoformat(),
        "date_to": date_to.isoformat(),
        "summary": summary,
        "total_fmt": fmt(summary["total"]),
        "chart_data_json": json.dumps(chart_data),
        "employee_breakdown": employee_breakdown,
        "department_breakdown": department_breakdown,
        "category_breakdown": category_breakdown,
    }
    return render(request, "dashboard/observation_report.html", context)


@login_required
def observation_report_export(request):
    from datetime import date

    from django.core.exceptions import PermissionDenied
    from django.http import HttpResponse
    from apps.dashboard.services.observation_report import ObservationReportService
    from apps.dashboard.services.observation_report_export import generate_observation_excel

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access.")

    hospital_id = request.GET.get("hospital")
    date_from_str = request.GET.get("date_from")
    date_to_str = request.GET.get("date_to")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        return HttpResponse("Hospital parameter required", status=400)

    today = timezone.now().date()
    if date_from_str:
        date_from = date.fromisoformat(date_from_str)
    else:
        date_from = today.replace(day=1)

    if date_to_str:
        date_to = date.fromisoformat(date_to_str)
    else:
        date_to = today

    service = ObservationReportService(hospital_id=hospital_id, date_from=date_from, date_to=date_to)
    buf = generate_observation_excel(service)

    date_label = f"{date_from.isoformat()}_to_{date_to.isoformat()}"
    response = HttpResponse(
        buf.getvalue(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = f'attachment; filename="observations_{date_label}.xlsx"'
    return response


@login_required
def complaint_monthly_report(request):
    import json

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.complaint_monthly_service import ComplaintMonthlyService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    year = request.GET.get("year")
    month = request.GET.get("month")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/complaint_monthly_report.html", {"no_data": True})

    year = int(year) if year else timezone.now().year
    month = int(month) if month else timezone.now().month

    service = ComplaintMonthlyService(hospital_id=hospital_id, year=year, month=month)
    available_months = service.get_available_months()
    summary = service.get_summary()
    chart_data = service.get_chart_data()
    stage_times = service.get_avg_stage_times()

    fmt = lambda n: f"{n:,}"

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "selected_year": year,
        "selected_month": month,
        "available_months": available_months,
        "summary": summary,
        "total_fmt": fmt(summary["total"]),
        "chart_data_json": json.dumps(chart_data),
        "stage_times": stage_times,
    }
    return render(request, "dashboard/complaint_monthly_report.html", context)


@login_required
def complaint_monthly_export(request):
    from django.core.exceptions import PermissionDenied
    from django.http import HttpResponse
    from apps.dashboard.services.complaint_monthly_service import ComplaintMonthlyService
    from apps.dashboard.services.complaint_monthly_export import generate_complaint_monthly_excel

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access.")

    hospital_id = request.GET.get("hospital")
    year = int(request.GET.get("year", timezone.now().year))
    month = int(request.GET.get("month", timezone.now().month))

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        return HttpResponse("Hospital parameter required", status=400)

    service = ComplaintMonthlyService(hospital_id=hospital_id, year=year, month=month)
    buf = generate_complaint_monthly_excel(service)

    month_label = f"{year}-{month:02d}"
    response = HttpResponse(
        buf.getvalue(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = f'attachment; filename="complaints_monthly_{month_label}.xlsx"'
    return response


def _build_kpi_blocks(kpi_data, satisfaction_data, moh_kpi_data, active_months):
    blocks = [
        {
            "label": "KPI #1 - Resolution to Patient Complaints",
            "numerator_label": "Total Number of Closed Complaints",
            "denominator_label": "Total Number of Complaints",
            "result_label": "Result (%)",
            "numerator_values": [kpi_data["months"][m]["closed"] for m in active_months],
            "denominator_values": [kpi_data["months"][m]["total"] for m in active_months],
            "result_values": [kpi_data["months"][m]["resolution_rate"] for m in active_months],
            "total_num": kpi_data["totals"]["closed"],
            "total_den": kpi_data["totals"]["total"],
            "total_res": kpi_data["totals"]["resolution_rate"],
        },
        {
            "label": "KPI #2 - 72-Hour Complaint Resolution Rate",
            "numerator_label": "Number of Complaints Resolved Within 72 Hours",
            "denominator_label": "Total Number of Complaints",
            "result_label": "Result (%)",
            "numerator_values": [kpi_data["months"][m]["resolved_72h"] for m in active_months],
            "denominator_values": [kpi_data["months"][m]["total"] for m in active_months],
            "result_values": [kpi_data["months"][m]["resolved_72h_rate"] for m in active_months],
            "total_num": kpi_data["totals"]["resolved_72h"],
            "total_den": kpi_data["totals"]["total"],
            "total_res": kpi_data["totals"]["resolved_72h_rate"],
        },
        {
            "label": "KPI #3 - Satisfaction Rate",
            "numerator_label": "Number of Satisfied Responses",
            "denominator_label": "Total Number of Patient Surveyed (Responses)",
            "result_label": "Result (%)",
            "numerator_values": [satisfaction_data["months"][m]["satisfied"] for m in active_months],
            "denominator_values": [satisfaction_data["months"][m]["surveyed"] for m in active_months],
            "result_values": [satisfaction_data["months"][m]["rate"] for m in active_months],
            "total_num": satisfaction_data["totals"]["satisfied"],
            "total_den": satisfaction_data["totals"]["surveyed"],
            "total_res": satisfaction_data["totals"]["rate"],
        },
        {
            "label": "Response Rate - Calls",
            "numerator_label": "Total Responses",
            "denominator_label": "Total Complaints",
            "result_label": "Result (%)",
            "numerator_values": [satisfaction_data["call_months"][m]["responses"] for m in active_months],
            "denominator_values": [satisfaction_data["call_months"][m]["total"] for m in active_months],
            "result_values": [satisfaction_data["call_months"][m]["rate"] for m in active_months],
            "total_num": satisfaction_data["call_totals"]["responses"],
            "total_den": satisfaction_data["call_totals"]["total"],
            "total_res": satisfaction_data["call_totals"]["rate"],
        },
        {
            "label": "Response Rate - Survey",
            "numerator_label": "Total Responses",
            "denominator_label": "Total Complaints",
            "result_label": "Result (%)",
            "numerator_values": [satisfaction_data["survey_months"][m]["responses"] for m in active_months],
            "denominator_values": [satisfaction_data["survey_months"][m]["total"] for m in active_months],
            "result_values": [satisfaction_data["survey_months"][m]["rate"] for m in active_months],
            "total_num": satisfaction_data["survey_totals"]["responses"],
            "total_den": satisfaction_data["survey_totals"]["total"],
            "total_res": satisfaction_data["survey_totals"]["rate"],
        },
        {
            "label": "MOH KPI",
            "numerator_label": "Complaints which received a (satisfied) scoring on its resolution",
            "denominator_label": "Total number of complaints received",
            "result_label": "Result (%)",
            "numerator_values": [moh_kpi_data["moh"]["months"][m]["satisfied_scoring"] for m in active_months],
            "denominator_values": [moh_kpi_data["moh"]["months"][m]["total"] for m in active_months],
            "result_values": [moh_kpi_data["moh"]["months"][m]["rate"] for m in active_months],
            "total_num": moh_kpi_data["moh"]["totals"]["satisfied_scoring"],
            "total_den": moh_kpi_data["moh"]["totals"]["total"],
            "total_res": moh_kpi_data["moh"]["totals"]["rate"],
        },
        {
            "label": "MOH KPI - Real Numbers",
            "numerator_label": "Complaints which received a (satisfied) scoring on its resolution",
            "denominator_label": "Total number of complaints received",
            "result_label": "Result (%)",
            "numerator_values": [moh_kpi_data["real"]["months"][m]["satisfied_scoring"] for m in active_months],
            "denominator_values": [moh_kpi_data["real"]["months"][m]["total"] for m in active_months],
            "result_values": [moh_kpi_data["real"]["months"][m]["rate"] for m in active_months],
            "total_num": moh_kpi_data["real"]["totals"]["satisfied_scoring"],
            "total_den": moh_kpi_data["real"]["totals"]["total"],
            "total_res": moh_kpi_data["real"]["totals"]["rate"],
        },
        {
            "label": "KPI #4 - 48-Hour Response Rate",
            "numerator_label": "Total Responses Within 48 Hours",
            "denominator_label": "Total Number of Complaints",
            "result_label": "Result (%)",
            "numerator_values": [kpi_data["months"][m]["resolved_48h"] for m in active_months],
            "denominator_values": [kpi_data["months"][m]["total"] for m in active_months],
            "result_values": [kpi_data["months"][m]["resolved_48h_rate"] for m in active_months],
            "total_num": kpi_data["totals"]["resolved_48h"],
            "total_den": kpi_data["totals"]["total"],
            "total_res": kpi_data["totals"]["resolved_48h_rate"],
        },
    ]
    return blocks


def _build_source_subrows(source_breakdown, keys, labels, active_months):
    rows = []
    for key, label in zip(keys, labels):
        total = sum(source_breakdown[m][key] for m in active_months)
        if total == 0:
            continue
        monthly = [{"count": source_breakdown[m][key]} for m in active_months]
        rows.append({"label": label, "total": total, "monthly": monthly})
    return rows


def _build_location_ratio_tables(location_ratios, active_months):
    import calendar
    tables = []
    for area, title, comp_col, pat_col in [
        ("ip", "In-Patient Complaints vs Patients", "In-Patient Complaints", "Total In-Patient"),
        ("op", "Out-Patient Complaints vs Patients", "Out-Patient Complaint", "Total Out-Patient"),
        ("er", "ER Complaints vs Patients", "ER Complaints", "Total ER Patients"),
    ]:
        rows = []
        for m in active_months:
            d = location_ratios["months"][m]
            rows.append({
                "month": calendar.month_abbr[m],
                "complaints": d[f"{area}_complaints"],
                "patients": d[f"{area}_patients"],
                "ratio": d[f"{area}_ratio"] * 100,
                "is_total": False,
            })
        t = location_ratios["totals"][area]
        rows.append({
            "month": "TOTAL",
            "complaints": t["complaints"],
            "patients": t["patients"],
            "ratio": t["ratio"] * 100,
            "is_total": True,
        })
        tables.append({
            "title": title, "complaint_col": comp_col, "patient_col": pat_col,
            "rows": rows,
        })
    return tables


@login_required
def complaint_quarterly_report(request):
    import json

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.complaint_quarterly_service import ComplaintQuarterlyService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    start_date_str = request.GET.get("start_date")
    end_date_str = request.GET.get("end_date")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/complaint_quarterly_report.html", {"no_data": True})

    from datetime import date as _date
    current_year = timezone.now().year
    if start_date_str and end_date_str:
        start_date = _date.fromisoformat(start_date_str)
        end_date = _date.fromisoformat(end_date_str)
    else:
        start_date = _date(current_year, 1, 1)
        end_date = _date(current_year, 12, 31)
        start_date_str = start_date.isoformat()
        end_date_str = end_date.isoformat()

    service = ComplaintQuarterlyService(hospital_id=hospital_id, start_date=start_date, end_date=end_date)
    active_months = service.active_months
    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "selected_year": start_date.year,
        "start_date": start_date_str,
        "end_date": end_date_str,
        "available_years": service.get_available_years(),
        "kpi_data": service.get_kpi_data(),
        "satisfaction_data": service.get_satisfaction_data(),
        "moh_kpi_data": service.get_moh_kpi_data(),
        "source_breakdown": service.get_source_breakdown(),
        "source_totals": service.get_source_totals(),
        "location_breakdown": service.get_location_breakdown(),
        "dept_type_breakdown": service.get_dept_type_breakdown(),
        "dept_type_monthly": service.get_dept_type_monthly_table(),
        "location_ratios": service.get_location_ratios(),
        "quarterly_volumes": service.get_quarterly_volumes(),
        "monthly_summary": service.get_monthly_summary(),
        "escalated": service.get_escalated_breakdown(),
        "response_rates": service.get_response_rates(),
        "chart_data_json": json.dumps(service.get_chart_data()),
    }

    kpi_data = context["kpi_data"]
    satisfaction_data = context["satisfaction_data"]
    moh_kpi_data = context["moh_kpi_data"]
    source_breakdown = context["source_breakdown"]
    source_totals = context["source_totals"]
    location_breakdown = context["location_breakdown"]
    dept_type_breakdown = context["dept_type_breakdown"]
    dept_type_monthly = context["dept_type_monthly"]
    location_ratios = context["location_ratios"]
    monthly_summary = context["monthly_summary"]
    escalated = context["escalated"]
    response_rates = context["response_rates"]

    import calendar as _cal
    context["month_labels"] = [_cal.month_abbr[m] for m in active_months]

    context["kpi_blocks"] = _build_kpi_blocks(kpi_data, satisfaction_data, moh_kpi_data, active_months)

    context["source_sub_external"] = _build_source_subrows(source_breakdown, ["moh", "chi"], ["MOH", "CHI"], active_months)
    context["source_sub_internal"] = _build_source_subrows(source_breakdown, ["patients", "relatives"], ["Patients", "Patient's relatives"], active_months)
    context["source_internal_monthly"] = [source_breakdown[m]["internal"] for m in active_months]
    context["source_total_monthly"] = [source_breakdown[m]["total"] for m in active_months]

    context["source_total_rows"] = [
        {"label": "Internal Complaints", "count": source_totals["internal"]["count"], "pct_label": "% Internal", "pct": source_totals["internal"]["pct"]},
        {"label": "External Complaints", "count": source_totals["external"]["count"], "pct_label": "% External", "pct": source_totals["external"]["pct"]},
    ]

    total_all = sum(location_breakdown[m]["total"] for m in active_months)
    context["location_rows"] = []
    for label, key in [("In-Patient", "ip"), ("Out-Patient", "op"), ("ER", "er")]:
        t = sum(location_breakdown[m][key] for m in active_months)
        context["location_rows"].append({
            "label": label, "total": t, "pct": round(t / total_all, 3) if total_all else 0,
            "monthly": [location_breakdown[m][key] for m in active_months], "is_total": False,
        })
    context["location_rows"].append({
        "label": "Total", "total": total_all, "pct": 1,
        "monthly": [location_breakdown[m]["total"] for m in active_months], "is_total": True,
    })

    context["dept_type_rows"] = []
    for label, key in [("Medical", "medical"), ("Administrative", "administrative"), ("Nursing", "nursing"), ("Support Services", "support")]:
        t = sum(dept_type_breakdown[m][key] for m in active_months)
        context["dept_type_rows"].append({
            "label": label, "total": t, "pct": round(t / total_all, 3) if total_all else 0,
            "monthly": [dept_type_breakdown[m][key] for m in active_months], "is_total": False,
        })
    context["dept_type_rows"].append({
        "label": "Total", "total": total_all, "pct": 1,
        "monthly": [dept_type_breakdown[m]["total"] for m in active_months], "is_total": True,
    })

    context["dept_monthly_rows"] = []
    for mr in dept_type_monthly["months"]:
        context["dept_monthly_rows"].append({
            "month": mr["month"], "medical": mr["medical"], "administrative": mr["administrative"],
            "nursing": mr["nursing"], "support": mr["support"], "total": mr["total"],
            "is_total": False, "is_pct": False,
        })
    context["dept_monthly_rows"].append({
        "month": "TOTAL",
        "medical": dept_type_monthly["totals"]["medical"], "administrative": dept_type_monthly["totals"]["administrative"],
        "nursing": dept_type_monthly["totals"]["nursing"], "support": dept_type_monthly["totals"]["support"],
        "total": dept_type_monthly["totals"]["total"],
        "is_total": True, "is_pct": False,
    })
    context["dept_monthly_rows"].append({
        "month": "% From Total",
        "medical": round(dept_type_monthly["percentages"]["medical"] * 100, 1),
        "administrative": round(dept_type_monthly["percentages"]["administrative"] * 100, 1),
        "nursing": round(dept_type_monthly["percentages"]["nursing"] * 100, 1),
        "support": round(dept_type_monthly["percentages"]["support"] * 100, 1),
        "total": round(dept_type_monthly["percentages"]["total"] * 100, 1),
        "is_total": False, "is_pct": True,
    })

    context["location_ratio_tables"] = _build_location_ratio_tables(location_ratios, active_months)

    context["monthly_summary_json"] = json.dumps(monthly_summary)
    context["dept_type_rows_json"] = json.dumps(context["dept_type_rows"])

    per_dept = service.get_per_department_breakdown()
    cat_configs = [
        ("Medical", "medical"),
        ("Administrative", "administrative"),
        ("Nursing", "nursing"),
        ("Support Services", "support_services"),
    ]
    escalated_by_cat = escalated["by_category"]
    escalated_table = []
    for cat_label, cat_key in cat_configs:
        depts = escalated_by_cat.get(cat_key, {})
        tc = sum(d["total"] for d in per_dept["categories"].get(cat_key, []))
        esc_total = sum(depts.values())
        sorted_depts = sorted(depts.items(), key=lambda x: -x[1])
        escalated_table.append({
            "label": cat_label,
            "sub_depts": [{"name": n, "count": c} for n, c in sorted_depts],
            "total_escalated": esc_total,
            "total_complaints": tc,
            "escalation_rate": round(esc_total / tc, 3) if tc else 0,
        })
    context["escalated_table"] = escalated_table
    context["escalated_json"] = json.dumps({
        "by_source": escalated.get("by_source", {}),
        "total_escalated": escalated.get("total_escalated", 0),
        "total_complaints": escalated.get("total_complaints", 0),
        "escalation_rate": escalated.get("escalation_rate", 0),
        "by_category_rates": {e["label"]: e["escalation_rate"] for e in escalated_table},
        "by_category_counts": {e["label"]: e["total_escalated"] for e in escalated_table},
    })

    context["per_dept"] = per_dept
    context["per_dept_json"] = json.dumps({
        "categories": {k: v for k, v in per_dept["categories"].items()},
        "source_totals": per_dept["source_totals"],
        "avg_response_days": per_dept.get("avg_response_days", {}),
    })

    dept_category_tables = []
    for cat_label, cat_key in cat_configs:
        depts = per_dept["categories"].get(cat_key, [])
        totals = {
            "moh": sum(d["moh"] for d in depts),
            "chi": sum(d["chi"] for d in depts),
            "internal": sum(d["internal"] for d in depts),
            "total": sum(d["total"] for d in depts),
            "escalated": sum(d["escalated"] for d in depts),
        }
        dept_category_tables.append({"label": cat_label, "depts": depts, "totals": totals})
    context["dept_category_tables"] = dept_category_tables

    st = per_dept["source_totals"]
    context["per_dept_source_rows"] = [
        {"label": "MOH", "count": st["moh"], "is_total": False},
        {"label": "CHI", "count": st["chi"], "is_total": False},
        {"label": "Internal", "count": st["internal"], "is_total": False},
        {"label": "Total", "count": st["total"], "is_total": True},
    ]

    context["response_rates_json"] = json.dumps(response_rates)

    context["response_rate_source_list"] = [
        {"label": "Internal Complaints", "total": response_rates["internal"]["total"], "individual": response_rates["internal"].get("individual", [])},
        {"label": "MOH Complaints", "total": response_rates["moh"]["total"], "individual": response_rates["moh"].get("individual", [])},
        {"label": "CHI Complaints", "total": response_rates["chi"]["total"], "individual": response_rates["chi"].get("individual", [])},
    ]

    return render(request, "dashboard/complaint_quarterly_report.html", context)


@login_required
def complaint_quarterly_export(request):
    from django.core.exceptions import PermissionDenied
    from django.http import HttpResponse
    from apps.dashboard.services.complaint_quarterly_service import ComplaintQuarterlyService
    from apps.dashboard.services.complaint_quarterly_export import generate_complaint_quarterly_excel

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin()):
        raise PermissionDenied("Only PX Admins and Hospital Admins can access.")

    hospital_id = request.GET.get("hospital")
    start_date_str = request.GET.get("start_date")
    end_date_str = request.GET.get("end_date")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        return HttpResponse("Hospital parameter required", status=400)

    from datetime import date as _date
    current_year = timezone.now().year
    if start_date_str and end_date_str:
        start_date = _date.fromisoformat(start_date_str)
        end_date = _date.fromisoformat(end_date_str)
    else:
        start_date = _date(current_year, 1, 1)
        end_date = _date(current_year, 12, 31)

    service = ComplaintQuarterlyService(hospital_id=hospital_id, start_date=start_date, end_date=end_date)
    buf = generate_complaint_quarterly_excel(service)

    response = HttpResponse(
        buf.getvalue(),
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    date_label = f"{start_date.strftime('%Y%m%d')}-{end_date.strftime('%Y%m%d')}"
    response["Content-Disposition"] = f'attachment; filename="complaints_{date_label}.xlsx"'
    return response


@login_required
def comments_report(request):
    import json

    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.comments_report_service import CommentsReportService
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    period = request.GET.get("period", "monthly")
    year = request.GET.get("year")
    quarter = request.GET.get("quarter")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/comments_report.html", {"no_data": True})

    year = int(year) if year else timezone.now().year
    quarter = int(quarter) if quarter else ((timezone.now().month - 1) // 3 + 1)

    service = CommentsReportService(hospital_id=hospital_id, year=year, quarter=quarter)
    available_periods = service.get_available_periods()
    summary = service.get_summary()
    by_category = service.get_category_breakdown()
    by_sentiment = service.get_sentiment_breakdown()
    by_subcategory = service.get_subcategory_breakdown()
    action_plans = service.get_action_plans()
    chart_data = service.get_chart_data()

    fmt = lambda n: f"{n:,}"

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "selected_year": year,
        "selected_quarter": quarter,
        "available_periods": available_periods,
        "summary": summary,
        "by_category": by_category,
        "by_sentiment": by_sentiment,
        "by_subcategory": by_subcategory,
        "action_plans": action_plans,
        "chart_data_json": json.dumps(chart_data),
    }
    return render(request, "dashboard/comments_report.html", context)


@login_required
def standards_dashboard(request):
    from django.core.exceptions import PermissionDenied
    from apps.dashboard.services.standards_report_service import StandardsReportService
    from apps.standards.models import StandardSource
    from apps.organizations.models import Hospital

    user = request.user
    if not (user.is_px_admin() or user.is_hospital_admin() or user.is_px_employee() or user.is_px_management()):
        raise PermissionDenied("Only PX Admins, Hospital Admins, and PX Employee and PX Management can access.")

    hospital_id = request.GET.get("hospital")
    source_code = request.GET.get("source", "")

    if user.is_hospital_admin() and user.hospital:
        hospital_id = hospital_id or str(user.hospital.id)
    elif user.is_px_admin() and request.tenant_hospital:
        hospital_id = hospital_id or str(request.tenant_hospital.id)

    if not hospital_id:
        first = Hospital.objects.first()
        if first:
            hospital_id = str(first.id)

    if not hospital_id:
        return render(request, "dashboard/standards_dashboard.html", {"no_data": True})

    service = StandardsReportService(hospital_id=hospital_id, source_code=source_code or None)

    summary = service.get_summary()
    if summary["total"] == 0:
        return render(request, "dashboard/standards_dashboard.html", {
            "no_data": True,
            "hospitals": Hospital.objects.all(),
            "selected_hospital": hospital_id,
            "sources": StandardSource.objects.filter(is_active=True),
            "selected_source": source_code,
        })

    category_breakdown = service.get_category_breakdown()
    corrective_actions = service.get_corrective_actions()
    standards_table = service.get_standards_table()
    score_gauge = service.get_score_gauge_data()

    import json

    context = {
        "hospitals": Hospital.objects.all(),
        "selected_hospital": hospital_id,
        "sources": StandardSource.objects.filter(is_active=True),
        "selected_source": source_code,
        "summary": summary,
        "category_breakdown": category_breakdown,
        "corrective_actions": corrective_actions,
        "standards_table": standards_table,
        "score_gauge": score_gauge,
        "chart_data_json": service.get_all_chart_data(),
    }
    return render(request, "dashboard/standards_dashboard.html", context)


@login_required
def my_performance(request):
    from apps.analytics.services.analytics_service import UnifiedAnalyticsService
    from apps.organizations.models import Staff

    user = request.user

    staff_member = Staff.objects.filter(user=user).select_related("department", "hospital").first()
    if not staff_member:
        messages.error(request, _("No staff profile found for your account."))
        return redirect("dashboard:my_dashboard")

    date_range = request.GET.get("date_range", "30d")
    custom_start = request.GET.get("custom_start")
    custom_end = request.GET.get("custom_end")

    if custom_start:
        from datetime import datetime

        custom_start = datetime.fromisoformat(custom_start)
    if custom_end:
        from datetime import datetime

        custom_end = datetime.fromisoformat(custom_end)

    start_date, end_date = UnifiedAnalyticsService._get_date_range(date_range, custom_start, custom_end)

    performance = UnifiedAnalyticsService.get_staff_detailed_performance(
        staff_id=str(staff_member.user_id),
        user=user,
        date_range=date_range,
        custom_start=custom_start,
        custom_end=custom_end,
    )

    trends = UnifiedAnalyticsService.get_staff_performance_trends(
        staff_id=str(staff_member.user_id), user=user, months=6
    )

    if staff_member.department:
        benchmarks = UnifiedAnalyticsService.get_department_benchmarks(
            user=user,
            department_id=str(staff_member.department.id),
            date_range=date_range,
        )
    else:
        benchmarks = None

    context = {
        "staff_member": staff_member,
        "performance": performance,
        "trends": trends,
        "benchmarks": benchmarks,
        "date_range": date_range,
        "start_date": start_date,
        "end_date": end_date,
    }
    return render(request, "dashboard/my_performance.html", context)
