"""
KPI Report Calculation Service

This service calculates KPI metrics for monthly reports based on
the complaint and survey data in the system.
"""

import logging
from datetime import datetime, timedelta
from decimal import Decimal
from typing import Dict, List, Optional

from django.db.models import Avg, Count, F, Q
from django.utils import timezone

from apps.complaints.models import Complaint, ComplaintStatus, ComplaintSource
from apps.organizations.models import Department
from apps.surveys.models import SurveyInstance, SurveyStatus, SurveyTemplate

from .kpi_models import (
    KPIReport,
    KPIReportDepartmentBreakdown,
    KPIReportLocationBreakdown,
    KPIReportMonthlyData,
    KPIReportSourceBreakdown,
    KPIReportStatus,
    KPIReportType,
)


def _dt(year, month, day=1):
    """Create a timezone-aware datetime to avoid naive datetime warnings."""
    return timezone.make_aware(datetime(year, month, day))

DEPARTMENT_CATEGORY_KEYWORDS = {
    "medical": [
        "medical",
        "surgery",
        "cardiology",
        "orthopedics",
        "pediatrics",
        "obstetrics",
        "gynecology",
        "er",
        "emergency",
        "lab",
        "icu",
        "clinic",
        "ward",
        "physiotherapy",
        "psychiatric",
        "ophthalmology",
        "pharmacy",
        "radiology",
        "pathology",
        "anesthesia",
        "ent",
        "dermatology",
        "urology",
        "neurology",
        "oncology",
        "nursery",
    ],
    "nursing": [
        "nursing",
        "nurse",
        "iv medication room nursing",
        "long term nursing",
        "vaccination room nursing",
        "pediatric inpatient",
    ],
    "admin": [
        "administration",
        "admin",
        "reception",
        "manager",
        "approval",
        "report",
        "finance",
        "it",
        "hr",
        "medical reports",
        "appointments",
        "on-duty",
        "opd reception",
        "outpatient reception",
    ],
    "support": [
        "housekeeping",
        "maintenance",
        "security",
        "cafeteria",
        "transport",
        "support",
    ],
}

logger = logging.getLogger(__name__)


DEPT_CATEGORY_MAP = {
    "medical": "medical",
    "non_medical": "non_medical",
    "nursing": "nursing",
    "support_services": "support_services",
    "": "other",
}


def _get_dept_category(dept_name: str) -> str:
    """Look up a department's category from the Department model."""
    try:
        dept = Department.objects.filter(name__iexact=dept_name).first()
        if dept and dept.category:
            return DEPT_CATEGORY_MAP.get(dept.category, "other")
    except Exception:
        pass
    name_lower = dept_name.lower()
    if any(k in name_lower for k in DEPARTMENT_CATEGORY_KEYWORDS["medical"]):
        return "medical"
    if any(k in name_lower for k in DEPARTMENT_CATEGORY_KEYWORDS["nursing"]):
        return "nursing"
    if any(k in name_lower for k in DEPARTMENT_CATEGORY_KEYWORDS["admin"]):
        return "non_medical"
    if any(k in name_lower for k in DEPARTMENT_CATEGORY_KEYWORDS["support"]):
        return "support_services"
    return "other"


class KPICalculationService:
    """
    Service for calculating KPI report metrics

    Handles the complex calculations for each KPI type:
    - 72H Resolution Rate
    - Patient Experience Score
    - Satisfaction with Resolution
    - Response Rate
    - Activation Time
    - Unactivated Rate
    """

    @classmethod
    def generate_monthly_report(cls, report_type: str, hospital, year: int, month: int, generated_by=None) -> KPIReport:
        """
        Generate a complete monthly KPI report

        Args:
            report_type: Type of KPI report (from KPIReportType)
            hospital: Hospital instance
            year: Report year
            month: Report month (1-12)
            generated_by: User who generated the report (optional)

        Returns:
            KPIReport instance
        """
        # Get or create the report
        report, created = KPIReport.objects.get_or_create(
            report_type=report_type,
            hospital=hospital,
            year=year,
            month=month,
            defaults={
                "report_date": timezone.now().date(),
                "status": KPIReportStatus.PENDING,
                "generated_by": generated_by,
                "target_percentage": (
                    0.00
                    if report_type == KPIReportType.UNACTIVATED
                    else 85.00
                    if report_type == KPIReportType.PATIENT_EXPERIENCE
                    else 80.00
                    if report_type == KPIReportType.RESPONSE_RATE
                    else 95.00
                ),
                "threshold_percentage": (
                    5.00
                    if report_type == KPIReportType.UNACTIVATED
                    else 78.00
                    if report_type == KPIReportType.PATIENT_EXPERIENCE
                    else 70.00
                    if report_type == KPIReportType.RESPONSE_RATE
                    else 90.00
                ),
                "threshold_percentage": (
                    78.00
                    if report_type == KPIReportType.PATIENT_EXPERIENCE
                    else 70.00
                    if report_type == KPIReportType.RESPONSE_RATE
                    else 90.00
                ),
            },
        )

        if not created and report.status == KPIReportStatus.COMPLETED:
            # Report already exists and is complete - return it
            return report

        # Update status to generating
        report.status = KPIReportStatus.GENERATING
        report.save()

        try:
            # Calculate based on report type
            if report_type == KPIReportType.RESOLUTION_72H:
                cls._calculate_72h_resolution(report)
            elif report_type == KPIReportType.PATIENT_EXPERIENCE:
                cls._calculate_patient_experience(report)
            elif report_type == KPIReportType.SATISFACTION_RESOLUTION:
                cls._calculate_satisfaction_resolution(report)
            elif report_type == KPIReportType.N_PAD_001:
                cls._calculate_n_pad_001(report)
            elif report_type == KPIReportType.RESPONSE_RATE:
                cls._calculate_response_rate(report)
            elif report_type == KPIReportType.ACTIVATION_2H:
                cls._calculate_activation_2h(report)
            elif report_type == KPIReportType.UNACTIVATED:
                cls._calculate_unactivated(report)
            elif report_type == KPIReportType.MOH_24H:
                cls._calculate_moh_24h(report)
            elif report_type == KPIReportType.CHI_48H:
                cls._calculate_chi_48h(report)

            # Mark as completed
            report.status = KPIReportStatus.COMPLETED
            report.generated_at = timezone.now()
            report.save()

            # Generate AI analysis for supported report types
            supported_types = [
                KPIReportType.RESOLUTION_72H,
                KPIReportType.PATIENT_EXPERIENCE,
                KPIReportType.N_PAD_001,
                KPIReportType.SATISFACTION_RESOLUTION,
                KPIReportType.RESPONSE_RATE,
                KPIReportType.ACTIVATION_2H,
                KPIReportType.UNACTIVATED,
                KPIReportType.MOH_24H,
                KPIReportType.CHI_48H,
            ]
            if report_type in supported_types:
                try:
                    cls.generate_ai_analysis(report)
                    logger.info(f"AI analysis generated for KPI report {report.id}")
                except Exception as ai_error:
                    logger.warning(f"Failed to generate AI analysis for report {report.id}: {ai_error}")

            logger.info(f"KPI Report {report.id} generated successfully")

        except Exception as e:
            logger.exception(f"Error generating KPI report {report.id}")
            report.status = KPIReportStatus.FAILED
            report.error_message = str(e)
            report.save()
            raise

        return report

    @classmethod
    def _calculate_72h_resolution(cls, report: KPIReport):
        """Calculate 72-Hour Resolution Rate (MOH-2)"""
        # Get date range for the report period
        start_date = _dt(report.year, report.month, 1)
        if report.month == 12:
            end_date = _dt(report.year + 1, 1, 1)
        else:
            end_date = _dt(report.year, report.month + 1, 1)

        # Get all months data for YTD (year to date)
        year_start = _dt(report.year, 1, 1)

        # Calculate for each month
        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            # Get complaints for this month
            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",  # Only actual complaints
            )

            # Count total complaints
            denominator = complaints.count()

            # Count resolved within 72 hours
            numerator = 0
            for complaint in complaints:
                if complaint.resolved_at and complaint.activated_at:
                    resolution_time = complaint.resolved_at - complaint.activated_at
                    if resolution_time.total_seconds() <= 72 * 3600:  # 72 hours
                        numerator += 1

            # Create or update monthly data
            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage

            # Store source breakdown in details
            source_data = cls._get_source_breakdown(complaints)
            monthly_data.details = {"source_breakdown": source_data}
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        # Update report totals
        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        # Create source breakdown for pie chart
        all_complaints = Complaint.objects.filter(
            hospital=report.hospital, created_at__gte=year_start, created_at__lt=end_date, complaint_type="complaint"
        )
        cls._create_source_breakdowns(report, all_complaints)

        # Create department breakdown
        cls._create_department_breakdown(report, all_complaints)

        # Create location breakdown
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_patient_experience(cls, report: KPIReport):
        """Calculate Patient Experience Score (MOH-1)"""
        # Get date range
        year_start = _dt(report.year, 1, 1)
        start_date = _dt(report.year, report.month, 1)
        if report.month == 12:
            end_date = _dt(report.year + 1, 1, 1)
        else:
            end_date = _dt(report.year, report.month + 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            # Get completed surveys for patient experience
            surveys = SurveyInstance.objects.filter(
                survey_template__hospital=report.hospital,
                status=SurveyStatus.COMPLETED,
                completed_at__gte=month_start,
                completed_at__lt=month_end,
                survey_template__survey_type__in=["stage", "general"],
            )

            denominator = surveys.count()

            # Count positive responses (score >= 4 out of 5)
            numerator = surveys.filter(total_score__gte=4).count()

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage

            # Store average score
            avg_score = surveys.aggregate(avg=Avg("total_score"))["avg"] or 0
            monthly_data.details = {"avg_score": float(round(avg_score, 2))}
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

    @classmethod
    def _calculate_satisfaction_resolution(cls, report: KPIReport):
        """Calculate Overall Satisfaction with Resolution (MOH-3)

        Based on complaint.satisfaction field:
        - Denominator: complaints with satisfaction in (satisfied, neutral, dissatisfied)
        - Numerator: complaints with satisfaction = 'satisfied'
        """
        year_start = _dt(report.year, 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
                satisfaction__in=["satisfied", "neutral", "dissatisfied"],
                satisfaction_set_at__isnull=False,
            )

            denominator = complaints.count()
            numerator = complaints.filter(satisfaction="satisfied").count()

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=(
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            ),
            complaint_type="complaint",
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_n_pad_001(cls, report: KPIReport):
        """Calculate N-PAD-001 Resolution Rate"""
        year_start = _dt(report.year, 1, 1)
        if report.month == 12:
            year_end = _dt(report.year + 1, 1, 1)
        else:
            year_end = _dt(report.year, report.month + 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            )

            denominator = complaints.count()
            numerator = complaints.filter(status__in=[ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED]).count()

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital, created_at__gte=year_start, created_at__lt=year_end, complaint_type="complaint"
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_response_rate(cls, report: KPIReport):
        """Calculate Department Response Rate (48h)"""
        year_start = _dt(report.year, 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            )

            denominator = complaints.count()

            numerator = 0
            for complaint in complaints:
                first_response = (
                    complaint.updates.filter(update_type__in=["communication", "resolution"])
                    .order_by("created_at")
                    .first()
                )
                if first_response and complaint.created_at:
                    response_time = first_response.created_at - complaint.created_at
                    if response_time.total_seconds() <= 48 * 3600:
                        numerator += 1

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=(
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            ),
            complaint_type="complaint",
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_activation_2h(cls, report: KPIReport):
        """Calculate Complaint Activation Within 2 Hours"""
        year_start = _dt(report.year, 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            # Get complaints with assigned_to (activated)
            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            )

            denominator = complaints.count()

            # Count activated within 2 hours
            numerator = 0
            for complaint in complaints:
                if complaint.assigned_at and complaint.created_at:
                    activation_time = complaint.assigned_at - complaint.created_at
                    if activation_time.total_seconds() <= 2 * 3600:
                        numerator += 1

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": numerator,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=(
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            ),
            complaint_type="complaint",
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_unactivated(cls, report: KPIReport):
        """Calculate Unactivated Filled Complaints Rate"""
        from apps.dashboard.models import ComplaintRequest

        year_start = _dt(report.year, 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            )

            denominator = complaints.count()

            filled_unactivated = (
                complaints.filter(
                    complaint_request_records__filled=True,
                    assigned_to__isnull=True,
                )
                .distinct()
                .count()
            )

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={
                    "numerator": filled_unactivated,
                    "denominator": denominator,
                },
            )
            monthly_data.numerator = filled_unactivated
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage > report.threshold_percentage
            monthly_data.save()

            total_numerator += filled_unactivated
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=(
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            ),
            complaint_type="complaint",
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_moh_24h(cls, report: KPIReport):
        """Calculate 24-Hour MOH Complaint Resolution Rate"""
        year_start = _dt(report.year, 1, 1)
        if report.month == 12:
            end_date = _dt(report.year + 1, 1, 1)
        else:
            end_date = _dt(report.year, report.month + 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
                source__code__iexact="moh",
            )

            denominator = complaints.count()
            numerator = 0
            for complaint in complaints:
                if complaint.resolved_at and complaint.activated_at:
                    resolution_time = complaint.resolved_at - complaint.activated_at
                    if resolution_time.total_seconds() <= 24 * 3600:
                        numerator += 1

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={"numerator": numerator, "denominator": denominator},
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=end_date,
            complaint_type="complaint",
            source__code__iexact="moh",
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _calculate_chi_48h(cls, report: KPIReport):
        """Calculate 48-Hour CHI Complaint Resolution Rate"""
        year_start = _dt(report.year, 1, 1)
        if report.month == 12:
            end_date = _dt(report.year + 1, 1, 1)
        else:
            end_date = _dt(report.year, report.month + 1, 1)

        total_numerator = 0
        total_denominator = 0

        for month in range(1, 13):
            month_start = _dt(report.year, month, 1)
            if month == 12:
                month_end = _dt(report.year + 1, 1, 1)
            else:
                month_end = _dt(report.year, month + 1, 1)

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            ).filter(
                Q(source__code__iexact="chi") | Q(source__code__iexact="cchi")
            )

            denominator = complaints.count()
            numerator = 0
            for complaint in complaints:
                if complaint.resolved_at and complaint.activated_at:
                    resolution_time = complaint.resolved_at - complaint.activated_at
                    if resolution_time.total_seconds() <= 48 * 3600:
                        numerator += 1

            monthly_data, _ = KPIReportMonthlyData.objects.get_or_create(
                kpi_report=report,
                month=month,
                defaults={"numerator": numerator, "denominator": denominator},
            )
            monthly_data.numerator = numerator
            monthly_data.denominator = denominator
            monthly_data.calculate_percentage()
            monthly_data.is_below_target = monthly_data.percentage < report.target_percentage
            monthly_data.save()

            total_numerator += numerator
            total_denominator += denominator

        report.total_numerator = total_numerator
        report.total_denominator = total_denominator
        if total_denominator > 0:
            report.overall_result = Decimal(str((total_numerator / total_denominator) * 100))
        report.save()

        all_complaints = Complaint.objects.filter(
            hospital=report.hospital,
            created_at__gte=year_start,
            created_at__lt=end_date,
            complaint_type="complaint",
        ).filter(
            Q(source__code__iexact="chi") | Q(source__code__iexact="cchi")
        )
        cls._create_source_breakdowns(report, all_complaints)
        cls._create_department_breakdown(report, all_complaints)
        cls._create_location_breakdowns(report, all_complaints)

    @classmethod
    def _get_source_breakdown(cls, complaints) -> Dict[str, int]:
        """Get breakdown of complaints by source"""
        sources = {}
        for complaint in complaints:
            source_name = complaint.source.name_en if complaint.source else "Other"
            sources[source_name] = sources.get(source_name, 0) + 1
        return sources

    @classmethod
    def _create_source_breakdowns(cls, report: KPIReport, complaints):
        """Create source breakdown records for pie chart"""
        # Delete existing
        report.source_breakdowns.all().delete()

        # Count by source
        source_counts = {}
        total = complaints.count()

        for complaint in complaints:
            source_name = complaint.source.name_en if complaint.source else "Other"
            source_counts[source_name] = source_counts.get(source_name, 0) + 1

        # Create records
        for source_name, count in source_counts.items():
            percentage = (count / total * 100) if total > 0 else 0
            KPIReportSourceBreakdown.objects.create(
                kpi_report=report, source_name=source_name, complaint_count=count, percentage=Decimal(str(percentage))
            )

    @classmethod
    def _create_department_breakdown(cls, report: KPIReport, complaints):
        """Create department breakdown records"""
        report.department_breakdowns.all().delete()

        category_map = {
            "medical": "medical",
            "non_medical": "non_medical",
            "nursing": "nursing",
            "support_services": "support_services",
        }

        for dept_cat, db_cat in category_map.items():
            dept_complaints = complaints.filter(department__category=dept_cat).distinct()

            complaint_count = dept_complaints.count()
            resolved_count = dept_complaints.filter(
                status__in=[ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED]
            ).count()

            avg_days = None
            resolved_complaints = dept_complaints.filter(
                resolved_at__isnull=False, activated_at__isnull=False
            )
            if resolved_complaints.exists():
                total_days = 0
                for c in resolved_complaints:
                    days = (c.resolved_at - c.activated_at).total_seconds() / (24 * 3600)
                    total_days += days
                avg_days = Decimal(str(total_days / resolved_complaints.count()))

            top_areas_list = []
            seen = set()
            for c in dept_complaints[:20]:
                if c.category:
                    name = c.category.name_en
                    if name not in seen:
                        top_areas_list.append(name)
                        seen.add(name)
            top_areas = "\n".join(top_areas_list[:5]) if top_areas_list else ""

            KPIReportDepartmentBreakdown.objects.create(
                kpi_report=report,
                department_category=db_cat,
                complaint_count=complaint_count,
                resolved_count=resolved_count,
                avg_resolution_days=avg_days,
                top_areas=top_areas,
            )

    @classmethod
    def _create_location_breakdowns(cls, report: KPIReport, complaints):
        """Create location breakdown records (Inpatient, Outpatient, Emergency)"""
        report.location_breakdowns.all().delete()

        location_categories = {
            "Inpatient": ["inpatient", "in-patient", "ip", "in patient"],
            "Outpatient": ["outpatient", "out-patient", "opd", "out patient", "op"],
            "Emergency": ["emergency", "er", "ed", "a&e", "accident"],
        }

        total = complaints.count()
        if total == 0:
            return

        for loc_type, keywords in location_categories.items():
            q_objects = Q()
            for keyword in keywords:
                q_objects |= Q(department__location_type__icontains=keyword)

            loc_complaints = complaints.filter(q_objects).distinct()
            count = loc_complaints.count()
            percentage = (count / total * 100) if total > 0 else 0

            KPIReportLocationBreakdown.objects.create(
                kpi_report=report,
                location_type=loc_type,
                complaint_count=count,
                percentage=Decimal(str(round(percentage, 2))),
            )

    @classmethod
    def generate_ai_analysis(cls, report: KPIReport) -> dict:
        """
        Generate AI analysis for a KPI report.

        Dispatches to specific analysis methods based on report type.

        Args:
            report: KPIReport instance

        Returns:
            Dictionary containing AI-generated analysis
        """
        if report.report_type == KPIReportType.RESOLUTION_72H:
            return cls._generate_72h_resolution_analysis(report)
        elif report.report_type == KPIReportType.PATIENT_EXPERIENCE:
            return cls._generate_patient_experience_analysis(report)
        elif report.report_type == KPIReportType.N_PAD_001:
            return cls._generate_n_pad_001_analysis(report)
        elif report.report_type == KPIReportType.SATISFACTION_RESOLUTION:
            return cls._generate_satisfaction_resolution_analysis(report)
        elif report.report_type == KPIReportType.RESPONSE_RATE:
            return cls._generate_response_rate_analysis(report)
        elif report.report_type == KPIReportType.ACTIVATION_2H:
            return cls._generate_activation_2h_analysis(report)
        elif report.report_type == KPIReportType.UNACTIVATED:
            return cls._generate_unactivated_analysis(report)
        else:
            logger.warning(f"AI analysis not supported for report type: {report.report_type}")
            return {"error": "Analysis not supported for this report type"}

    @classmethod
    def _generate_72h_resolution_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for 72-Hour Resolution Rate report"""
        from apps.core.ai_service import AIService

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_complaints = report.total_denominator
            resolved_within_72h = report.total_numerator

            # Get monthly data
            monthly_data = report.monthly_data.all().order_by("month")
            monthly_breakdown = []
            for md in monthly_data:
                if md.denominator > 0:
                    monthly_breakdown.append(
                        {
                            "month": md.month,
                            "percentage": float(md.percentage) if md.percentage else 0,
                            "resolved": md.numerator,
                            "total": md.denominator,
                        }
                    )

            # Get source breakdowns
            source_breakdowns = report.source_breakdowns.all()
            source_data = []
            for sb in source_breakdowns:
                source_data.append(
                    {
                        "source": sb.source_name,
                        "complaints": sb.complaint_count,
                        "percentage": float(sb.percentage) if sb.percentage else 0,
                    }
                )

            # Get department breakdowns
            dept_breakdowns = report.department_breakdowns.all()
            dept_data = []
            for db in dept_breakdowns:
                dept_data.append(
                    {
                        "category": db.get_department_category_display(),
                        "complaints": db.complaint_count,
                        "resolved": db.resolved_count,
                        "avg_days": float(db.avg_resolution_days) if db.avg_resolution_days else None,
                    }
                )

            # Calculate resolution time buckets
            year_start = _dt(report.year, 1, 1)
            year_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            all_complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=year_start,
                created_at__lt=year_end,
                complaint_type="complaint",
            )

            complaints = all_complaints.filter(
                status__in=[ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED],
            )

            resolved_count = complaints.count()

            resolved_24h = resolved_48h = resolved_72h = resolved_over_72h = 0
            dept_response_times = {}

            for c in complaints:
                if c.resolved_at and c.activated_at:
                    hours = (c.resolved_at - c.activated_at).total_seconds() / 3600
                    if hours <= 24:
                        resolved_24h += 1
                    elif hours <= 48:
                        resolved_48h += 1
                    elif hours <= 72:
                        resolved_72h += 1
                    else:
                        resolved_over_72h += 1

                    dept_name = c.department.name if c.department else "Unassigned"
                    if dept_name not in dept_response_times:
                        dept_response_times[dept_name] = []
                    dept_response_times[dept_name].append(hours / 24)

            # G2: Categorize slow departments into 4 categories
            medical_slow = []
            nursing_slow = []
            admin_slow = []
            support_slow = []

            for dept, days_list in dept_response_times.items():
                if days_list:
                    avg_days = sum(days_list) / len(days_list)
                    entry = {"name": dept, "avg_days": round(avg_days, 1), "count": len(days_list)}
                    cat = _get_dept_category(dept)
                    if cat == "medical":
                        medical_slow.append(entry)
                    elif cat == "nursing":
                        nursing_slow.append(entry)
                    elif cat == "non_medical":
                        admin_slow.append(entry)
                    elif cat == "support_services":
                        support_slow.append(entry)

            medical_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            nursing_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            admin_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            support_slow.sort(key=lambda x: x["avg_days"], reverse=True)

            # G3: Per-source resolution time buckets (CCHI and MOH)
            moh_complaints = all_complaints.filter(
                status__in=[ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED],
                source__code__iexact="moh",
            )
            cchi_complaints = all_complaints.filter(
                status__in=[ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED],
            ).filter(
                Q(source__code__iexact="chi") | Q(source__code__iexact="cchi")
            )

            moh_24h = moh_48h = moh_72h = moh_over = moh_total = 0
            for c in moh_complaints:
                moh_total += 1
                if c.resolved_at and c.activated_at:
                    hours = (c.resolved_at - c.activated_at).total_seconds() / 3600
                    if hours <= 24:
                        moh_24h += 1
                    elif hours <= 48:
                        moh_48h += 1
                    elif hours <= 72:
                        moh_72h += 1
                    else:
                        moh_over += 1

            cchi_24h = cchi_48h = cchi_72h = cchi_over = cchi_total = 0
            for c in cchi_complaints:
                cchi_total += 1
                if c.resolved_at and c.activated_at:
                    hours = (c.resolved_at - c.activated_at).total_seconds() / 3600
                    if hours <= 24:
                        cchi_24h += 1
                    elif hours <= 48:
                        cchi_48h += 1
                    elif hours <= 72:
                        cchi_72h += 1
                    else:
                        cchi_over += 1

            # G4: Count complaints lacking responses
            complaints_no_response = 0
            for c in all_complaints:
                has_response = c.updates.filter(update_type="response").exists()
                if not has_response:
                    complaints_no_response += 1

            escalated_count = all_complaints.filter(updates__update_type="escalation").distinct().count()
            closed_count = all_complaints.filter(status=ComplaintStatus.CLOSED).count()

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage)
            performance_status = (
                "met"
                if overall_percentage >= target_percentage
                else "below threshold"
                if overall_percentage >= threshold_percentage
                else "below threshold - action needed"
            )

            # G5: Use resolved_count as denominator for time buckets
            prompt = f"""Analyze this 72-Hour Complaint Resolution KPI report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Overall Resolution Rate (≤72h): {overall_percentage:.2f}%
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {performance_status}
- Total Complaints: {total_complaints}
- Total Resolved: {resolved_count}
- Resolved within 72h: {resolved_within_72h}

RESOLUTION TIME BREAKDOWN (of resolved complaints):
- Within 24h: {resolved_24h} ({(resolved_24h / resolved_count * 100) if resolved_count else 0:.2f}%)
- Within 48h: {resolved_48h} ({(resolved_48h / resolved_count * 100) if resolved_count else 0:.2f}%)
- Within 72h: {resolved_72h} ({(resolved_72h / resolved_count * 100) if resolved_count else 0:.2f}%)
- After 72h: {resolved_over_72h} ({(resolved_over_72h / resolved_count * 100) if resolved_count else 0:.2f}%)

AVERAGE RESPONSE TIME BY DEPARTMENT CATEGORY (exceeding 48 hours):
Medical Department:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['count']} complaints)" for d in medical_slow[:10]]) if medical_slow else "- All within timeframe"}

Non-Medical Department:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['count']} complaints)" for d in admin_slow[:10]]) if admin_slow else "- All within timeframe"}

Nursing Department:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['count']} complaints)" for d in nursing_slow[:5]]) if nursing_slow else "- All within timeframe"}

Support Services:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['count']} complaints)" for d in support_slow[:5]]) if support_slow else "- No complaints received"}

COMPLAINTS LACKING RESPONSES: {complaints_no_response}

ESCALATION & CLOSURE:
- Escalated Complaints: {escalated_count}
- Closed Complaints: {closed_count}

MOH RESOLUTION BREAKDOWN ({moh_total} resolved complaints):
- Within 24h: {moh_24h} ({(moh_24h / moh_total * 100) if moh_total else 0:.2f}%)
- Within 48h: {moh_48h} ({(moh_48h / moh_total * 100) if moh_total else 0:.2f}%)
- Within 72h: {moh_72h} ({(moh_72h / moh_total * 100) if moh_total else 0:.2f}%)
- After 72h: {moh_over} ({(moh_over / moh_total * 100) if moh_total else 0:.2f}%)

CCHI RESOLUTION BREAKDOWN ({cchi_total} resolved complaints):
- Within 24h: {cchi_24h} ({(cchi_24h / cchi_total * 100) if cchi_total else 0:.2f}%)
- Within 48h: {cchi_48h} ({(cchi_48h / cchi_total * 100) if cchi_total else 0:.2f}%)
- Within 72h: {cchi_72h} ({(cchi_72h / cchi_total * 100) if cchi_total else 0:.2f}%)
- After 72h: {cchi_over} ({(cchi_over / cchi_total * 100) if cchi_total else 0:.2f}%)

MONTHLY TREND:
{chr(10).join([f"- Month {m['month']}: {m['percentage']:.2f}% ({m['resolved']}/{m['total']})" for m in monthly_breakdown])}

SOURCE BREAKDOWN:
{chr(10).join([f"- {s['source']}: {s['complaints']} ({s['percentage']:.2f}%)" for s in source_data])}

DEPARTMENT PERFORMANCE:
{chr(10).join([f"- {d['category']}: {d['complaints']} complaints, {d['resolved']} resolved" + (f", Avg {d['avg_days']:.1f} days" if d["avg_days"] else "") for d in dept_data])}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% 72h resolution rate vs {target_percentage:.0f}% target",
    "comparison_to_target": "Analysis of meeting target and threshold",
    "resolution_time_analysis": {{
        "within_24h": {{"count": {resolved_24h}, "percentage": "{(resolved_24h / resolved_count * 100) if resolved_count else 0:.2f}%"}},
        "within_48h": {{"count": {resolved_48h}, "percentage": "{(resolved_48h / resolved_count * 100) if resolved_count else 0:.2f}%"}},
        "within_72h": {{"count": {resolved_72h}, "percentage": "{(resolved_72h / resolved_count * 100) if resolved_count else 0:.2f}%"}},
        "after_72h": {{"count": {resolved_over_72h}, "percentage": "{(resolved_over_72h / resolved_count * 100) if resolved_count else 0:.2f}%"}}
    }},
    "slow_departments": {{
        "medical": ["Dept Name: X Days"],
        "non_medical": ["Dept Name: X Days"],
        "nursing": ["Dept Name: X Days"],
        "support_services": ["Dept Name: X Days"]
    }},
    "source_resolution_breakdown": {{
        "moh": {{"total": {moh_total}, "within_24h": {moh_24h}, "within_48h": {moh_48h}, "within_72h": {moh_72h}, "after_72h": {moh_over}}},
        "cchi": {{"total": {cchi_total}, "within_24h": {cchi_24h}, "within_48h": {cchi_48h}, "within_72h": {cchi_72h}, "after_72h": {cchi_over}}}
    }},
    "escalation_closure": {{
        "escalated": {escalated_count},
        "closed": {closed_count},
        "complaints_no_response": {complaints_no_response}
    }},
    "key_findings": ["Finding 1", "Finding 2"],
    "recommendations": ["Recommendation 1", "Recommendation 2"]
}}"""

            system_prompt = """You are a healthcare KPI analysis expert. Analyze 72-Hour Complaint Resolution data and provide:
1. Executive summary with performance status vs target and threshold
2. Resolution time breakdown analysis
3. Slow departments analysis by category (Medical, Non-Medical, Nursing, Support)
4. Source-specific resolution insights (MOH vs CCHI breakdown)
5. Escalation and response status
6. Key findings with specific numbers
7. Actionable recommendations

Be specific and use actual numbers from the data."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2500,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for 72h report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating 72h analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_patient_experience_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for Patient Experience Score (MOH-1) report"""
        from apps.core.ai_service import AIService
        from apps.surveys.models import SurveyInstance, SurveyStatus

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_surveyed = report.total_denominator
            satisfied_count = report.total_numerator

            monthly_data = report.monthly_data.all().order_by("month")
            monthly_breakdown = []
            for md in monthly_data:
                if md.denominator > 0:
                    monthly_breakdown.append(
                        {
                            "month": md.month,
                            "month_name": [
                                "Jan",
                                "Feb",
                                "Mar",
                                "Apr",
                                "May",
                                "Jun",
                                "Jul",
                                "Aug",
                                "Sep",
                                "Oct",
                                "Nov",
                                "Dec",
                            ][md.month - 1],
                            "percentage": float(md.percentage) if md.percentage else 0,
                            "satisfied": md.numerator,
                            "total": md.denominator,
                            "avg_score": float(md.details.get("avg_score", 0)) if md.details else 0,
                        }
                    )

            year_start = _dt(report.year, 1, 1)
            year_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            from django.db.models import Avg as AvgAgg, Count

            surveys = SurveyInstance.objects.filter(
                survey_template__hospital=report.hospital,
                survey_template__survey_type__in=["stage", "general"],
                status=SurveyStatus.COMPLETED,
                completed_at__gte=year_start,
                completed_at__lt=year_end,
            )

            total_completed = surveys.count()

            avg_score_val = surveys.aggregate(avg=AvgAgg("total_score"))["avg"] or 0

            dissatisfied = surveys.filter(total_score__lt=4).count()
            neutral_count = surveys.filter(total_score__gte=3, total_score__lt=4).count()
            very_satisfied = surveys.filter(total_score__gte=4.5).count()

            negative_surveys = surveys.filter(is_negative=True).count()

            delivery_breakdown = surveys.values("delivery_channel").annotate(count=Count("id")).order_by("-count")
            delivery_lines = []
            for d in delivery_breakdown:
                label = dict(SurveyInstance._meta.get_field("delivery_channel").choices).get(
                    d["delivery_channel"], d["delivery_channel"]
                )
                pct = (d["count"] / total_completed * 100) if total_completed else 0
                delivery_lines.append(f"- {label}: {d['count']} ({pct:.1f}%)")

            lowest_month = min(monthly_breakdown, key=lambda x: x["percentage"]) if monthly_breakdown else None
            highest_month = max(monthly_breakdown, key=lambda x: x["percentage"]) if monthly_breakdown else None

            prev_month = report.month - 1 if report.month > 1 else 12
            prev_year = report.year if report.month > 1 else report.year - 1
            prev_percentage = None
            try:
                prev_report = KPIReport.objects.get(
                    report_type=report.report_type,
                    hospital=report.hospital,
                    year=prev_year,
                    month=prev_month,
                )
                prev_percentage = float(prev_report.overall_result) if prev_report.overall_result else None
            except KPIReport.DoesNotExist:
                pass

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage)

            performance_status = (
                "Target Met"
                if overall_percentage >= target_percentage
                else "Below Target"
                if overall_percentage >= threshold_percentage
                else "Below Threshold"
            )

            prev_trend = ""
            if prev_percentage is not None:
                diff = overall_percentage - prev_percentage
                direction = "improved" if diff > 0 else "declined" if diff < 0 else "stable"
                prev_trend = f" ({direction} from {prev_month}/{prev_year}: {prev_percentage:.1f}%)"

            prompt = f"""Analyze this Patient Experience Score (MOH-1) KPI report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Patient Experience Score: {overall_percentage:.2f}%{prev_trend}
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {performance_status}
- Total Patients Surveyed: {total_surveyed}
- Total Completed Responses: {total_completed}
- Average Score: {avg_score_val:.2f}

SATISFACTION BREAKDOWN:
- Very Satisfied (score >= 4.5): {very_satisfied} ({(very_satisfied / total_completed * 100) if total_completed else 0:.1f}%)
- Satisfied/Good (score >= 4): {satisfied_count} ({(satisfied_count / total_completed * 100) if total_completed else 0:.1f}%)
- Neutral (3-4): {neutral_count} ({(neutral_count / total_completed * 100) if total_completed else 0:.1f}%)
- Dissatisfied (<3): {dissatisfied} ({(dissatisfied / total_completed * 100) if total_completed else 0:.1f}%)
- Flagged as Negative: {negative_surveys}

DELIVERY CHANNEL BREAKDOWN:
{chr(10).join(delivery_lines) if delivery_lines else "- No data"}

MONTHLY TRENDS:
{chr(10).join([f"- {m['month_name']}: {m['percentage']:.2f}% ({m['satisfied']}/{m['total']}, avg score: {m['avg_score']:.2f})" for m in monthly_breakdown])}

LOWEST: {lowest_month["month_name"] if lowest_month else "N/A"} ({lowest_month["percentage"]:.2f}%)
HIGHEST: {highest_month["month_name"] if highest_month else "N/A"} ({highest_month["percentage"]:.2f}%)

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% patient experience score vs {target_percentage:.0f}% target",
    "comparison_to_target": "Analysis vs target ({target_percentage:.0f}%) and threshold ({threshold_percentage:.0f}%){prev_trend}",
    "patient_experience_score": "{overall_percentage:.2f}%",
    "satisfaction_breakdown": {{
        "very_satisfied": {very_satisfied},
        "satisfied_good": {satisfied_count},
        "neutral": {neutral_count},
        "dissatisfied": {dissatisfied},
        "negative_flagged": {negative_surveys}
    }},
    "delivery_channel_analysis": "Analysis of survey delivery channels",
    "monthly_trend": ["Month: Percentage%"],
    "response_statistics": {{
        "total_surveyed": {total_surveyed},
        "total_completed": {total_completed},
        "average_score": "{avg_score_val:.2f}"
    }},
    "key_findings": ["Finding 1", "Finding 2"],
    "recommendations": ["Recommendation 1", "Recommendation 2"]
}}"""

            system_prompt = """You are a healthcare patient experience analysis expert for MOH-1 Patient Experience Score.
Analyze the patient experience survey data and provide:
1. Executive summary of patient experience performance
2. Comparison to target (85%) and threshold (78%)
3. Previous month trend comparison
4. Satisfaction breakdown analysis
5. Delivery channel insights
6. Month-by-month trend analysis
7. Key findings with specific numbers
8. Actionable recommendations for improving patient experience

Focus on identifying drivers of satisfaction and dissatisfaction."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2500,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for Patient Experience report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating Patient Experience analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_n_pad_001_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for N-PAD-001 Resolution to Patient Complaints report"""
        from apps.core.ai_service import AIService

        try:
            # Get report data
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_complaints = report.total_denominator
            resolved_complaints = report.total_numerator

            # Get date range
            year_start = _dt(report.year, 1, 1)
            year_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            # Query complaints for detailed analysis
            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=year_start,
                created_at__lt=year_end,
                complaint_type="complaint",
            ).select_related("department", "source")

            # Count by status
            closed_count = complaints.filter(status=ComplaintStatus.CLOSED).count()
            resolved_count = complaints.filter(status=ComplaintStatus.RESOLVED).count()
            escalated_count = complaints.filter(updates__update_type="escalation").distinct().count()

            # Department breakdown
            dept_counts = {}
            for c in complaints:
                dept_cat = "Unassigned"
                if c.department:
                    name = c.department.name.lower()
                    if any(
                        k in name
                        for k in [
                            "medical",
                            "surgery",
                            "cardiology",
                            "orthopedics",
                            "pediatrics",
                            "obstetrics",
                            "gynecology",
                            "er",
                            "lab",
                            "icu",
                        ]
                    ):
                        dept_cat = "Medical"
                    elif any(k in name for k in ["nursing", "nurse"]):
                        dept_cat = "Nursing"
                    elif any(k in name for k in ["admin", "reception", "manager", "approval", "report"]):
                        dept_cat = "Admin"
                    elif any(k in name for k in ["housekeeping", "maintenance", "security", "cafeteria", "transport"]):
                        dept_cat = "Support Services"
                    else:
                        dept_cat = c.department.name

                if dept_cat not in dept_counts:
                    dept_counts[dept_cat] = {"closed": 0, "escalated": 0, "total": 0}
                dept_counts[dept_cat]["total"] += 1
                if c.status == ComplaintStatus.CLOSED:
                    dept_counts[dept_cat]["closed"] += 1

            # Escalation reasons
            escalated_complaints = complaints.filter(updates__update_type="escalation").distinct()
            patient_dissatisfaction = 0
            lack_of_response = 0

            for c in escalated_complaints:
                updates = c.updates.filter(update_type="escalation")
                for u in updates:
                    message = u.message.lower() if u.message else ""
                    if any(
                        k in message
                        for k in ["dissatisfaction", "dissatisfied", "unhappy", "not satisfied", "complain"]
                    ):
                        patient_dissatisfaction += 1
                    if any(k in message for k in ["no response", "lack of response", "no reply", "delay"]):
                        lack_of_response += 1

            # Source breakdown
            source_counts = {}
            for c in complaints:
                source = "Unknown"
                if c.source:
                    source_name = c.source.name_en.lower() if c.source.name_en else ""
                    if "moh" in source_name:
                        source = "MOH"
                    elif "chi" in source_name:
                        source = "CHI"
                    else:
                        source = c.source.name_en
                elif c.complaint_source_type == "external":
                    source = "Patient/Relative"
                else:
                    source = "Internal"

                source_counts[source] = source_counts.get(source, 0) + 1

            # Location breakdown
            location_counts = {}
            for c in complaints:
                loc = c.department.location_type if c.department and c.department.location_type else "Unknown"
                location_counts[loc] = location_counts.get(loc, 0) + 1

            # Main department breakdown
            main_dept_counts = {
                "Medical": dept_counts.get("Medical", {}).get("total", 0),
                "Nursing": dept_counts.get("Nursing", {}).get("total", 0),
                "Admin": dept_counts.get("Admin", {}).get("total", 0),
                "Support Services": dept_counts.get("Support Services", {}).get("total", 0),
            }

            # Top departments by complaints (detailed)
            detailed_dept_counts = {}
            for c in complaints:
                if c.department:
                    dept_name = c.department.name
                    if dept_name not in detailed_dept_counts:
                        detailed_dept_counts[dept_name] = 0
                    detailed_dept_counts[dept_name] += 1

            top_departments = sorted(detailed_dept_counts.items(), key=lambda x: x[1], reverse=True)[:10]

            target_percentage = float(report.target_percentage)

            prompt = f"""Analyze this N-PAD-001 Resolution to Patient Complaints KPI report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Resolution Rate: {overall_percentage:.2f}%
- Target: {target_percentage:.2f}%
- Total Complaints: {total_complaints}
- Resolved: {resolved_complaints}
- Closed: {closed_count}

CLOSED COMPLAINTS BY DEPARTMENT CATEGORY:
- Medical: {dept_counts.get("Medical", {}).get("closed", 0)}
- Nursing: {dept_counts.get("Nursing", {}).get("closed", 0)}
- Admin: {dept_counts.get("Admin", {}).get("closed", 0)}
- Support Services: {dept_counts.get("Support Services", {}).get("closed", 0)}

ESCALATED COMPLAINTS: {escalated_count}
- Due to Patient Dissatisfaction: {patient_dissatisfaction}
- Due to Lack of Response: {lack_of_response}

BY DEPARTMENT CATEGORY:
- Medical: {dept_counts.get("Medical", {}).get("escalated", 0)}
- Nursing: {dept_counts.get("Nursing", {}).get("escalated", 0)}
- Admin: {dept_counts.get("Admin", {}).get("escalated", 0)}
- Support: {dept_counts.get("Support Services", {}).get("escalated", 0)}

TOP DEPARTMENTS BY COMPLAINTS:
{chr(10).join([f"- {name}: {count}" for name, count in top_departments])}

SOURCE BREAKDOWN:
{chr(10).join([f"- {source}: {count}" for source, count in source_counts.items()])}

LOCATION BREAKDOWN:
{chr(10).join([f"- {loc}: {count}" for loc, count in location_counts.items()])}

MAIN DEPARTMENT BREAKDOWN:
{chr(10).join([f"- {dept}: {count}" for dept, count in main_dept_counts.items()])}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of achieving {overall_percentage:.0f}% resolution rate",
    "comparison_to_target": "Analysis of meeting {target_percentage:.0f}% target",
    "closed_complaints_analysis": "Details about {closed_count} closed complaints",
    "escalated_complaints_analysis": "Analysis of {escalated_count} escalated complaints",
    "top_departments": [
        "Department 1: X complaints",
        "Department 2: Y complaints"
    ],
    "department_breakdown": {{
        "medical": "Medical dept analysis",
        "nursing": "Nursing dept analysis",
        "admin": "Admin dept analysis",
        "support": "Support services analysis"
    }},
    "source_breakdown": {{
        "moh": "MOH complaints analysis",
        "chi": "CHI complaints analysis",
        "patients": "Patient complaints analysis",
        "relatives": "Relative complaints analysis"
    }},
    "location_breakdown": {{
        "inpatient": "In-patient analysis",
        "outpatient": "Out-patient analysis",
        "er": "ER analysis"
    }},
    "recommendations": [
        "Recommendation 1",
        "Recommendation 2"
    ]
}}"""

            system_prompt = """You are a healthcare KPI analysis expert for N-PAD-001 Resolution to Patient Complaints.
Analyze the complaint resolution data and provide:
1. Executive summary of resolution performance
2. Comparison to target achievement
3. Closed complaints breakdown by department
4. Escalated complaints analysis with reasons
5. Top departments with highest complaint counts
6. Source breakdown insights (MOH, CHI, Patients, Relatives)
7. Location breakdown insights (Inpatient, Outpatient, Emergency)
8. Main department category analysis
9. Practical recommendations for maintaining/improving resolution rates

Be specific with numbers and focus on actionable insights."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2500,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for N-PAD-001 report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating N-PAD-001 analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_satisfaction_resolution_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for Overall Satisfaction with Resolution (MOH-3) report"""
        from apps.core.ai_service import AIService
        from apps.surveys.models import SurveyInstance, SurveyStatus

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_responses = report.total_denominator
            satisfied_responses = report.total_numerator

            monthly_data = report.monthly_data.all().order_by("month")
            monthly_breakdown = []
            for md in monthly_data:
                if md.denominator > 0:
                    monthly_breakdown.append(
                        {
                            "month": md.month,
                            "month_name": [
                                "Jan",
                                "Feb",
                                "Mar",
                                "Apr",
                                "May",
                                "Jun",
                                "Jul",
                                "Aug",
                                "Sep",
                                "Oct",
                                "Nov",
                                "Dec",
                            ][md.month - 1],
                            "percentage": float(md.percentage) if md.percentage else 0,
                            "satisfied": md.numerator,
                            "total": md.denominator,
                        }
                    )

            year_start = _dt(report.year, 1, 1)
            year_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            total_complaints_received = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=year_start,
                created_at__lt=year_end,
                complaint_type="complaint",
            ).count()

            surveys = SurveyInstance.objects.filter(
                survey_template__hospital=report.hospital,
                survey_template__survey_type="complaint_resolution",
                completed_at__gte=year_start,
                completed_at__lt=year_end,
            )

            completed_surveys = surveys.filter(status=SurveyStatus.COMPLETED)
            completed_count = completed_surveys.count()

            no_response = total_complaints_received - completed_count
            dissatisfied_count = 0
            neutral_count = 0

            for survey in completed_surveys:
                score = survey.total_score
                if score is not None:
                    if score >= 4:
                        pass
                    elif score <= 2:
                        dissatisfied_count += 1
                    else:
                        neutral_count += 1
                else:
                    for resp in survey.responses.all():
                        if resp.question and (
                            "satisfaction" in resp.question.text.lower() or "satisfied" in resp.question.text.lower()
                        ):
                            val = resp.numeric_value
                            if val is not None:
                                val_int = int(val)
                                if val_int <= 2:
                                    dissatisfied_count += 1
                                elif val_int == 3:
                                    neutral_count += 1
                            else:
                                text = (resp.text_value or resp.choice_value or "").lower()
                                if any(w in text for w in ["dissatisfied", "unhappy", "bad", "poor"]):
                                    dissatisfied_count += 1
                                else:
                                    neutral_count += 1
                            break

            response_rate = (completed_count / total_complaints_received * 100) if total_complaints_received > 0 else 0
            satisfaction_excl_no_response = (satisfied_responses / completed_count * 100) if completed_count > 0 else 0

            moh_complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=year_start,
                created_at__lt=year_end,
                complaint_type="complaint",
                source__code__iexact="moh",
            ).count()

            cchi_complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=year_start,
                created_at__lt=year_end,
                complaint_type="complaint",
            ).filter(
                Q(source__code__iexact="chi") | Q(source__code__iexact="cchi")
            ).count()

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage)

            performance_status = (
                "target met"
                if overall_percentage >= target_percentage
                else "below target but above threshold"
                if overall_percentage >= threshold_percentage
                else "below threshold - action needed"
            )

            lowest_month = min(monthly_breakdown, key=lambda x: x["percentage"]) if monthly_breakdown else None
            highest_month = max(monthly_breakdown, key=lambda x: x["percentage"]) if monthly_breakdown else None

            prompt = f"""Analyze this Overall Satisfaction with Complaint Resolution (MOH-3) KPI report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Overall Satisfaction Rate: {overall_percentage:.2f}%
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {performance_status}

SATISFACTION BREAKDOWN:
- Total Complaints Received: {total_complaints_received}
- Total Responses: {completed_count}
- No Response: {no_response}
- Satisfied: {satisfied_responses}
- Not Satisfied: {dissatisfied_count}
- Neutral: {neutral_count}

SATISFACTION RATE: {satisfaction_excl_no_response:.2f}% (after excluding no responses)
RESPONSE RATE: {response_rate:.2f}% ({completed_count}/{total_complaints_received})

MONTHLY SATISFACTION TRENDS:
{chr(10).join([f"- {m['month_name']}: {m['percentage']:.2f}% ({m['satisfied']}/{m['total']})" for m in monthly_breakdown])}

LOWEST PERFORMANCE: {lowest_month["month_name"] if lowest_month else "N/A"} ({lowest_month["percentage"]:.2f}%)
HIGHEST PERFORMANCE: {highest_month["month_name"] if highest_month else "N/A"} ({highest_month["percentage"]:.2f}%)

SOURCE BREAKDOWN:
- MOH complaints: {moh_complaints}
- CCHI complaints: {cchi_complaints}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% satisfaction rate vs {target_percentage:.0f}% target",
    "comparison_to_target": "Analysis of meeting target ({target_percentage:.0f}%) and threshold ({threshold_percentage:.0f}%)",
    "satisfaction_rate": "{satisfaction_excl_no_response:.2f}%",
    "response_rate": "{response_rate:.2f}%",
    "participation_analysis": "Analysis of {response_rate:.1f}% response rate and {no_response} complaints with no response",
    "monthly_trend": [
        "Month: Percentage%"
    ],
    "satisfaction_breakdown": {{
        "satisfied": {satisfied_responses},
        "not_satisfied": {dissatisfied_count},
        "neutral": {neutral_count}
    }},
    "response_statistics": {{
        "total_complaints_received": {total_complaints_received},
        "total_responses": {completed_count},
        "no_response": {no_response},
        "satisfied": {satisfied_responses},
        "not_satisfied": {dissatisfied_count},
        "neutral": {neutral_count}
    }},
    "key_issues": [
        "Issue 1: description",
        "Issue 2: description"
    ],
    "recommendations": [
        "Recommendation 1",
        "Recommendation 2"
    ]
}}"""

            system_prompt = """You are a healthcare patient satisfaction analysis expert for MOH-3 Overall Satisfaction with Complaint Resolution.
Analyze the satisfaction survey data and provide:
1. Executive summary of overall satisfaction performance
2. Comparison to target and threshold (80% target, 70% threshold)
3. Satisfaction rate analysis (excluding non-responses)
4. Response rate / participation analysis
5. Month-by-month satisfaction rate analysis with trends
6. Key issues causing dissatisfaction
7. Actionable recommendations for improving satisfaction

Focus on identifying why patients are dissatisfied and provide practical solutions."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2500,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for Satisfaction Resolution report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating Satisfaction Resolution analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_response_rate_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for Department Response Rate (Dep-KPI-4) report"""
        from apps.core.ai_service import AIService

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_complaints = report.total_denominator
            responded_within_48h = report.total_numerator

            # Previous month comparison
            prev_month = report.month - 1 if report.month > 1 else 12
            prev_year = report.year if report.month > 1 else report.year - 1
            prev_percentage = None
            try:
                prev_report = KPIReport.objects.get(
                    report_type=report.report_type,
                    hospital=report.hospital,
                    year=prev_year,
                    month=prev_month,
                )
                prev_percentage = float(prev_report.overall_result) if prev_report.overall_result else None
            except KPIReport.DoesNotExist:
                pass

            year_start = _dt(report.year, 1, 1)
            year_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            all_complaints = (
                Complaint.objects.filter(
                    hospital=report.hospital,
                    created_at__gte=year_start,
                    created_at__lt=year_end,
                    complaint_type="complaint",
                )
                .select_related("department", "source")
                .prefetch_related("updates")
            )

            responded_48_72h = 0
            responded_over_72h = 0
            complaints_no_response = 0
            dept_response_times = {}

            for c in all_complaints:
                first_response = (
                    c.updates.filter(update_type__in=["communication", "resolution"]).order_by("created_at").first()
                )

                if first_response and c.created_at:
                    hours = (first_response.created_at - c.created_at).total_seconds() / 3600
                    dept_name = c.department.name if c.department else "Unassigned"

                    if dept_name not in dept_response_times:
                        dept_response_times[dept_name] = []
                    dept_response_times[dept_name].append(hours / 24)

                    if hours > 48:
                        if hours <= 72:
                            responded_48_72h += 1
                        else:
                            responded_over_72h += 1
                else:
                    complaints_no_response += 1

            total_exceeding_48h = responded_48_72h + responded_over_72h

            escalated_count = all_complaints.filter(updates__update_type="escalation").distinct().count()

            medical_slow = []
            nursing_slow = []
            admin_slow = []
            support_slow = []

            for dept, days_list in dept_response_times.items():
                if days_list:
                    avg_days = sum(days_list) / len(days_list)
                    entry = {"name": dept, "avg_days": round(avg_days, 1), "complaint_count": len(days_list)}
                    cat = _get_dept_category(dept)
                    if avg_days > 2:
                        if cat == "medical":
                            medical_slow.append(entry)
                        elif cat == "nursing":
                            nursing_slow.append(entry)
                        elif cat == "non_medical":
                            admin_slow.append(entry)
                        elif cat == "support_services":
                            support_slow.append(entry)

            medical_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            nursing_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            admin_slow.sort(key=lambda x: x["avg_days"], reverse=True)
            support_slow.sort(key=lambda x: x["avg_days"], reverse=True)

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage)

            performance_status = (
                "Target Met"
                if overall_percentage >= target_percentage
                else "Below Target"
                if overall_percentage >= threshold_percentage
                else "Below Threshold"
            )

            prev_trend = ""
            if prev_percentage is not None:
                diff = overall_percentage - prev_percentage
                direction = "improved" if diff > 0 else "declined" if diff < 0 else "stable"
                prev_trend = f" ({direction} from {prev_month}/{prev_year}: {prev_percentage:.1f}%)"

            prompt = f"""Analyze this Department Response Rate (Dep-KPI-4) KPI report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Response Rate (≤48h): {overall_percentage:.2f}%{prev_trend}
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {performance_status}
- Total Complaints: {total_complaints}
- Responded within 48h: {responded_within_48h}

COMPLAINTS EXCEEDING 48 HOURS: {total_exceeding_48h}
- 48-72 hours: {responded_48_72h} complaints ({(responded_48_72h / total_complaints * 100) if total_complaints else 0:.2f}%)
- Over 72 hours: {responded_over_72h} complaints ({(responded_over_72h / total_complaints * 100) if total_complaints else 0:.2f}%)
- Escalated due to delays: {escalated_count}
- No response: {complaints_no_response}

DEPARTMENTS WITH MORE THAN 48 HOURS OF RESPONSE:
MEDICAL DEPARTMENT:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['complaint_count']} complaints)" for d in medical_slow[:10]]) if medical_slow else "- None exceeding timeframe"}

NON-MEDICAL DEPARTMENT:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['complaint_count']} complaints)" for d in admin_slow[:10]]) if admin_slow else "- All within timeframe"}

NURSING DEPARTMENT:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['complaint_count']} complaints)" for d in nursing_slow[:5]]) if nursing_slow else "- None exceeding timeframe"}

SUPPORT SERVICES:
{chr(10).join([f"- {d['name']}: {d['avg_days']} Days ({d['complaint_count']} complaints)" for d in support_slow[:5]]) if support_slow else "- No complaints received"}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% response rate vs {target_percentage:.0f}% target",
    "comparison_to_target": "Analysis of meeting target ({target_percentage:.0f}%) and threshold ({threshold_percentage:.0f}%){prev_trend}",
    "response_rate": "{overall_percentage:.2f}%",
    "complaints_exceeding_48h": {{
        "total": {total_exceeding_48h},
        "within_48_72h": {{"count": {responded_48_72h}, "percentage": "{(responded_48_72h / total_complaints * 100) if total_complaints else 0:.2f}%"}},
        "over_72h": {{"count": {responded_over_72h}, "percentage": "{(responded_over_72h / total_complaints * 100) if total_complaints else 0:.2f}%"}}
    }},
    "escalated_due_to_delays": {escalated_count},
    "complaints_no_response": {complaints_no_response},
    "slow_departments": {{
        "medical": ["Dept Name: X Days"],
        "non_medical": ["Dept Name: X Days"],
        "nursing": ["Dept Name: X Days"],
        "support_services": ["Dept Name: X Days"]
    }},
    "key_findings": ["Finding 1", "Finding 2"],
    "recommendations": ["Recommendation 1", "Recommendation 2"]
}}"""

            system_prompt = """You are a healthcare department response analysis expert for Dep-KPI-4 Department Response Rate.
Analyze the response time data and provide:
1. Executive summary of response rate performance
2. Comparison to target and threshold
3. Previous month trend comparison
4. Breakdown of complaints exceeding 48 hours
5. Escalated complaints due to department delays
6. Analysis of slow departments by category (Medical, Nursing, Non-Medical, Support)
7. Specific department names with their average response times
8. Actionable recommendations for improving response times

Focus on identifying which departments need improvement and practical follow-up strategies."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2000,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for Response Rate report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating Response Rate analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_activation_2h_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for Complaint Activation Within 2 Hours (KPI-6) report"""
        from apps.core.ai_service import AIService

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_complaints = report.total_denominator
            activated_within_2h = report.total_numerator

            month_start = _dt(report.year, report.month, 1)
            month_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            complaints = Complaint.objects.filter(
                hospital=report.hospital,
                created_at__gte=month_start,
                created_at__lt=month_end,
                complaint_type="complaint",
            ).select_related("assigned_to")

            activated_complaints = []
            delayed_complaints = []

            staff_activation = {}
            staff_delays = {}

            for c in complaints:
                if c.assigned_at and c.created_at:
                    hours = (c.assigned_at - c.created_at).total_seconds() / 3600

                    staff_name = c.assigned_to.get_full_name() if c.assigned_to else "Unknown"

                    if hours <= 2:
                        activated_complaints.append({"id": str(c.id), "hours": hours, "staff": staff_name})

                        if staff_name not in staff_activation:
                            staff_activation[staff_name] = 0
                        staff_activation[staff_name] += 1
                    else:
                        delayed_complaints.append({"id": str(c.id), "hours": hours, "staff": staff_name})

                        if staff_name not in staff_delays:
                            staff_delays[staff_name] = 0
                        staff_delays[staff_name] += 1

            top_activators = sorted(staff_activation.items(), key=lambda x: x[1], reverse=True)
            top_delays = sorted(staff_delays.items(), key=lambda x: x[1], reverse=True)

            total_count = len(activated_complaints) + len(delayed_complaints)
            activated_count = len(activated_complaints)
            delay_count = len(delayed_complaints)

            activated_percentage = (activated_count / total_count * 100) if total_count > 0 else 0
            delay_percentage = (delay_count / total_count * 100) if total_count > 0 else 0

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage) if report.threshold_percentage else 90.0

            prev_month = report.month - 1 if report.month > 1 else 12
            prev_year = report.year if report.month > 1 else report.year - 1

            try:
                prev_report = KPIReport.objects.get(
                    report_type=report.report_type, hospital=report.hospital, year=prev_year, month=prev_month
                )
                prev_percentage = float(prev_report.overall_result) if prev_report.overall_result else 0
            except KPIReport.DoesNotExist:
                prev_percentage = None

            prompt = f"""Analyze this Complaint Activation Within 2 Hours (KPI-6) report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Activation Rate (≤2h): {overall_percentage:.2f}%
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {"Target Met" if overall_percentage >= target_percentage else "Below Target" if overall_percentage >= threshold_percentage else "Below Threshold"}
- Total Complaints: {total_count}

PREVIOUS MONTH COMPARISON:
{prev_month}/{prev_year}: {prev_percentage:.2f}% {"(improved)" if prev_percentage and overall_percentage > prev_percentage else "(declined)" if prev_percentage and overall_percentage < prev_percentage else "(stable)" if prev_percentage else "(no data)"}

ACTIVATED WITHIN 2 HOURS:
- Total: {activated_count} Complaints ({activated_percentage:.2f}%)

BY STAFF:
{chr(10).join([f"- {name}: {count} Complaints - {(count / activated_count * 100) if activated_count else 0:.2f}%" for name, count in top_activators[:5]]) if top_activators else "- No data"}

DELAYS IN ACTIVATION:
- Total: {delay_count} Complaints ({delay_percentage:.2f}%)

BY STAFF:
{chr(10).join([f"- {name}: {count} Complaints - {(count / delay_count * 100) if delay_count else 0:.2f}%" for name, count in top_delays[:5]]) if top_delays else "- No delays"}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% activation rate",
    "comparison_to_target": "Analysis vs {target_percentage:.0f}% target and {threshold_percentage:.0f}% threshold",
    "trend_analysis": "Comparison to previous month: improved/declined/stable",
    "delay_reasons": [
        "Reason 1: Staff attempts to resolve immediately but patient refuses",
        "Reason 2: Unclear complaint content requiring clarification",
        "Reason 3: Ensuring correct department direction"
    ],
    "activation_statistics": {{
        "activated_within_2h": {{
            "count": {activated_count},
            "percentage": "{activated_percentage:.2f}%",
            "by_staff": [
                "Staff Name: X Complaints - Y%"
            ]
        }},
        "delays": {{
            "count": {delay_count},
            "percentage": "{delay_percentage:.2f}%",
            "by_staff": [
                "Staff Name: X Complaints - Y%"
            ]
        }}
    }},
    "recommendations": [
        "Establish timer notification in complaints platform",
        "Add delay reason feature to complaints platform"
    ]
}}"""

            system_prompt = """You are a healthcare complaint activation analysis expert for KPI-6 Activation Within 2 Hours.
Analyze the activation time data and provide:
1. Executive summary of activation rate performance
2. Comparison to target and threshold
3. Trend analysis comparing to previous month
4. Reasons for activation delays
5. Activation statistics by staff member
6. Delay statistics by staff member
7. Actionable recommendations for improving activation times

Focus on identifying why activations are delayed and practical solutions."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2000,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for Activation 2h report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating Activation 2h analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}

    @classmethod
    def _generate_unactivated_analysis(cls, report: KPIReport) -> dict:
        """Generate AI analysis for Unactivated Filled Complaints Rate (KPI-7) report"""
        from apps.core.ai_service import AIService
        from apps.dashboard.models import ComplaintRequest

        try:
            overall_percentage = float(report.overall_result) if report.overall_result else 0
            total_complaints = report.total_denominator
            unactivated_filled = report.total_numerator

            month_start = _dt(report.year, report.month, 1)
            month_end = (
                _dt(report.year + 1, 1, 1) if report.month == 12 else _dt(report.year, report.month + 1, 1)
            )

            all_requests = ComplaintRequest.objects.filter(
                complaint__hospital=report.hospital,
                complaint__created_at__gte=month_start,
                complaint__created_at__lt=month_end,
                complaint__complaint_type="complaint",
            ).select_related("staff", "complaint")

            on_hold_count = all_requests.filter(on_hold=True).count()
            filled_count = all_requests.filter(filled=True).count()
            not_filled_count = all_requests.filter(not_filled=True).count()
            barcode_count = all_requests.filter(from_barcode=True).count()

            filling_times = dict(ComplaintRequest.FILLING_TIME_CHOICES)
            time_breakdown = {}
            for t in ComplaintRequest.FILLING_TIME_CHOICES:
                time_breakdown[t[0]] = all_requests.filter(filling_time_category=t[0]).count()

            staff_stats = {}
            for req in all_requests:
                staff_name = req.staff.get_full_name() if req.staff else "Unknown"
                if staff_name not in staff_stats:
                    staff_stats[staff_name] = {"filled": 0, "not_filled": 0, "total": 0}
                staff_stats[staff_name]["total"] += 1
                if req.filled:
                    staff_stats[staff_name]["filled"] += 1
                if req.not_filled:
                    staff_stats[staff_name]["not_filled"] += 1

            staff_table = sorted(
                [
                    {"name": s, "total": v["total"], "filled": v["filled"], "not_filled": v["not_filled"]}
                    for s, v in staff_stats.items()
                ],
                key=lambda x: x["total"],
                reverse=True,
            )

            target_percentage = float(report.target_percentage)
            threshold_percentage = float(report.threshold_percentage) if report.threshold_percentage else 5.0

            performance_status = (
                "Within Target"
                if overall_percentage <= target_percentage
                else "Above Threshold - Action Needed"
                if overall_percentage <= threshold_percentage
                else "Critical - Exceeds Acceptable Limit"
            )

            prompt = f"""Analyze this Unactivated Filled Complaints Rate (KPI-7) report.

REPORT DATA:
- Report Period: {report.year}-{report.month:02d}
- Hospital: {report.hospital.name}
- Unactivated Filled Rate: {overall_percentage:.2f}%
- Target: {target_percentage:.2f}%
- Threshold: {threshold_percentage:.2f}%
- Status: {performance_status}
- Total Complaints: {total_complaints}
- Unactivated Filled: {unactivated_filled}

COMPLAINT REQUEST BREAKDOWN:
- On Hold: {on_hold_count}
- Not Filled: {not_filled_count}
- Filled: {filled_count}
- From Barcode: {barcode_count}

TIME TO FILL ANALYSIS:
- Same Time: {time_breakdown.get("same_time", 0)}
- Within 6 Hours: {time_breakdown.get("within_6h", 0)}
- 6 Hours to 24 Hours: {time_breakdown.get("6_to_24h", 0)}
- After 1 Day: {time_breakdown.get("after_1_day", 0)}
- Time Not Mentioned: {time_breakdown.get("not_mentioned", 0)}

STAFF BREAKDOWN:
{chr(10).join([f"- {s['name']}: Total {s['total']}, Filled {s['filled']}, Not Filled {s['not_filled']}" for s in staff_table[:10]]) if staff_table else "- No data"}

Provide analysis in JSON format:
{{
    "executive_summary": "Overview of {overall_percentage:.2f}% unactivated filled rate vs {threshold_percentage:.0f}% threshold",
    "threshold_analysis": "Rate {"exceeds" if overall_percentage > threshold_percentage else "is within"} acceptable threshold of {threshold_percentage:.0f}%",
    "complaint_statistics": {{
        "on_hold": {on_hold_count},
        "not_filled": {not_filled_count},
        "filled": {filled_count},
        "from_barcode": {barcode_count}
    }},
    "time_to_fill": {{
        "same_time": {time_breakdown.get("same_time", 0)},
        "within_6h": {time_breakdown.get("within_6h", 0)},
        "6h_to_24h": {time_breakdown.get("6_to_24h", 0)},
        "after_1d": {time_breakdown.get("after_1_day", 0)},
        "not_mentioned": {time_breakdown.get("not_mentioned", 0)}
    }},
    "staff_breakdown": [
        "Staff Name: Total X, Filled Y, Not Filled Z"
    ],
    "key_findings": ["Finding 1", "Finding 2"],
    "recommendations": [
        "Monitoring the workflow and activation times among employees",
        "Improve system notifications for prompt staff follow-up"
    ]
}}"""

            system_prompt = """You are a healthcare complaint management analysis expert for KPI-7 Unactivated Filled Complaints Rate.
Analyze the unactivation data and provide:
1. Executive summary of unactivation rate vs threshold (target: 0%, threshold: 5%)
2. Threshold analysis
3. Complaint request statistics (on hold, filled, not filled, barcode)
4. Time to fill analysis
5. Staff breakdown and performance
6. Key findings with specific numbers
7. Actionable recommendations for reducing unactivated complaints

Focus on why complaints remain unactivated and practical solutions."""

            response = AIService.chat_completion(
                prompt=prompt,
                system_prompt=system_prompt,
                response_format="json_object",
                temperature=0.3,
                max_tokens=2000,
            )

            import json

            analysis = json.loads(response)
            analysis["_metadata"] = {
                "generated_at": timezone.now().isoformat(),
                "report_id": str(report.id),
                "report_type": report.report_type,
                "hospital": report.hospital.name,
                "year": report.year,
                "month": report.month,
            }

            report.ai_analysis = analysis
            report.ai_analysis_generated_at = timezone.now()
            report.save(update_fields=["ai_analysis", "ai_analysis_generated_at"])

            logger.info(f"AI analysis generated for Unactivated report {report.id}")
            return analysis

        except Exception as e:
            logger.exception(f"Error generating Unactivated analysis: {e}")
            return {"error": str(e), "executive_summary": "Analysis failed"}
