"""
KPI Report Models - Monthly automated reports based on MOH requirements

This module implements KPI reports that match the Excel-style templates:
- 72H Resolution Rate (MOH-2)
- Patient Experience Score (MOH-1)
- Overall Satisfaction with Resolution (MOH-3)
- N-PAD-001 Resolution Rate
- Response Rate (Dep-KPI-4)
- Activation Within 2 Hours (KPI-6)
- Unactivated Filled Complaints Rate (KPI-7)
"""

from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.core.models import TimeStampedModel, UUIDModel


class KPIReportType(models.TextChoices):
    """KPI report types matching MOH and internal requirements"""

    RESOLUTION_72H = "resolution_72h", _("MOH-2: 72-Hour Resolution Rate")
    PATIENT_EXPERIENCE = "patient_experience", _("MOH-1: Patient Experience Score")
    SATISFACTION_RESOLUTION = "satisfaction_resolution", _("MOH-3: Overall Satisfaction with Resolution")
    N_PAD_001 = "n_pad_001", _("N-PAD-001: Resolution to Patient Complaints")
    RESPONSE_RATE = "response_rate", _("Dep-KPI-4: Department Response Rate")
    ACTIVATION_2H = "activation_2h", _("KPI-6: Complaint Activation Within 2 Hours")
    UNACTIVATED = "unactivated", _("KPI-7: Unactivated Filled Complaints Rate")
    MOH_24H = "moh_24h", _("MOH-24h: 24-Hour MOH Complaint Resolution Rate")
    CHI_48H = "chi_48h", _("CHI-48h: 48-Hour CHI Complaint Resolution Rate")


class KPIReportStatus(models.TextChoices):
    """Status of KPI report generation"""

    PENDING = "pending", _("Pending")
    GENERATING = "generating", _("Generating")
    COMPLETED = "completed", _("Completed")
    FAILED = "failed", _("Failed")


class KPIReport(UUIDModel, TimeStampedModel):
    """
    KPI Report - Monthly automated report for a specific KPI type

    Each report represents one month of data for a specific KPI,
    matching the Excel-style table format from the reference templates.
    """

    report_type = models.CharField(
        max_length=50, choices=KPIReportType.choices, db_index=True, help_text=_("Type of KPI report")
    )

    # Organization scope
    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        related_name="kpi_reports",
        help_text=_("Hospital this report belongs to"),
    )

    # Reporting period
    year = models.IntegerField(db_index=True)
    month = models.IntegerField(db_index=True)

    # Report metadata
    report_date = models.DateField(help_text=_("Date the report was generated"))
    status = models.CharField(
        max_length=20, choices=KPIReportStatus.choices, default=KPIReportStatus.PENDING, db_index=True
    )
    generated_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="generated_kpi_reports",
        help_text=_("User who generated the report (null for automated)"),
    )
    generated_at = models.DateTimeField(null=True, blank=True)

    # Report configuration metadata
    target_percentage = models.DecimalField(
        max_digits=5, decimal_places=2, default=95.00, help_text=_("Target percentage for this KPI")
    )
    threshold_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=90.00,
        help_text=_("Threshold (minimum acceptable) percentage for this KPI"),
    )

    # Report metadata (category, type, risk, etc.)
    category = models.CharField(
        max_length=50, default="Organizational", help_text=_("Report category (e.g., Organizational, Clinical)")
    )
    kpi_type = models.CharField(
        max_length=50, default="Outcome", help_text=_("KPI type (e.g., Outcome, Process, Structure)")
    )
    risk_level = models.CharField(
        max_length=20,
        default="High",
        choices=[
            ("High", "High"),
            ("Medium", "Medium"),
            ("Low", "Low"),
        ],
        help_text=_("Risk level for this KPI"),
    )
    data_collection_method = models.CharField(
        max_length=50, default="Retrospective", help_text=_("Data collection method")
    )
    data_collection_frequency = models.CharField(
        max_length=50, default="Monthly", help_text=_("How often data is collected")
    )
    reporting_frequency = models.CharField(
        max_length=50, default="Monthly", help_text=_("How often report is generated")
    )
    dimension = models.CharField(
        max_length=50, default="Efficiency", help_text=_("KPI dimension (e.g., Efficiency, Quality, Safety)")
    )
    collector_name = models.CharField(max_length=200, blank=True, help_text=_("Name of data collector"))
    analyzer_name = models.CharField(max_length=200, blank=True, help_text=_("Name of data analyzer"))

    # Summary metrics
    total_numerator = models.IntegerField(default=0, help_text=_("Total count of successful outcomes"))
    total_denominator = models.IntegerField(default=0, help_text=_("Total count of all cases"))
    overall_result = models.DecimalField(
        max_digits=6, decimal_places=2, default=0.00, help_text=_("Overall percentage result")
    )

    # Error tracking
    error_message = models.TextField(blank=True)

    # AI-generated analysis
    ai_analysis = models.JSONField(
        null=True, blank=True, help_text=_("AI-generated analysis and recommendations for this report")
    )
    ai_analysis_generated_at = models.DateTimeField(
        null=True, blank=True, help_text=_("When the AI analysis was generated")
    )

    class Meta:
        ordering = ["-year", "-month", "report_type"]
        unique_together = [["report_type", "hospital", "year", "month"]]
        indexes = [
            models.Index(fields=["report_type", "-year", "-month"]),
            models.Index(fields=["hospital", "-year", "-month"]),
            models.Index(fields=["status", "-created_at"]),
        ]
        verbose_name = "KPI Report"
        verbose_name_plural = "KPI Reports"

    def __str__(self):
        return f"{self.get_report_type_display()} - {self.year}/{self.month:02d} - {self.hospital.name}"

    @property
    def report_period_display(self):
        """Get human-readable report period"""
        month_names = [
            "",
            "January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December",
        ]
        return f"{month_names[self.month]} {self.year}"

    @property
    def kpi_id(self):
        """Get KPI ID based on report type"""
        mapping = {
            KPIReportType.RESOLUTION_72H: "MOH-2",
            KPIReportType.PATIENT_EXPERIENCE: "MOH-1",
            KPIReportType.SATISFACTION_RESOLUTION: "MOH-3",
            KPIReportType.N_PAD_001: "N-PAD-001",
            KPIReportType.RESPONSE_RATE: "Dep-KPI-4",
            KPIReportType.ACTIVATION_2H: "KPI-6",
            KPIReportType.UNACTIVATED: "KPI-7",
            KPIReportType.MOH_24H: "MOH-24h",
            KPIReportType.CHI_48H: "CHI-48h",
        }
        return mapping.get(self.report_type, "KPI")

    @property
    def indicator_title(self):
        """Get indicator title based on report type"""
        titles = {
            KPIReportType.RESOLUTION_72H: "72-Hour Complaint Resolution Rate",
            KPIReportType.PATIENT_EXPERIENCE: "Patient Experience Score",
            KPIReportType.SATISFACTION_RESOLUTION: "Overall Satisfaction with Complaint Resolution",
            KPIReportType.N_PAD_001: "Resolution to Patient Complaints",
            KPIReportType.RESPONSE_RATE: "Department Response Rate (48h)",
            KPIReportType.ACTIVATION_2H: "Complaint Activation Within 2 Hours",
            KPIReportType.UNACTIVATED: "Unactivated Filled Complaints Rate",
            KPIReportType.MOH_24H: "24-Hour MOH Complaint Resolution Rate",
            KPIReportType.CHI_48H: "48-Hour CHI Complaint Resolution Rate",
        }
        return titles.get(self.report_type, "KPI Report")

    @property
    def numerator_label(self):
        """Get label for numerator based on report type"""
        labels = {
            KPIReportType.RESOLUTION_72H: "Resolved ≤72h",
            KPIReportType.PATIENT_EXPERIENCE: "Positive Responses",
            KPIReportType.SATISFACTION_RESOLUTION: "Satisfied Responses",
            KPIReportType.N_PAD_001: "Resolved Complaints",
            KPIReportType.RESPONSE_RATE: "Responded Within 48h",
            KPIReportType.ACTIVATION_2H: "Activated Within 2h",
            KPIReportType.UNACTIVATED: "Unactivated Complaints",
            KPIReportType.MOH_24H: "Resolved ≤24h",
            KPIReportType.CHI_48H: "Resolved ≤48h",
        }
        return labels.get(self.report_type, "Numerator")

    @property
    def denominator_label(self):
        """Get label for denominator based on report type"""
        labels = {
            KPIReportType.RESOLUTION_72H: "Total complaints",
            KPIReportType.PATIENT_EXPERIENCE: "Total responses",
            KPIReportType.SATISFACTION_RESOLUTION: "Total responses",
            KPIReportType.N_PAD_001: "Total complaints",
            KPIReportType.RESPONSE_RATE: "Total complaints",
            KPIReportType.ACTIVATION_2H: "Total complaints",
            KPIReportType.UNACTIVATED: "Total filled complaints",
            KPIReportType.MOH_24H: "Total MOH complaints",
            KPIReportType.CHI_48H: "Total CHI complaints",
        }
        return labels.get(self.report_type, "Denominator")


class KPIReportMonthlyData(UUIDModel, TimeStampedModel):
    """
    Monthly breakdown data for a KPI report

    Stores the Jan-Dec + TOTAL values shown in the Excel-style table.
    This allows for trend analysis and historical comparison.
    """

    kpi_report = models.ForeignKey(KPIReport, on_delete=models.CASCADE, related_name="monthly_data")

    # Month (1-12) - 0 represents the TOTAL row
    month = models.IntegerField(db_index=True, help_text=_("Month number (1-12), 0 for TOTAL"))

    # Values for this month
    numerator = models.IntegerField(default=0, help_text=_("Count of successful outcomes"))
    denominator = models.IntegerField(default=0, help_text=_("Count of all cases"))
    percentage = models.DecimalField(max_digits=6, decimal_places=2, default=0.00, help_text=_("Calculated percentage"))

    # Status indicators
    is_below_target = models.BooleanField(default=False, help_text=_("Whether this month is below target"))

    # Additional metadata for this month
    details = models.JSONField(
        default=dict, blank=True, help_text=_("Additional breakdown data (e.g., by source, department)")
    )

    class Meta:
        ordering = ["month"]
        unique_together = [["kpi_report", "month"]]
        indexes = [
            models.Index(fields=["kpi_report", "month"]),
        ]
        verbose_name = "KPI Monthly Data"
        verbose_name_plural = "KPI Monthly Data"

    def __str__(self):
        month_name = (
            "TOTAL"
            if self.month == 0
            else ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][self.month - 1]
        )
        return f"{self.kpi_report} - {month_name}: {self.percentage}%"

    def calculate_percentage(self):
        """Calculate percentage from numerator and denominator"""
        if self.denominator > 0:
            self.percentage = (self.numerator / self.denominator) * 100
        else:
            self.percentage = 0
        return self.percentage


class KPIReportDepartmentBreakdown(UUIDModel, TimeStampedModel):
    """
    Department-level breakdown for KPI reports

    Stores metrics for each department to show in the department grid
    section of the report (Medical, Nursing, Admin, Support Services).
    """

    kpi_report = models.ForeignKey(KPIReport, on_delete=models.CASCADE, related_name="department_breakdowns")

    department_category = models.CharField(
        max_length=50,
        choices=[
            ("medical", "Medical Department"),
            ("nursing", "Nursing Department"),
            ("non_medical", "Non-Medical / Admin"),
            ("support_services", "Support Services"),
        ],
        help_text=_("Category of department"),
    )

    # Department-specific metrics
    complaint_count = models.IntegerField(default=0)
    resolved_count = models.IntegerField(default=0)
    avg_resolution_days = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    # Top complaints/areas (stored as text for display)
    top_areas = models.TextField(blank=True, help_text=_("Top complaint areas or notes (newline-separated)"))

    # JSON field for flexible department-specific data
    details = models.JSONField(default=dict, blank=True)

    class Meta:
        ordering = ["department_category"]
        unique_together = [["kpi_report", "department_category"]]
        verbose_name = "KPI Department Breakdown"
        verbose_name_plural = "KPI Department Breakdowns"

    def __str__(self):
        return f"{self.kpi_report} - {self.get_department_category_display()}"


class KPIReportLocationBreakdown(UUIDModel, TimeStampedModel):
    """
    Location-level breakdown for KPI reports

    Stores complaint distribution by location type
    (In-Patient, Out-Patient, ER).
    """

    kpi_report = models.ForeignKey(KPIReport, on_delete=models.CASCADE, related_name="location_breakdowns")

    location_type = models.CharField(
        max_length=50,
        choices=[
            ("Inpatient", "Inpatient"),
            ("Outpatient", "Outpatient"),
            ("Emergency", "Emergency"),
        ],
        help_text=_("Location type category"),
    )

    complaint_count = models.IntegerField(default=0)
    percentage = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    class Meta:
        ordering = ["location_type"]
        unique_together = [["kpi_report", "location_type"]]
        verbose_name = "KPI Location Breakdown"
        verbose_name_plural = "KPI Location Breakdowns"

    def __str__(self):
        return f"{self.kpi_report} - {self.location_type}: {self.percentage}%"


class KPIReportSourceBreakdown(UUIDModel, TimeStampedModel):
    """
    Complaint source breakdown for KPI reports

    Stores percentage distribution of complaints by source
    (Patient, Family, Staff, MOH, CHI, etc.)
    """

    kpi_report = models.ForeignKey(KPIReport, on_delete=models.CASCADE, related_name="source_breakdowns")

    source_name = models.CharField(max_length=100)
    complaint_count = models.IntegerField(default=0)
    percentage = models.DecimalField(max_digits=5, decimal_places=2, default=0.00)

    class Meta:
        ordering = ["-complaint_count"]
        verbose_name = "KPI Source Breakdown"
        verbose_name_plural = "KPI Source Breakdowns"

    def __str__(self):
        return f"{self.kpi_report} - {self.source_name}: {self.percentage}%"
