"""
Physicians models - Physician ratings and performance tracking

This module implements physician performance tracking:
- Monthly rating aggregation from surveys
- Performance metrics
- Leaderboards
- HIS Doctor Rating imports
"""

from django.db import models

from apps.core.models import TimeStampedModel, UUIDModel


class PhysicianMonthlyRating(UUIDModel, TimeStampedModel):
    """
    Physician monthly rating - aggregated from survey responses.

    Calculated monthly from all surveys mentioning this physician.
    """

    staff = models.ForeignKey("organizations.Staff", on_delete=models.CASCADE, related_name="monthly_ratings")

    # Time period
    year = models.IntegerField(db_index=True)
    month = models.IntegerField(db_index=True, help_text="1-12")

    # Ratings
    average_rating = models.DecimalField(max_digits=3, decimal_places=2, help_text="Average rating (1-5)")
    total_surveys = models.IntegerField(help_text="Number of surveys included")
    positive_count = models.IntegerField(default=0)
    neutral_count = models.IntegerField(default=0)
    negative_count = models.IntegerField(default=0)

    rating_1_count = models.IntegerField(default=0)
    rating_2_count = models.IntegerField(default=0)
    rating_3_count = models.IntegerField(default=0)
    rating_4_count = models.IntegerField(default=0)
    rating_5_count = models.IntegerField(default=0)

    # Breakdown by journey stage
    md_consult_rating = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)

    # Ranking
    hospital_rank = models.IntegerField(null=True, blank=True, help_text="Rank within hospital")
    department_rank = models.IntegerField(null=True, blank=True, help_text="Rank within department")

    # Metadata
    metadata = models.JSONField(default=dict, blank=True)

    class Meta:
        ordering = ["-year", "-month", "-average_rating"]
        unique_together = [["staff", "year", "month"]]
        indexes = [
            models.Index(fields=["staff", "-year", "-month"]),
            models.Index(fields=["year", "month", "-average_rating"]),
        ]

    def __str__(self):
        return f"{self.staff.get_full_name()} - {self.year}-{self.month:02d}: {self.average_rating}"


class PhysicianIndividualRating(UUIDModel, TimeStampedModel):
    """
    Individual physician rating from HIS or manual import.

    Stores each individual patient rating before aggregation.
    Source can be HIS integration, CSV import, or manual entry.
    """

    class RatingSource(models.TextChoices):
        HIS_API = "his_api", "HIS API"
        CSV_IMPORT = "csv_import", "CSV Import"
        MANUAL = "manual", "Manual Entry"

    class PatientType(models.TextChoices):
        INPATIENT = "IP", "Inpatient"
        OUTPATIENT = "OP", "Outpatient"
        EMERGENCY = "ER", "Emergency"
        DAYCASE = "DC", "Day Case"

    # Links
    staff = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.CASCADE,
        related_name="individual_ratings",
        null=True,
        blank=True,
        help_text="Linked staff record (if matched)",
    )
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="physician_ratings")

    # Source tracking
    source = models.CharField(max_length=20, choices=RatingSource.choices, default=RatingSource.MANUAL)
    source_reference = models.CharField(
        max_length=100, blank=True, help_text="Reference ID from source system (e.g., HIS record ID)"
    )

    # Doctor information (as received from source)
    doctor_name_raw = models.CharField(max_length=300, help_text="Doctor name as received (may include ID prefix)")
    doctor_id = models.CharField(
        max_length=50, blank=True, db_index=True, help_text="Doctor ID extracted from source (e.g., '10738')"
    )
    doctor_name = models.CharField(max_length=200, blank=True, help_text="Clean doctor name without ID")
    department_name = models.CharField(max_length=200, blank=True, help_text="Department name from source")

    # Patient information (optional - HIS ratings don't include patient data)
    patient_uhid = models.CharField(
        max_length=100, blank=True, null=True, db_index=True, help_text="Patient UHID/MRN (optional for HIS ratings)"
    )
    patient_name = models.CharField(max_length=300, blank=True, null=True)
    patient_gender = models.CharField(max_length=20, blank=True, default="")
    patient_age = models.CharField(max_length=50, blank=True, default="")
    patient_nationality = models.CharField(max_length=100, blank=True, default="")
    patient_phone = models.CharField(max_length=30, blank=True, default="")
    patient_type = models.CharField(max_length=10, choices=PatientType.choices, blank=True, null=True)

    # Visit dates
    admit_date = models.DateTimeField(null=True, blank=True)
    discharge_date = models.DateTimeField(null=True, blank=True)

    # Rating data
    rating = models.IntegerField(help_text="Rating from 1-5")
    feedback = models.TextField(blank=True)
    rating_date = models.DateTimeField()

    # Aggregation tracking
    is_aggregated = models.BooleanField(
        default=False, help_text="Whether this rating has been included in monthly aggregation"
    )
    aggregated_at = models.DateTimeField(null=True, blank=True)

    # Metadata
    metadata = models.JSONField(default=dict, blank=True, help_text="Additional data from source")

    class Meta:
        ordering = ["-rating_date", "-created_at"]
        indexes = [
            models.Index(fields=["hospital", "-rating_date"]),
            models.Index(fields=["staff", "-rating_date"]),
            models.Index(fields=["doctor_id", "-rating_date"]),
            models.Index(fields=["is_aggregated", "rating_date"]),
            models.Index(fields=["patient_uhid", "-rating_date"]),
        ]

    def __str__(self):
        return f"{self.doctor_name or self.doctor_name_raw} - {self.rating}/5 on {self.rating_date.date()}"


class DoctorRatingImportJob(UUIDModel, TimeStampedModel):
    """
    Tracks bulk doctor rating import jobs (CSV or API batch).
    """

    class JobStatus(models.TextChoices):
        PENDING = "pending", "Pending"
        PROCESSING = "processing", "Processing"
        COMPLETED = "completed", "Completed"
        FAILED = "failed", "Failed"
        PARTIAL = "partial", "Partial Success"

    class JobSource(models.TextChoices):
        HIS_API = "his_api", "HIS API"
        CSV_UPLOAD = "csv_upload", "CSV Upload"

    # Job info
    name = models.CharField(max_length=200)
    status = models.CharField(max_length=20, choices=JobStatus.choices, default=JobStatus.PENDING)
    source = models.CharField(max_length=20, choices=JobSource.choices)

    # User & Organization
    created_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="doctor_rating_jobs"
    )
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="doctor_rating_jobs")

    # Progress tracking
    total_records = models.IntegerField(default=0)
    processed_count = models.IntegerField(default=0)
    success_count = models.IntegerField(default=0)
    failed_count = models.IntegerField(default=0)
    skipped_count = models.IntegerField(default=0)

    # Timing
    started_at = models.DateTimeField(null=True, blank=True)
    completed_at = models.DateTimeField(null=True, blank=True)

    # Results
    results = models.JSONField(default=dict, blank=True, help_text="Processing results and errors")
    error_message = models.TextField(blank=True)

    # Raw data storage (for CSV uploads)
    raw_data = models.JSONField(default=list, blank=True, help_text="Stored raw data for processing")

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.name} - {self.status}"

    @property
    def progress_percentage(self):
        if self.total_records == 0:
            return 0
        return int((self.processed_count / self.total_records) * 100)

    @property
    def is_complete(self):
        return self.status in [self.JobStatus.COMPLETED, self.JobStatus.FAILED, self.JobStatus.PARTIAL]

    @property
    def duration_seconds(self):
        if self.started_at and self.completed_at:
            return (self.completed_at - self.started_at).total_seconds()
        return None
