"""
Complaints models - Complaint management with SLA tracking

This module implements the complaint management system that:
- Tracks complaints with SLA deadlines
- Manages complaint workflow (open → in progress → resolved → closed)
- Triggers resolution satisfaction surveys
- Creates PX actions for negative resolution satisfaction
- Maintains complaint timeline and attachments
"""

from datetime import timedelta

from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from apps.core.encryption import EncryptedCharField, compute_national_id_hash, mask_national_id
from apps.core.models import PriorityChoices, SeverityChoices, SoftDeleteModel, TenantModel, TimeStampedModel, UUIDModel
from apps.organizations.models import LocationType


class ComplaintStatus(models.TextChoices):
    """Complaint status choices"""

    OPEN = "open", _("Open")
    IN_PROGRESS = "in_progress", _("In Progress")
    PARTIALLY_RESOLVED = "partially_resolved", _("Partially Resolved")
    RESOLVED = "resolved", _("Resolved")
    CLOSED = "closed", _("Closed")
    CANCELLED = "cancelled", _("Cancelled")
    PENDING_EXTERNAL = "pending_external", _("Pending External")
    OVR_PENDING = "ovr_pending", _("OVR Pending Approval")


class PatientContactStatus(models.TextChoices):
    """Patient contact status - tracks whether the patient has been contacted"""

    NOT_CONTACTED = "not_contacted", _("Not Contacted")
    CONTACTED = "contacted", _("Contacted")
    CONTACTED_NO_RESPONSE = "contacted_no_response", _("Contacted, No Response")


class DelayReasonChoices(models.TextChoices):
    """Delay reason for 72h closure"""

    DEPARTMENT_NO_RESPONSE = "department_no_response", _("Department No Response")
    ESCALATED = "escalated", _("Escalated")
    PATIENT_NOT_SATISFIED = "patient_not_satisfied", _("Patient Not Satisfied with Complaint Resolution")


class ResolutionCategory(models.TextChoices):
    """Resolution category choices"""

    FULL_ACTION_TAKEN = "full_action_taken", _("Full Action Taken")
    PARTIAL_ACTION_TAKEN = "partial_action_taken", _("Partial Action Taken")
    NO_ACTION_NEEDED = "no_action_needed", _("No Action Needed")
    CANNOT_RESOLVE = "cannot_resolve", _("Cannot Resolve")
    PATIENT_WITHDRAWN = "patient_withdrawn", _("Patient Withdrawn")


class ResolutionOutcome(models.TextChoices):
    """Resolution outcome - who was in wrong/right"""

    PATIENT = "patient", _("Patient")
    HOSPITAL = "hospital", _("Hospital")
    OTHER = "other", _("Other — please specify")


class ComplaintType(models.TextChoices):
    """Complaint type choices - distinguish between complaints and appreciations"""

    COMPLAINT = "complaint", _("Complaint")
    APPRECIATION = "appreciation", _("Appreciation")


class ComplaintSourceType(models.TextChoices):
    """Complaint source type choices - Internal vs External"""

    INTERNAL = "internal", _("Internal")
    EXTERNAL = "external", _("External")


class ComplaintSource(models.TextChoices):
    """Complaint source choices"""

    PATIENT = "patient", _("Patient")
    FAMILY = "family", _("Family Member")
    STAFF = "staff", _("Staff")
    SURVEY = "survey", _("Survey")
    SOCIAL_MEDIA = "social_media", _("Social Media")
    CALL_CENTER = "call_center", _("Call Center")
    MOH = "moh", _("Ministry of Health")
    CHI = "chi", _("Council of Health Insurance")
    OTHER = "other", _("Other")


class ComplaintCategory(UUIDModel, TimeStampedModel):
    """
    Custom complaint categories per hospital with 4-level SHCT taxonomy.

    Supports hierarchical structure:
    - Level 1: Domain (CLINICAL, MANAGEMENT, RELATIONSHIPS)
    - Level 2: Category (Quality, Safety, Communication, etc.)
    - Level 3: Subcategory (Examination, Patient Journey, etc.)
    - Level 4: Classification (Examination not performed, etc.)

    Uses ManyToMany to allow categories to be shared across multiple hospitals.
    """

    class LevelChoices(models.IntegerChoices):
        DOMAIN = 1, _("Domain")
        CATEGORY = 2, _("Category")
        SUBCATEGORY = 3, _("Subcategory")
        CLASSIFICATION = 4, _("Classification")

    class DomainTypeChoices(models.TextChoices):
        CLINICAL = "CLINICAL", _("Clinical")
        MANAGEMENT = "MANAGEMENT", _("Management")
        RELATIONSHIPS = "RELATIONSHIPS", _("Relationships")

    hospitals = models.ManyToManyField(
        "organizations.Hospital",
        blank=True,
        related_name="complaint_categories",
        help_text="Empty list = system-wide category. Add hospitals to share category.",
    )

    code = models.CharField(max_length=100, help_text="Unique code for this category")

    name_en = models.CharField(max_length=200)
    name_ar = models.CharField(max_length=200, blank=True)

    description_en = models.TextField(blank=True)
    description_ar = models.TextField(blank=True)

    parent = models.ForeignKey(
        "self",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="subcategories",
        help_text="Parent category for hierarchical structure",
    )

    level = models.IntegerField(
        choices=LevelChoices.choices,
        help_text="Hierarchy level (1=Domain, 2=Category, 3=Subcategory, 4=Classification)",
    )

    domain_type = models.CharField(
        max_length=20, choices=DomainTypeChoices.choices, blank=True, help_text="Domain type for top-level categories"
    )

    order = models.IntegerField(default=0, help_text="Display order")

    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["order", "name_en"]
        verbose_name_plural = "Complaint Categories"
        indexes = [
            models.Index(fields=["code"]),
        ]

    def __str__(self):
        level_display = self.get_level_display()
        hospital_count = self.hospitals.count()

        if hospital_count == 0:
            hospital_info = "System-wide"
        elif hospital_count == 1:
            hospital_info = self.hospitals.first().name
        else:
            hospital_info = f"{hospital_count} hospitals"

        if self.level == self.LevelChoices.CLASSIFICATION and self.parent:
            parent_path = " > ".join([self.parent.name_en])
            return f"{level_display}: {parent_path} > {self.name_en}"
        else:
            return f"{level_display}: {self.name_en} ({hospital_info})"

    def get_localized_name(self):
        from django.utils.translation import get_language

        if get_language() == "ar" and self.name_ar:
            return self.name_ar
        return self.name_en


class Complaint(UUIDModel, TimeStampedModel, SoftDeleteModel):
    """
    Complaint model with SLA tracking.

    Workflow:
    1. OPEN - Complaint received
    2. IN_PROGRESS - Being investigated
    3. RESOLVED - Solution provided
    4. CLOSED - Confirmed closed (triggers resolution satisfaction survey)

    SLA:
    - Calculated based on severity and hospital configuration
    - Reminders sent before due date
    - Escalation triggered when overdue
    """

    # Patient and encounter information
    patient = models.ForeignKey(
        "organizations.Patient", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaints"
    )

    # Contact information for anonymous/unregistered submissions
    contact_name = models.CharField(max_length=200, blank=True)
    contact_phone = models.CharField(max_length=20, blank=True)
    contact_email = models.EmailField(blank=True)

    # Public complaint form fields
    relation_to_patient = models.CharField(
        max_length=20,
        choices=[
            ("patient", _("Patient")),
            ("relative", _("Relative")),
            ("friend", _("Friend")),
            ("other", _("Other")),
        ],
        blank=True,
        verbose_name=_("Relation to Patient"),
        help_text="Complainant's relationship to the patient",
    )

    patient_name = models.CharField(
        max_length=200, blank=True, verbose_name="Patient Name", help_text="Name of the patient involved"
    )

    national_id = EncryptedCharField(
        max_length=512, blank=True, verbose_name="National ID/Iqama No.", help_text="Saudi National ID or Iqama number"
    )
    national_id_hash = models.CharField(max_length=64, blank=True, db_index=True)

    incident_date = models.DateField(
        null=True, blank=True, verbose_name="Incident Date", help_text="Date when the incident occurred"
    )

    staff_name = models.CharField(
        max_length=200, blank=True, verbose_name="Staff Involved", help_text="Name of staff member involved (if known)"
    )

    expected_result = models.TextField(
        blank=True, verbose_name="Expected Complaint Result", help_text="What the complainant expects as a resolution"
    )

    # Reference number for tracking
    reference_number = models.CharField(
        max_length=50,
        unique=True,
        null=True,
        blank=True,
        help_text="Unique reference number for patient tracking",
    )

    encounter_id = models.CharField(
        max_length=100, blank=True, db_index=True, help_text="Related encounter ID if applicable"
    )

    # Organization
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="complaints")
    department = models.ForeignKey(
        "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaints"
    )
    staff = models.ForeignKey(
        "organizations.Staff", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaints"
    )
    location_type = models.CharField(
        max_length=20,
        choices=LocationType.choices,
        blank=True,
        help_text="Where the incident occurred (OP/IP/ER/GO)",
    )
    area = models.ForeignKey(
        "organizations.Area", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaints"
    )

    # Complaint details
    title = models.CharField(max_length=500)
    description = models.TextField()

    ai_brief_en = models.CharField(
        max_length=100, blank=True, db_index=True, help_text="AI-generated 2-3 word summary in English"
    )
    ai_brief_ar = models.CharField(max_length=100, blank=True, help_text="AI-generated 2-3 word summary in Arabic")

    # Classification - 4-level SHCT taxonomy
    domain = models.ForeignKey(
        ComplaintCategory,
        on_delete=models.PROTECT,
        related_name="complaints_domain",
        null=True,
        blank=True,
        help_text="Level 1: Domain",
    )
    category = models.ForeignKey(
        ComplaintCategory,
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="Level 2: Category",
    )
    # Keep CharField for backward compatibility (stores the code)
    subcategory = models.CharField(max_length=100, blank=True, help_text="Level 3: Subcategory code (legacy)")
    classification = models.CharField(max_length=100, blank=True, help_text="Level 4: Classification code (legacy)")
    # New FK fields for proper relationships
    subcategory_obj = models.ForeignKey(
        ComplaintCategory,
        on_delete=models.PROTECT,
        related_name="complaints_subcategory",
        null=True,
        blank=True,
        help_text="Level 3: Subcategory",
    )
    classification_obj = models.ForeignKey(
        ComplaintCategory,
        on_delete=models.PROTECT,
        related_name="complaints_classification",
        null=True,
        blank=True,
        help_text="Level 4: Classification",
    )

    # Location hierarchy - legacy fields
    legacy_location = models.ForeignKey(
        "organizations.LegacyLocation",
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_main_section = models.ForeignKey(
        "organizations.LegacyMainSection",
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_subsection = models.ForeignKey(
        "organizations.LegacySubSection",
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )

    # New hierarchy (from 4th Version Excel)
    section = models.ForeignKey(
        "organizations.Section",
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="Section within department",
    )

    # Legacy raw fields for mapping
    old_location_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original location Arabic text from complaint",
    )
    old_main_section_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original main section Arabic text from complaint",
    )
    old_subsection_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original subsection Arabic text from complaint",
    )

    # Type (complaint vs appreciation)
    complaint_type = models.CharField(
        max_length=20,
        choices=ComplaintType.choices,
        default=ComplaintType.COMPLAINT,
        db_index=True,
        help_text="Type of feedback (complaint vs appreciation)",
    )

    # Source type (Internal vs External)
    complaint_source_type = models.CharField(
        max_length=20,
        choices=ComplaintSourceType.choices,
        default=ComplaintSourceType.INTERNAL,
        db_index=True,
        help_text="Source type (Internal = staff-generated, External = patient/public-generated)",
    )

    # Priority and severity
    priority = models.CharField(
        max_length=20, choices=PriorityChoices.choices, default=PriorityChoices.MEDIUM, db_index=True
    )
    severity = models.CharField(
        max_length=20, choices=SeverityChoices.choices, default=SeverityChoices.MEDIUM, db_index=True
    )

    # Source
    source = models.ForeignKey(
        "px_sources.PXSource",
        on_delete=models.PROTECT,
        related_name="complaints",
        null=True,
        blank=True,
        help_text="Source of complaint",
    )

    # Creator tracking
    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_complaints",
        help_text="User who created this complaint (SourceUser or Patient)",
    )

    # Status and workflow
    status = models.CharField(
        max_length=25, choices=ComplaintStatus.choices, default=ComplaintStatus.OPEN, db_index=True
    )

    patient_contact_status = models.CharField(
        max_length=30,
        choices=PatientContactStatus.choices,
        default=PatientContactStatus.NOT_CONTACTED,
        db_index=True,
        help_text="Tracks whether the patient has been contacted regarding this complaint",
    )
    patient_contact_status_at = models.DateTimeField(
        null=True, blank=True, help_text="When the patient contact status was last updated"
    )
    patient_contact_status_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="patient_contact_updated_complaints",
        help_text="User who last updated the patient contact status",
    )

    # Assignment
    assigned_to = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="assigned_complaints"
    )
    assigned_at = models.DateTimeField(null=True, blank=True)

    # Activation tracking
    activated_at = models.DateTimeField(
        null=True,
        blank=True,
        db_index=True,
        help_text="Timestamp when complaint was first activated (moved from OPEN to IN_PROGRESS)",
    )

    # SLA tracking
    due_at = models.DateTimeField(db_index=True, help_text="SLA deadline")
    is_overdue = models.BooleanField(default=False, db_index=True)
    breached_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="Timestamp when complaint first breached SLA"
    )
    reminder_sent_at = models.DateTimeField(null=True, blank=True, help_text="First SLA reminder timestamp")
    second_reminder_sent_at = models.DateTimeField(null=True, blank=True, help_text="Second SLA reminder timestamp")
    escalated_at = models.DateTimeField(null=True, blank=True)

    # Explanation tracking
    explanation_requested = models.BooleanField(
        default=False, help_text="Whether an explanation has been requested from staff"
    )
    explanation_requested_at = models.DateTimeField(
        null=True, blank=True, help_text="When explanation request was first sent to staff"
    )
    explanation_received_at = models.DateTimeField(
        null=True, blank=True, help_text="When explanation was received from staff"
    )
    explanation_delay_reason = models.TextField(blank=True, help_text="Reason for delay in receiving staff explanation")

    # Resolution
    resolution = models.TextField(blank=True)
    resolution_sent_at = models.DateTimeField(null=True, blank=True)
    resolution_category = models.CharField(
        max_length=50, choices=ResolutionCategory.choices, blank=True, db_index=True, help_text="Category of resolution"
    )
    resolution_outcome = models.CharField(
        max_length=20,
        choices=ResolutionOutcome.choices,
        blank=True,
        db_index=True,
        help_text="Who was in wrong/right (Patient / Hospital / Other)",
    )
    resolution_outcome_other = models.TextField(
        blank=True, help_text="Specify if Other was selected for resolution outcome"
    )
    resolved_at = models.DateTimeField(null=True, blank=True)
    resolved_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="resolved_complaints"
    )

    # Closure
    closed_at = models.DateTimeField(null=True, blank=True)
    closed_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="closed_complaints"
    )

    cancelled_at = models.DateTimeField(null=True, blank=True)
    cancelled_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="cancelled_complaints"
    )

    partially_resolved_at = models.DateTimeField(null=True, blank=True)
    partially_resolved_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="partially_resolved_complaints"
    )

    # Reopen
    reopened_at = models.DateTimeField(null=True, blank=True)
    reopened_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="reopened_complaints"
    )
    reopened_from = models.ForeignKey(
        "self", on_delete=models.SET_NULL, null=True, blank=True, related_name="reopenings",
        help_text="Original complaint this was reopened from"
    )

    # Resolution satisfaction survey
    resolution_survey = models.ForeignKey(
        "surveys.SurveyInstance", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaint_resolution"
    )
    resolution_survey_sent_at = models.DateTimeField(null=True, blank=True)

    # Direct satisfaction tracking (from calls/follow-ups)
    satisfaction = models.CharField(
        max_length=20,
        choices=[
            ("satisfied", _("Satisfied")),
            ("neutral", _("Neutral")),
            ("dissatisfied", _("Dissatisfied")),
            ("no_response", _("No Response")),
        ],
        blank=True,
        db_index=True,
        help_text="Direct satisfaction feedback from patient follow-up call",
    )
    satisfaction_set_at = models.DateTimeField(null=True, blank=True, help_text="When satisfaction was last set")

    # External references
    moh_reference = models.CharField(max_length=100, blank=True, help_text="Ministry of Health reference number")
    moh_reference_date = models.DateField(null=True, blank=True, help_text="MOH reference date")
    chi_reference = models.CharField(
        max_length=100, blank=True, help_text="Council of Health Insurance reference number"
    )
    chi_reference_date = models.DateField(null=True, blank=True, help_text="CHI reference date")

    # File number (patient MRN)
    file_number = models.CharField(max_length=100, blank=True, db_index=True, help_text="Patient file/MRN number")

    # Workflow timeline (Step 1 fields)
    form_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="When complaint form was sent to the complained department"
    )
    forwarded_to_dept_at = models.DateTimeField(
        null=True, blank=True, help_text="When complaint was forwarded to the involved department"
    )
    sent_to_department = models.BooleanField(
        default=False, help_text="Whether this complaint has been sent to the primary department for visibility"
    )
    sent_to_department_at = models.DateTimeField(
        null=True, blank=True, help_text="When the complaint was sent to the primary department"
    )
    response_date = models.DateField(null=True, blank=True, help_text="Date when response was received")

    # Complaint details (Step 1 fields)
    complaint_subject = models.CharField(
        max_length=500, blank=True, help_text="Main complaint subject (from Excel classification)"
    )
    action_taken_by_dept = models.TextField(blank=True, help_text="Action taken by the responsible department")
    action_result = models.TextField(blank=True, help_text="Result of the action/investigation taken")
    recommendation_action_plan = models.TextField(blank=True, help_text="Solutions, suggestions, and action plan")
    delay_reason_closure = models.CharField(
        max_length=50,
        choices=DelayReasonChoices.choices,
        blank=True,
        help_text="Reason for not closing the complaint within 72 hours",
    )
    was_pending_external = models.BooleanField(
        default=False, help_text="Whether this complaint was ever in pending_external status"
    )
    pending_external_set_at = models.DateTimeField(
        null=True, blank=True, help_text="When complaint was set to pending_external status"
    )

    # Escalated as OVR tracking
    is_escalated_ovr = models.BooleanField(default=False, db_index=True, help_text="Whether complaint is escalated as OVR")
    escalated_ovr_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="escalated_ovr_complaints",
        help_text="User who escalated as OVR",
    )
    escalated_ovr_at = models.DateTimeField(null=True, blank=True, help_text="When OVR escalation was set")

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

    notes = GenericRelation("core.Note")

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["status", "-created_at"]),
            models.Index(fields=["hospital", "status", "-created_at"]),
            models.Index(fields=["assigned_to", "status", "-created_at"]),
            models.Index(fields=["department", "status", "-created_at"]),
            models.Index(fields=["is_overdue", "status"]),
            models.Index(fields=["due_at", "status"]),
        ]

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

    def get_absolute_url(self):
        from django.urls import reverse

        return reverse("complaints:complaint_detail", kwargs={"pk": self.pk})

    def get_owner(self):
        """
        Returns the owner of this complaint.
        Cascade: section(champion, supervisor, deputy_supervisor)
        -> department(champion, deputy_manager, supervisor,
           deputy_supervisor, manager_2nd, manager_3rd).
        Returns: Staff instance or None.
        """
        if self.section:
            for role in ("champion", "supervisor", "deputy_supervisor"):
                owner = getattr(self.section, role, None)
                if owner:
                    return owner
        if self.department:
            dept = self.department
            for role in ("champion", "deputy_manager",
                         "supervisor", "deputy_supervisor",
                         "manager_2nd", "manager_3rd"):
                owner = getattr(dept, role, None)
                if owner:
                    return owner
        return None

    def get_masked_national_id(self):
        return mask_national_id(self.national_id)

    def save(self, *args, **kwargs):
        """Calculate SLA due date on creation, generate reference number, and sync complaint_type from metadata"""
        # Track status change for signals
        if self.pk:
            try:
                old_instance = Complaint.objects.get(pk=self.pk)
                self._status_was = old_instance.status
            except Complaint.DoesNotExist:
                self._status_was = None

        # Generate reference number if not set (for all creation methods: form, API, admin)
        if not self.reference_number:
            from apps.core.reference import generate_reference

            self.reference_number = generate_reference("CMP", self.hospital)

        if not self.due_at:
            self.due_at = self.calculate_sla_due_date()

        # Sync complaint_type from AI metadata if not already set
        # This ensures that model field stays in sync with AI classification
        if self.metadata and "ai_analysis" in self.metadata:
            ai_complaint_type = self.metadata["ai_analysis"].get("complaint_type", "complaint")
            # Only sync if model field is still default 'complaint'
            # This preserves any manual changes while fixing AI-synced complaints
            if self.complaint_type == "complaint" and ai_complaint_type != "complaint":
                self.complaint_type = ai_complaint_type

        if self.national_id:
            self.national_id_hash = compute_national_id_hash(self.national_id)
        else:
            self.national_id_hash = ""

        self._sync_department_timestamps()

        super().save(*args, **kwargs)

    def _sync_department_timestamps(self):
        """Sync forwarded_to_dept_at and sent_to_department_at — keep both in agreement."""
        now = timezone.now()
        if self.sent_to_department and not self.sent_to_department_at:
            self.sent_to_department_at = now
        if self.sent_to_department_at and not self.forwarded_to_dept_at:
            self.forwarded_to_dept_at = self.sent_to_department_at
        if self.forwarded_to_dept_at and not self.sent_to_department_at:
            self.sent_to_department_at = self.forwarded_to_dept_at

    def calculate_sla_due_date(self):
        """
        Calculate SLA due date based on source, severity, and hospital configuration.

        Priority order:
        1. Source-based config (MOH, CHI, Internal)
        2. Severity/priority-based config
        3. Settings defaults

        Source-based configs take precedence over severity/priority-based configs.
        """
        # Try source-based SLA config first
        if self.source:
            try:
                sla_config = ComplaintSLAConfig.objects.get(hospital=self.hospital, source=self.source, is_active=True)
                sla_hours = sla_config.sla_hours
                return timezone.now() + timedelta(hours=sla_hours)
            except ComplaintSLAConfig.DoesNotExist:
                pass  # Fall through to next option

        # Try severity/priority-based config
        try:
            sla_config = ComplaintSLAConfig.objects.get(
                hospital=self.hospital,
                source__isnull=True,  # Explicitly check for null source
                severity=self.severity,
                priority=self.priority,
                is_active=True,
            )
            sla_hours = sla_config.sla_hours
            return timezone.now() + timedelta(hours=sla_hours)
        except ComplaintSLAConfig.DoesNotExist:
            pass  # Fall through to next option

        # Try severity/priority-based config without source filter (backward compatibility)
        try:
            sla_config = ComplaintSLAConfig.objects.get(
                hospital=self.hospital, severity=self.severity, priority=self.priority, is_active=True
            )
            sla_hours = sla_config.sla_hours
            return timezone.now() + timedelta(hours=sla_hours)
        except ComplaintSLAConfig.DoesNotExist:
            pass  # Fall back to settings

        # Fall back to settings defaults
        sla_hours = settings.SLA_DEFAULTS["complaint"].get(self.severity, settings.SLA_DEFAULTS["complaint"]["medium"])

        return timezone.now() + timedelta(hours=sla_hours)

    def get_sla_config(self):
        """
        Get the SLA config for this complaint.

        Returns the source-based or severity/priority-based config that applies to this complaint.
        Returns None if no config is found (will use defaults).
        """
        # Try source-based SLA config first
        if self.source:
            try:
                return ComplaintSLAConfig.objects.get(hospital=self.hospital, source=self.source, is_active=True)
            except ComplaintSLAConfig.DoesNotExist:
                pass  # Fall through to next option

        # Try severity/priority-based config
        try:
            return ComplaintSLAConfig.objects.get(
                hospital=self.hospital,
                source__isnull=True,
                severity=self.severity,
                priority=self.priority,
                is_active=True,
            )
        except ComplaintSLAConfig.DoesNotExist:
            pass  # Fall through to next option

        # Try severity/priority-based config without source filter (backward compatibility)
        try:
            return ComplaintSLAConfig.objects.get(
                hospital=self.hospital, severity=self.severity, priority=self.priority, is_active=True
            )
        except ComplaintSLAConfig.DoesNotExist:
            pass  # No config found

        return None

    def check_overdue(self):
        """Check if complaint is overdue and update status"""
        if self.status in [ComplaintStatus.CLOSED, ComplaintStatus.CANCELLED]:
            return False

        if self.due_at and timezone.now() > self.due_at:
            if not self.is_overdue:
                self.is_overdue = True
                self.breached_at = timezone.now()
                self.save(update_fields=["is_overdue", "breached_at"])
            return True
        return False

    @property
    def is_active_status(self):
        """
        Check if complaint is in an active status (can be worked on).
        Active statuses: OPEN, IN_PROGRESS, PARTIALLY_RESOLVED, PENDING_EXTERNAL
        Inactive statuses: RESOLVED, CLOSED, CANCELLED
        """
        return self.status in [
            ComplaintStatus.OPEN,
            ComplaintStatus.IN_PROGRESS,
            ComplaintStatus.PARTIALLY_RESOLVED,
            ComplaintStatus.PENDING_EXTERNAL,
        ]

    @property
    def sla_time_remaining(self):
        if not self.due_at:
            return None
        if self.status in [ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED, ComplaintStatus.CANCELLED]:
            return None
        remaining = self.due_at - timezone.now()
        if remaining.total_seconds() <= 0:
            return None
        return remaining

    @property
    def sla_is_overdue_display(self):
        if not self.due_at:
            return None
        if self.status in [ComplaintStatus.RESOLVED, ComplaintStatus.CLOSED, ComplaintStatus.CANCELLED]:
            return None
        remaining = self.due_at - timezone.now()
        if remaining.total_seconds() <= 0:
            overdue = abs(remaining)
            days = overdue.days
            hours, remainder = divmod(overdue.seconds, 3600)
            minutes = remainder // 60
            if days > 0:
                return f"Overdue by {days}d {hours}h"
            return f"Overdue by {hours}h {minutes}m"
        return None

    PUBLIC_STATUS_MAP = {
        ComplaintStatus.OPEN: {"label": _("Received"), "slug": "received", "progress": 15, "css": "amber"},
        ComplaintStatus.IN_PROGRESS: {"label": _("In Progress"), "slug": "in_progress", "progress": 50, "css": "blue"},
        ComplaintStatus.PARTIALLY_RESOLVED: {
            "label": _("In Progress"),
            "slug": "in_progress",
            "progress": 75,
            "css": "blue",
        },
        ComplaintStatus.RESOLVED: {"label": _("Resolved"), "slug": "resolved", "progress": 100, "css": "emerald"},
        ComplaintStatus.CLOSED: {"label": _("Closed"), "slug": "closed", "progress": 100, "css": "slate"},
        ComplaintStatus.CANCELLED: {"label": _("Cancelled"), "slug": "cancelled", "progress": 0, "css": "rose"},
    }

    @property
    def public_status(self):
        mapping = self.PUBLIC_STATUS_MAP.get(
            self.status,
            {
                "label": _("Received"),
                "slug": "received",
                "progress": 15,
                "css": "amber",
            },
        )
        return {
            "label": str(mapping["label"]),
            "slug": mapping["slug"],
            "progress": mapping["progress"],
            "css": mapping["css"],
        }

    @property
    def short_description_en(self):
        """Get AI-generated short description (English) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("short_description_en", "")
        return ""

    @property
    def short_description_ar(self):
        """Get AI-generated short description (Arabic) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("short_description_ar", "")
        return ""

    @property
    def short_description(self):
        """Get AI-generated short description from metadata (deprecated, use short_description_en)"""
        return self.short_description_en

    @property
    def suggested_action_en(self):
        """Get AI-generated suggested action (English) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("suggested_action_en", "")
        return ""

    @property
    def suggested_action_ar(self):
        """Get AI-generated suggested action (Arabic) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("suggested_action_ar", "")
        return ""

    @property
    def suggested_action(self):
        """Get AI-generated suggested action from metadata (deprecated, use suggested_action_en)"""
        return self.suggested_action_en

    @property
    def suggested_actions(self):
        """
        Get AI-generated suggested actions as a list from metadata.
        """
        if self.metadata and "ai_analysis" in self.metadata:
            actions = self.metadata["ai_analysis"].get("suggested_actions", [])
            if actions and isinstance(actions, list):
                return actions
            single_action = self.metadata["ai_analysis"].get("suggested_action_en", "")
            if single_action:
                return [{"action": single_action, "priority": "medium", "category": "process_improvement"}]
        return []

    @property
    def title_en(self):
        """Get AI-generated title (English) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("title_en", "")
        return ""

    @property
    def title_ar(self):
        """Get AI-generated title (Arabic) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("title_ar", "")
        return ""

    @property
    def reasoning_en(self):
        """Get AI-generated reasoning (English) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("reasoning_en", "")
        return ""

    @property
    def reasoning_ar(self):
        """Get AI-generated reasoning (Arabic) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("reasoning_ar", "")
        return ""

    @property
    def emotion(self):
        """Get AI-detected primary emotion from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion", "neutral")
        return "neutral"

    @property
    def emotion_intensity(self):
        """Get AI-detected emotion intensity (0.0 to 1.0) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion_intensity", 0.0)
        return 0.0

    @property
    def emotion_confidence(self):
        """Get AI confidence in emotion detection (0.0 to 1.0) from metadata"""
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion_confidence", 0.0)
        return 0.0

    @property
    def emotion_confidence_percent(self):
        """Get AI confidence as percentage (0-100) from metadata"""
        return self.emotion_confidence * 100

    @property
    def emotion_intensity_percent(self):
        """Get AI emotion intensity as percentage (0-100) from metadata"""
        return self.emotion_intensity * 100

    @property
    def get_emotion_display(self):
        """Get human-readable emotion display"""
        emotion_map = {
            "anger": "Anger",
            "sadness": "Sadness",
            "confusion": "Confusion",
            "fear": "Fear",
            "neutral": "Neutral",
        }
        return emotion_map.get(self.emotion, "Neutral")

    @property
    def get_emotion_badge_class(self):
        """Get Bootstrap badge class for emotion"""
        badge_map = {
            "anger": "danger",
            "sadness": "primary",
            "confusion": "warning",
            "fear": "info",
            "neutral": "secondary",
        }
        return badge_map.get(self.emotion, "secondary")

    @property
    def is_activated(self):
        return self.activated_at is not None

    @property
    def sent_to_any_department(self):
        return self.involved_departments.filter(sent=True).exists() or self.sent_to_department

    @property
    def all_departments_responded(self):
        sent = self.involved_departments.filter(sent=True)
        if not sent.exists():
            return self.sent_to_department
        return not sent.filter(response_submitted=False).exists()

    def get_tracking_url(self):
        """
        Get the public tracking URL for this complaint.
        """
        from django.contrib.sites.shortcuts import get_current_site
        from django.urls import reverse

        try:
            site = get_current_site(None)
            domain = site.domain
        except:
            domain = "localhost:8000"

        return f"https://{domain}{reverse('complaints:public_complaint_track')}?reference={self.reference_number}"


class ComplaintAttachment(UUIDModel, TimeStampedModel):
    """Complaint attachment (images, documents, etc.)"""

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(upload_to="complaints/%Y/%m/%d/")
    filename = models.CharField(max_length=500)
    file_type = models.CharField(max_length=100, blank=True)
    file_size = models.IntegerField(help_text="File size in bytes")

    uploaded_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="complaint_attachments"
    )

    description = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.complaint} - {self.filename}"


def pdf_summary_upload_to(instance, filename):
    return f"pdf_summaries/complaints/{instance.complaint_id}_ar.pdf"


class ComplaintPdfSummary(UUIDModel, TimeStampedModel):
    """Persisted PDF summary with AI-generated text and generated file."""

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="pdf_summaries")
    lang = models.CharField(max_length=5, default="ar")
    content_summary = models.TextField()
    dept_response_summary = models.TextField()
    file = models.FileField(upload_to=pdf_summary_upload_to, blank=True, null=True)
    file_size = models.IntegerField(default=0)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "PDF Summary"
        verbose_name_plural = "PDF Summaries"

    def __str__(self):
        return f"PDF Summary - {self.complaint.reference_number}"


class ComplaintUpdate(UUIDModel, TimeStampedModel):
    """
    Complaint update/timeline entry.

    Tracks all updates, status changes, and communications.
    """

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="updates")

    # Update details
    update_type = models.CharField(
        max_length=50,
        choices=[
            ("status_change", "Status Change"),
            ("assignment", "Assignment"),
            ("note", "Note"),
            ("resolution", "Resolution"),
            ("escalation", "Escalation"),
            ("communication", "Communication"),
        ],
        db_index=True,
    )

    message = models.TextField()

    # User who made the update
    created_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="complaint_updates"
    )

    # Status change tracking
    old_status = models.CharField(max_length=25, blank=True)
    new_status = models.CharField(max_length=25, blank=True)

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

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["complaint", "-created_at"]),
        ]

    def __str__(self):
        return f"{self.complaint} - {self.update_type} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"


class ComplaintSLAConfig(UUIDModel, TimeStampedModel):
    """
    SLA configuration for complaints per hospital, source, severity, and priority.

    Allows flexible SLA configuration instead of hardcoded values.
    Supports both source-based (MOH, CHI, Internal) and severity/priority-based configurations.
    """

    hospital = models.ForeignKey(
        "organizations.Hospital", on_delete=models.CASCADE, related_name="complaint_sla_configs"
    )

    source = models.ForeignKey(
        "px_sources.PXSource",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="complaint_sla_configs",
        help_text="Complaint source (MOH, CHI, Patient, etc.). Empty = severity/priority-based config",
    )

    severity = models.CharField(
        max_length=20,
        choices=SeverityChoices.choices,
        null=True,
        blank=True,
        help_text="Severity level for this SLA (optional if source is specified)",
    )

    priority = models.CharField(
        max_length=20,
        choices=PriorityChoices.choices,
        null=True,
        blank=True,
        help_text="Priority level for this SLA (optional if source is specified)",
    )

    sla_hours = models.IntegerField(help_text="Number of hours until SLA deadline")

    # Source-based reminder timing (from complaint creation)
    first_reminder_hours_after = models.IntegerField(
        default=0, help_text="Send 1st reminder X hours after complaint creation (0 = use reminder_hours_before)"
    )

    second_reminder_hours_after = models.IntegerField(
        default=0, help_text="Send 2nd reminder X hours after complaint creation (0 = use second_reminder_hours_before)"
    )

    escalation_hours_after = models.IntegerField(
        default=0, help_text="Escalate complaint X hours after creation if unresolved (0 = use overdue logic)"
    )

    # Legacy reminder timing (before deadline - kept for backward compatibility)
    reminder_hours_before = models.IntegerField(default=24, help_text="Send first reminder X hours before deadline")

    # Second reminder configuration
    second_reminder_enabled = models.BooleanField(default=False, help_text="Enable sending a second reminder")

    second_reminder_hours_before = models.IntegerField(
        default=6, help_text="Send second reminder X hours before deadline"
    )

    # Thank you email configuration
    thank_you_email_enabled = models.BooleanField(
        default=False, help_text="Send thank you email when complaint is closed"
    )

    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["hospital", "source", "severity", "priority"]
        unique_together = [["hospital", "source", "severity", "priority"]]
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
            models.Index(fields=["hospital", "source", "is_active"]),
        ]

    def __str__(self):
        source_display = self.source.name_en if self.source else "Any Source"
        sev_display = self.severity if self.severity else "Any Severity"
        pri_display = self.priority if self.priority else "Any Priority"
        return f"{self.hospital.name} - {source_display} - {sev_display}/{pri_display} - {self.sla_hours}h"

    def get_first_reminder_hours_after(self, complaint_created_at=None):
        if self.first_reminder_hours_after > 0:
            return self.first_reminder_hours_after
        else:
            return max(0, self.sla_hours - self.reminder_hours_before)

    def get_second_reminder_hours_after(self, complaint_created_at=None):
        if self.second_reminder_hours_after > 0:
            return self.second_reminder_hours_after
        elif self.second_reminder_enabled:
            return max(0, self.sla_hours - self.second_reminder_hours_before)
        else:
            return 0

    def get_escalation_hours_after(self, complaint_created_at=None):
        if self.escalation_hours_after > 0:
            return self.escalation_hours_after
        else:
            return None


class EscalationRule(UUIDModel, TimeStampedModel):
    """
    Configurable escalation rules for complaints.

    Defines who receives escalated complaints based on conditions.
    Supports multi-level escalation with configurable hierarchy.
    """

    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="escalation_rules")

    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)

    # Escalation level (supports multi-level escalation)
    escalation_level = models.IntegerField(default=1, help_text="Escalation level (1 = first level, 2 = second, etc.)")

    max_escalation_level = models.IntegerField(
        default=3, help_text="Maximum escalation level before stopping (default: 3)"
    )

    # Trigger conditions
    trigger_on_overdue = models.BooleanField(default=True, help_text="Trigger when complaint is overdue")

    trigger_hours_overdue = models.IntegerField(default=0, help_text="Trigger X hours after overdue (0 = immediately)")

    # Reminder-based escalation
    reminder_escalation_enabled = models.BooleanField(
        default=False, help_text="Enable escalation after reminder if no action taken"
    )

    reminder_escalation_hours = models.IntegerField(
        default=24, help_text="Escalate X hours after reminder if no action"
    )

    # Escalation target
    escalate_to_role = models.CharField(
        max_length=50,
        choices=[
            ("department_manager", "Department Manager"),
            ("hospital_admin", "Hospital Admin"),
            ("medical_director", "Medical Director"),
            ("admin_director", "Administrative Director"),
            ("px_admin", "PX Admin"),
            ("ceo", "CEO"),
            ("specific_user", "Specific User"),
        ],
        help_text="Role to escalate to",
    )

    escalate_to_user = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="escalation_target_rules",
        help_text="Specific user if escalate_to_role is 'specific_user'",
    )

    # Conditions
    severity_filter = models.CharField(
        max_length=20,
        choices=SeverityChoices.choices,
        blank=True,
        help_text="Only escalate complaints with this severity (blank = all)",
    )

    priority_filter = models.CharField(
        max_length=20,
        choices=PriorityChoices.choices,
        blank=True,
        help_text="Only escalate complaints with this priority (blank = all)",
    )

    order = models.IntegerField(default=0, help_text="Escalation order (lower = first)")

    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["hospital", "order"]
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
        ]

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


class ComplaintThreshold(UUIDModel, TimeStampedModel):
    """
    Configurable thresholds for complaint-related triggers.

    Defines when to trigger actions based on metrics (e.g., survey scores).
    """

    hospital = models.ForeignKey(
        "organizations.Hospital", on_delete=models.CASCADE, related_name="complaint_thresholds"
    )

    threshold_type = models.CharField(
        max_length=50,
        choices=[
            ("resolution_survey_score", "Resolution Survey Score"),
            ("response_time", "Response Time"),
            ("resolution_time", "Resolution Time"),
        ],
        help_text="Type of threshold",
    )

    threshold_value = models.FloatField(help_text="Threshold value (e.g., 50 for 50% score)")

    comparison_operator = models.CharField(
        max_length=10,
        choices=[
            ("lt", "Less Than"),
            ("lte", "Less Than or Equal"),
            ("gt", "Greater Than"),
            ("gte", "Greater Than or Equal"),
            ("eq", "Equal"),
        ],
        default="lt",
        help_text="How to compare against threshold",
    )

    action_type = models.CharField(
        max_length=50,
        choices=[
            ("create_px_action", "Create PX Action"),
            ("send_notification", "Send Notification"),
            ("escalate", "Escalate"),
        ],
        help_text="Action to take when threshold is breached",
    )

    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["hospital", "threshold_type"]
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
            models.Index(fields=["threshold_type", "is_active"]),
        ]

    def __str__(self):
        return f"{self.hospital.name} - {self.threshold_type} {self.comparison_operator} {self.threshold_value}"

    def check_threshold(self, value):
        """Check if value breaches threshold"""
        if self.comparison_operator == "lt":
            return value < self.threshold_value
        elif self.comparison_operator == "lte":
            return value <= self.threshold_value
        elif self.comparison_operator == "gt":
            return value > self.threshold_value
        elif self.comparison_operator == "gte":
            return value >= self.threshold_value
        elif self.comparison_operator == "eq":
            return value == self.threshold_value
        return False


class ExplanationSLAConfig(UUIDModel, TimeStampedModel):
    """
    SLA configuration for staff explanation requests.

    Defines time limits and escalation rules for staff to submit explanations
    when a complaint is filed against them.
    """

    hospital = models.ForeignKey(
        "organizations.Hospital", on_delete=models.CASCADE, related_name="explanation_sla_configs"
    )

    # Time limits
    response_hours = models.IntegerField(default=48, help_text="Hours staff has to submit explanation")

    reminder_hours_before = models.IntegerField(default=12, help_text="Send first reminder X hours before deadline")

    second_reminder_enabled = models.BooleanField(
        default=True, help_text="Enable sending a second reminder before escalation"
    )

    second_reminder_hours_before = models.IntegerField(
        default=4, help_text="Send second reminder X hours before deadline"
    )

    # Escalation settings
    auto_escalate_enabled = models.BooleanField(
        default=True, help_text="Automatically escalate to manager if no response"
    )

    escalation_hours_overdue = models.IntegerField(
        default=0, help_text="Escalate X hours after overdue (0 = immediately)"
    )

    max_escalation_levels = models.IntegerField(default=3, help_text="Maximum levels to escalate up staff hierarchy")

    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["hospital"]
        verbose_name = "Explanation SLA Config"
        verbose_name_plural = "Explanation SLA Configs"
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
        ]

    def __str__(self):
        return f"{self.hospital.name} - {self.response_hours}h to respond"


class InquirySLAConfig(UUIDModel, TimeStampedModel):
    """
    SLA configuration for inquiries per hospital and source.

    Allows flexible SLA configuration for inquiry response times.
    """

    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="inquiry_sla_configs")

    source = models.ForeignKey(
        "px_sources.PXSource",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiry_sla_configs",
        help_text="Inquiry source (MOH, CHI, Patient, etc.). Empty = default config",
    )

    sla_hours = models.IntegerField(help_text="Number of hours until SLA deadline")

    first_reminder_hours_after = models.IntegerField(
        default=0, help_text="Send 1st reminder X hours after inquiry creation (0 = use reminder_hours_before)"
    )

    second_reminder_hours_after = models.IntegerField(
        default=0, help_text="Send 2nd reminder X hours after inquiry creation (0 = use second_reminder_hours_before)"
    )

    escalation_hours_after = models.IntegerField(
        default=0, help_text="Escalate inquiry X hours after creation if unresolved (0 = use overdue logic)"
    )

    reminder_hours_before = models.IntegerField(default=24, help_text="Send first reminder X hours before deadline")

    second_reminder_enabled = models.BooleanField(default=False, help_text="Enable sending a second reminder")

    second_reminder_hours_before = models.IntegerField(
        default=6, help_text="Send second reminder X hours before deadline"
    )

    is_active = models.BooleanField(default=True)

    # Department response SLA fields
    dept_response_hours = models.IntegerField(
        default=48, help_text="Hours for department to submit a response"
    )
    dept_response_reminder_hours_before = models.IntegerField(
        default=12, help_text="Send 1st reminder X hours before dept response deadline"
    )
    dept_response_second_reminder_enabled = models.BooleanField(
        default=True, help_text="Enable sending a second reminder for dept response"
    )
    dept_response_second_reminder_hours_before = models.IntegerField(
        default=4, help_text="Send 2nd reminder X hours before dept response deadline"
    )
    dept_response_auto_escalate_enabled = models.BooleanField(
        default=True, help_text="Auto-escalate to department manager if response overdue"
    )
    dept_response_escalation_hours_overdue = models.IntegerField(
        default=0, help_text="Escalate X hours after dept response deadline (0 = immediately)"
    )

    class Meta:
        ordering = ["hospital", "source"]
        verbose_name = "Inquiry SLA Config"
        verbose_name_plural = "Inquiry SLA Configs"
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
            models.Index(fields=["hospital", "source", "is_active"]),
        ]

    def __str__(self):
        source_display = self.source.name_en if self.source else "Default"
        return f"{self.hospital.name} - {source_display} - {self.sla_hours}h"

    def get_first_reminder_hours_after(self, inquiry_created_at=None):
        if self.first_reminder_hours_after > 0:
            return self.first_reminder_hours_after
        else:
            return max(0, self.sla_hours - self.reminder_hours_before)

    def get_second_reminder_hours_after(self, inquiry_created_at=None):
        if self.second_reminder_hours_after > 0:
            return self.second_reminder_hours_after
        elif self.second_reminder_enabled:
            return max(0, self.sla_hours - self.second_reminder_hours_before)
        else:
            return 0

    def get_escalation_hours_after(self, inquiry_created_at=None):
        if self.escalation_hours_after > 0:
            return self.escalation_hours_after
        else:
            return None


class Inquiry(UUIDModel, TimeStampedModel, SoftDeleteModel):
    """
    Inquiry model for general questions/requests.

    Similar to complaints but for non-complaint inquiries.
    """

    # Patient information
    patient = models.ForeignKey(
        "organizations.Patient", on_delete=models.CASCADE, null=True, blank=True, related_name="inquiries"
    )

    # Contact information (if patient not in system)
    contact_name = models.CharField(max_length=200, blank=True)
    contact_phone = models.CharField(max_length=20, blank=True)
    contact_email = models.EmailField(blank=True)

    # Organization
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="inquiries")
    department = models.ForeignKey(
        "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="inquiries"
    )
    location_type = models.CharField(
        max_length=20,
        choices=LocationType.choices,
        blank=True,
    )
    area = models.ForeignKey(
        "organizations.Area", on_delete=models.SET_NULL, null=True, blank=True, related_name="inquiries"
    )

    # Location - legacy fields
    legacy_location = models.ForeignKey(
        "organizations.LegacyLocation",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiries",
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_main_section = models.ForeignKey(
        "organizations.LegacyMainSection",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiries",
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_subsection = models.ForeignKey(
        "organizations.LegacySubSection",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiries",
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )

    # New hierarchy (from 4th Version Excel)
    section = models.ForeignKey(
        "organizations.Section",
        on_delete=models.PROTECT,
        related_name="inquiries",
        null=True,
        blank=True,
        help_text="Section within department",
    )

    # Legacy raw fields for mapping
    old_location_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original location Arabic text from inquiry",
    )
    old_main_section_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original main section Arabic text from inquiry",
    )
    old_subsection_raw = models.CharField(
        max_length=200,
        blank=True,
        db_index=True,
        help_text="Original subsection Arabic text from inquiry",
    )

    # Reference number
    reference_number = models.CharField(max_length=50, unique=True, blank=True)

    # Inquiry details
    subject = models.CharField(max_length=500)
    message = models.TextField()

    # Category (legacy simple choices)
    category = models.CharField(
        max_length=100,
        choices=[
            ("appointment", _("Appointment")),
            ("billing", _("Billing")),
            ("medical_records", _("Medical Records")),
            ("general", _("General Information")),
            ("other", _("Other")),
        ],
    )

    # AI Taxonomy — 4-level SHCT taxonomy (reuse ComplaintCategory hierarchy)
    taxonomy_domain = models.ForeignKey(
        "ComplaintCategory",
        on_delete=models.SET_NULL,
        related_name="inquiries_domain",
        null=True,
        blank=True,
        help_text="Level 1: Domain",
    )
    taxonomy_category = models.ForeignKey(
        "ComplaintCategory",
        on_delete=models.SET_NULL,
        related_name="inquiries_category",
        null=True,
        blank=True,
        help_text="Level 2: Category",
    )
    taxonomy_subcategory = models.ForeignKey(
        "ComplaintCategory",
        on_delete=models.SET_NULL,
        related_name="inquiries_subcategory",
        null=True,
        blank=True,
        help_text="Level 3: Subcategory",
    )
    taxonomy_classification = models.ForeignKey(
        "ComplaintCategory",
        on_delete=models.SET_NULL,
        related_name="inquiries_classification",
        null=True,
        blank=True,
        help_text="Level 4: Classification",
    )

    # Priority
    priority = models.CharField(
        max_length=20,
        choices=[
            ("low", _("Low")),
            ("medium", _("Medium")),
            ("high", _("High")),
        ],
        default="low",
        db_index=True,
    )

    # AI-generated brief summaries
    ai_brief_en = models.CharField(max_length=500, blank=True, help_text="AI-generated brief summary (English)")
    ai_brief_ar = models.CharField(max_length=500, blank=True, help_text="AI-generated brief summary (Arabic)")

    # Source
    source = models.ForeignKey(
        "px_sources.PXSource",
        on_delete=models.PROTECT,
        related_name="inquiries",
        null=True,
        blank=True,
        help_text="Source of inquiry",
    )

    # Status
    status = models.CharField(
        max_length=25,
        choices=[
            ("open", _("Open")),
            ("in_progress", _("In Progress")),
            ("resolved", _("Resolved")),
            ("closed", _("Closed")),
        ],
        default="open",
        db_index=True,
    )

    contact_status = models.CharField(
        max_length=25,
        choices=[
            ("not_contacted", _("Not Contacted")),
            ("contacted", _("Contacted")),
            ("contacted_no_response", _("Contacted - No Response")),
        ],
        default="not_contacted",
        blank=True,
        db_index=True,
    )
    contact_status_at = models.DateTimeField(null=True, blank=True)
    contact_status_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
    )

    # Creator tracking
    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_inquiries",
        help_text="User who created this inquiry (SourceUser or Patient)",
    )

    # Assignment
    assigned_to = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="assigned_inquiries"
    )
    assigned_at = models.DateTimeField(null=True, blank=True)

    # Activation tracking
    activated_at = models.DateTimeField(
        null=True,
        blank=True,
        db_index=True,
        help_text="Timestamp when inquiry was first activated (moved from OPEN to IN_PROGRESS)",
    )

    # SLA tracking
    due_at = models.DateTimeField(null=True, blank=True, db_index=True, help_text="SLA deadline")
    is_overdue = models.BooleanField(default=False, db_index=True)
    breached_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="Timestamp when inquiry first breached SLA"
    )
    reminder_sent_at = models.DateTimeField(null=True, blank=True, help_text="First SLA reminder timestamp")
    second_reminder_sent_at = models.DateTimeField(null=True, blank=True, help_text="Second SLA reminder timestamp")
    escalated_at = models.DateTimeField(null=True, blank=True)

    # Response
    response = models.TextField(blank=True)
    response_en = models.TextField(blank=True, help_text="Response text (English)")
    response_ar = models.TextField(blank=True, help_text="Response text (Arabic)")
    response_sent_at = models.DateTimeField(null=True, blank=True, help_text="When response was sent to inquirer")
    responded_at = models.DateTimeField(null=True, blank=True)
    responded_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="responded_inquiries"
    )

    # Metadata (stores AI analysis, form data, etc.)
    metadata = models.JSONField(default=dict, blank=True)

    # Workflow classification
    is_straightforward = models.BooleanField(
        default=True,
        verbose_name="Is Straightforward",
        help_text="Direct resolution (no department coordination needed)",
    )

    is_outgoing = models.BooleanField(
        default=False, verbose_name="Is Outgoing", help_text="Inquiry sent to external department for response"
    )

    transferred_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="When the inquiry was transferred to a department"
    )
    sent_to_department = models.BooleanField(
        default=False, help_text="Whether this inquiry has been sent to the primary department for visibility"
    )
    sent_to_department_at = models.DateTimeField(
        null=True, blank=True, help_text="When the inquiry was sent to the primary department"
    )
    transferred_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="transferred_inquiries",
        help_text="User who transferred the inquiry",
    )
    transferred_to_department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="transferred_inquiries",
        help_text="Department the inquiry was transferred to",
    )
    transfer_count = models.PositiveIntegerField(default=0, help_text="Number of times this inquiry has been transferred")

    outgoing_department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="outgoing_inquiries",
        help_text="Department that was contacted for this inquiry",
    )

    department_response_en = models.TextField(blank=True, verbose_name="Department Response (English)")
    department_response_ar = models.TextField(blank=True, verbose_name="Department Response (Arabic)")
    department_response_summary_en = models.TextField(blank=True, verbose_name="AI Summary of Dept Response (EN)")
    department_response_summary_ar = models.TextField(blank=True, verbose_name="AI Summary of Dept Response (AR)")
    department_responded_at = models.DateTimeField(null=True, blank=True)
    department_responded_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="department_inquiry_responses",
    )

    # Token-based department response
    response_token = models.CharField(
        max_length=100, blank=True, null=True, unique=True, db_index=True,
        help_text="One-time token for department response link",
    )
    response_token_used = models.BooleanField(default=False)
    response_token_sent_at = models.DateTimeField(null=True, blank=True)

    # Department response SLA tracking
    dept_response_sla_due_at = models.DateTimeField(
        null=True, blank=True, db_index=True,
        help_text="SLA deadline for department response",
    )
    dept_response_is_overdue = models.BooleanField(
        default=False, db_index=True,
        help_text="Department response is overdue",
    )
    dept_response_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="First SLA reminder for dept response",
    )
    dept_response_second_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="Second SLA reminder for dept response",
    )
    dept_response_escalated_at = models.DateTimeField(
        null=True, blank=True, help_text="When dept response was escalated to manager",
    )

    # Department response acceptance review
    dept_response_acceptance_status = models.CharField(
        max_length=20,
        choices=[
            ("pending", _("Pending Review")),
            ("acceptable", _("Acceptable")),
            ("not_acceptable", _("Not Acceptable")),
        ],
        default="pending",
        help_text="Review status of the department response",
    )
    dept_response_accepted_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reviewed_inquiry_dept_responses",
        help_text="User who reviewed the department response",
    )
    dept_response_accepted_at = models.DateTimeField(
        null=True, blank=True, help_text="When the department response was reviewed",
    )
    dept_response_acceptance_notes = models.TextField(
        blank=True, help_text="Notes about the acceptance decision",
    )

    # Contact tracking — matches the 3-stage timeline in the Excel reports
    # Each stage has: date, time, staff, duration

    # Stage 1: تم التواصل ولم يتم الرد (Contacted, No Response)
    contacted_nr_at = models.DateTimeField(null=True, blank=True, verbose_name="Contacted NR Date")
    contacted_nr_time = models.TimeField(null=True, blank=True, verbose_name="Contacted NR Time")
    contacted_nr_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiry_contacted_nr",
        verbose_name="Contacted NR By",
    )
    contacted_nr_duration = models.DurationField(null=True, blank=True, verbose_name="Contacted NR Duration")

    # Stage 2: تحت الإجراء (Under Process / In Progress)
    under_process_at = models.DateTimeField(null=True, blank=True, verbose_name="Under Process Date")
    under_process_time = models.TimeField(null=True, blank=True, verbose_name="Under Process Time")
    under_process_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiry_under_process",
        verbose_name="Under Process By",
    )
    under_process_duration = models.DurationField(null=True, blank=True, verbose_name="Under Process Duration")

    # Stage 3: تم التواصل (Successfully Contacted)
    contacted_at = models.DateTimeField(null=True, blank=True, verbose_name="Contacted Date")
    contacted_time = models.TimeField(null=True, blank=True, verbose_name="Contacted Time")
    contacted_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiry_contacted",
        verbose_name="Contacted By",
    )
    contacted_duration = models.DurationField(null=True, blank=True, verbose_name="Contacted Duration")

    # Timeline SLA (from the report dropdown: 24h, 48h, 72h, >72h)
    timeline_sla = models.CharField(
        max_length=50,
        choices=[
            ("24_hours", "24 Hours"),
            ("48_hours", "48 Hours"),
            ("72_hours", "72 Hours"),
            ("more_than_72_hours", "More than 72 hours"),
        ],
        blank=True,
        verbose_name="Timeline SLA",
        help_text="Response deadline category",
    )

    # Notes
    staff_notes = models.TextField(blank=True, verbose_name="Staff Notes")
    supervisor_notes = models.TextField(blank=True, verbose_name="Supervisor Notes")

    # Follow-up tracking
    requires_follow_up = models.BooleanField(
        default=False, db_index=True, help_text="This inquiry requires follow-up call"
    )

    follow_up_due_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="Due date for follow-up call to inquirer"
    )

    follow_up_completed_at = models.DateTimeField(null=True, blank=True, help_text="When follow-up call was completed")

    follow_up_completed_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="completed_inquiry_followups",
        help_text="User who completed the follow-up call",
    )

    follow_up_notes = models.TextField(blank=True, help_text="Notes from follow-up call")

    follow_up_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="When reminder was sent for follow-up"
    )

    notes = GenericRelation("core.Note")

    class Meta:
        ordering = ["-created_at"]
        verbose_name_plural = "Inquiries"
        indexes = [
            models.Index(fields=["status", "-created_at"]),
            models.Index(fields=["hospital", "status", "-created_at"]),
            models.Index(fields=["assigned_to", "status", "-created_at"]),
        ]

    def save(self, *args, **kwargs):
        if not self.reference_number:
            from apps.core.reference import generate_reference

            self.reference_number = generate_reference("INQ", self.hospital)

        if not self.due_at:
            sla_config = self.get_sla_config()
            if sla_config:
                from datetime import timedelta

                self.due_at = timezone.now() + timedelta(hours=sla_config.sla_hours)

        # Auto-populate timeline_sla from due_at if not set
        if not self.timeline_sla and self.due_at and self.created_at:
            from datetime import timedelta
            hours = (self.due_at - self.created_at).total_seconds() / 3600
            if hours <= 24:
                self.timeline_sla = "24_hours"
            elif hours <= 48:
                self.timeline_sla = "48_hours"
            elif hours <= 72:
                self.timeline_sla = "72_hours"
            else:
                self.timeline_sla = "more_than_72_hours"

        super().save(*args, **kwargs)

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

    def get_absolute_url(self):
        from django.urls import reverse

        return reverse("inquiries:inquiry_detail", kwargs={"pk": self.pk})

    def get_owner(self):
        """
        Returns the owner of this inquiry.
        Cascade: section(champion, supervisor, deputy_supervisor)
        -> department(champion, deputy_manager, supervisor,
           deputy_supervisor, manager_2nd, manager_3rd).
        Returns: Staff instance or None.
        """
        if self.section:
            for role in ("champion", "supervisor", "deputy_supervisor"):
                owner = getattr(self.section, role, None)
                if owner:
                    return owner
        if self.department:
            dept = self.department
            for role in ("champion", "deputy_manager",
                         "supervisor", "deputy_supervisor",
                         "manager_2nd", "manager_3rd"):
                owner = getattr(dept, role, None)
                if owner:
                    return owner
        return None

    @property
    def short_description_en(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("short_description_en", "")
        return ""

    @property
    def short_description_ar(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("short_description_ar", "")
        return ""

    @property
    def reasoning_en(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("reasoning_en", "")
        return ""

    @property
    def reasoning_ar(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("reasoning_ar", "")
        return ""

    @property
    def emotion(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion", "neutral")
        return "neutral"

    @property
    def emotion_intensity(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion_intensity", 0.0)
        return 0.0

    @property
    def emotion_confidence(self):
        if self.metadata and "ai_analysis" in self.metadata:
            return self.metadata["ai_analysis"].get("emotion_confidence", 0.0)
        return 0.0

    @property
    def emotion_confidence_percent(self):
        return self.emotion_confidence * 100

    @property
    def emotion_intensity_percent(self):
        return self.emotion_intensity * 100

    @property
    def get_emotion_display(self):
        emotion_map = {
            "anger": "Anger",
            "sadness": "Sadness",
            "confusion": "Confusion",
            "fear": "Fear",
            "neutral": "Neutral",
        }
        return emotion_map.get(self.emotion, "Neutral")

    @property
    def get_emotion_badge_class(self):
        badge_map = {
            "anger": "danger",
            "sadness": "primary",
            "confusion": "warning",
            "fear": "info",
            "neutral": "secondary",
        }
        return badge_map.get(self.emotion, "secondary")

    @property
    def is_active_status(self):
        """
        Check if inquiry is in an active status (can be worked on).
        Active statuses: open, in_progress
        Inactive statuses: resolved, closed
        """
        return self.status in ["open", "in_progress"]

    def get_sla_config(self):
        """Get SLA configuration for this inquiry based on hospital and source."""
        try:
            if self.source:
                config = InquirySLAConfig.objects.filter(
                    hospital=self.hospital,
                    source=self.source,
                    is_active=True,
                ).first()
                if config:
                    return config

            config = InquirySLAConfig.objects.filter(
                hospital=self.hospital,
                is_active=True,
            ).first()
            if config:
                return config

        except Exception:
            pass

        return None

    def check_overdue(self):
        """Check if inquiry is overdue and update status"""
        if self.status in ["closed", "cancelled"]:
            return False

        if self.due_at and timezone.now() > self.due_at:
            if not self.is_overdue:
                self.is_overdue = True
                self.breached_at = timezone.now()
                self.save(update_fields=["is_overdue", "breached_at"])
            return True
        return False


class InquiryUpdate(UUIDModel, TimeStampedModel):
    """
    Inquiry update/timeline entry.

    Tracks all updates, status changes, and communications for inquiries.
    """

    inquiry = models.ForeignKey(Inquiry, on_delete=models.CASCADE, related_name="updates")

    # Update details
    update_type = models.CharField(
        max_length=50,
        choices=[
            ("status_change", _("Status Change")),
            ("assignment", _("Assignment")),
            ("note", _("Note")),
            ("response", _("Response")),
            ("communication", _("Communication")),
            ("department_response", _("Department Response")),
            ("sent_to_department", _("Sent to Department")),
            ("transferred_to_department", _("Transferred to Department")),
        ],
        db_index=True,
    )

    message = models.TextField()

    # User who made the update
    created_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="inquiry_updates"
    )

    # Status change tracking
    old_status = models.CharField(max_length=25, blank=True)
    new_status = models.CharField(max_length=25, blank=True)

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

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["inquiry", "-created_at"]),
        ]

    def __str__(self):
        return f"{self.inquiry} - {self.update_type} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"


class InquiryAttachment(UUIDModel, TimeStampedModel):
    """Inquiry attachment (images, documents, etc.)"""

    inquiry = models.ForeignKey(Inquiry, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(upload_to="inquiries/%Y/%m/%d/")
    filename = models.CharField(max_length=500)
    file_type = models.CharField(max_length=100, blank=True)
    file_size = models.IntegerField(help_text="File size in bytes")

    uploaded_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="inquiry_attachments"
    )

    description = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.inquiry} - {self.filename}"


class ComplaintExplanation(UUIDModel, TimeStampedModel):
    """
    Staff/recipient explanation about a complaint.

    Allows staff members to submit their perspective via token-based link.
    Each staff member can submit one explanation per complaint.
    Includes SLA tracking for explanation submission deadlines.
    """

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="explanations")

    staff = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="complaint_explanations",
        help_text="Staff member who submitted the explanation",
    )

    explanation = models.TextField(help_text="Staff's explanation about the complaint")

    token = models.CharField(max_length=64, unique=True, help_text="Unique access token for explanation submission")

    is_used = models.BooleanField(
        default=False, db_index=True, help_text="Token expiry tracking - becomes True after submission"
    )

    submitted_via = models.CharField(
        max_length=20,
        choices=[
            ("email_link", _("Email Link")),
            ("direct", _("Direct Entry")),
        ],
        default="email_link",
        help_text="How the explanation was submitted",
    )

    email_sent_at = models.DateTimeField(null=True, blank=True, help_text="When the explanation request email was sent")

    responded_at = models.DateTimeField(null=True, blank=True, help_text="When the explanation was submitted")

    # Request details
    requested_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="requested_complaint_explanations",
        help_text="User who requested the explanation",
    )

    request_message = models.TextField(blank=True, help_text="Optional message sent with the explanation request")

    # SLA tracking for explanation requests
    sla_due_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="SLA deadline for staff to submit explanation"
    )

    is_overdue = models.BooleanField(default=False, db_index=True, help_text="Explanation request is overdue")

    reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="First reminder sent to staff about overdue explanation"
    )

    second_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="Second reminder sent to staff about overdue explanation"
    )

    escalated_to_manager = models.ForeignKey(
        "self",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="escalated_from_staff",
        help_text="Escalated to this explanation (manager's explanation request)",
    )

    escalated_at = models.DateTimeField(null=True, blank=True, help_text="When explanation was escalated to manager")

    # Acceptance review fields
    class AcceptanceStatus(models.TextChoices):
        PENDING = "pending", _("Pending Review")
        ACCEPTABLE = "acceptable", _("Acceptable")
        NOT_ACCEPTABLE = "not_acceptable", _("Not Acceptable")

    acceptance_status = models.CharField(
        max_length=20,
        choices=AcceptanceStatus.choices,
        default=AcceptanceStatus.PENDING,
        help_text="Review status of the explanation",
    )

    accepted_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reviewed_explanations",
        help_text="User who reviewed and marked the explanation",
    )

    accepted_at = models.DateTimeField(null=True, blank=True, help_text="When the explanation was reviewed")

    acceptance_notes = models.TextField(blank=True, help_text="Notes about the acceptance decision")

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "Complaint Explanation"
        verbose_name_plural = "Complaint Explanations"
        indexes = [
            models.Index(fields=["complaint", "-created_at"]),
            models.Index(fields=["token", "is_used"]),
        ]

    def __str__(self):
        staff_name = str(self.staff) if self.staff else "Unknown"
        return f"{self.complaint} - {staff_name} - {'Submitted' if self.is_used else 'Pending'}"

    @property
    def can_submit(self):
        """Check if explanation can still be submitted"""
        return not self.is_used

    @property
    def attachment_count(self):
        """Count of explanation attachments"""
        return self.attachments.count()

    @property
    def linked_involved_department(self):
        """Find the linked ComplaintInvolvedDepartment for this explanation."""
        if not self.staff or not self.staff.department:
            return None
        return ComplaintInvolvedDepartment.objects.filter(
            complaint=self.complaint,
            department=self.staff.department,
            sent=True,
        ).first()

    def get_token(self):
        """Return the access token"""
        return self.token


class ExplanationAttachment(UUIDModel, TimeStampedModel):
    """Attachment for complaint explanation"""

    explanation = models.ForeignKey(ComplaintExplanation, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(upload_to="explanation_attachments/%Y/%m/%d/")
    filename = models.CharField(max_length=500)
    file_type = models.CharField(max_length=100, blank=True)
    file_size = models.IntegerField(help_text="File size in bytes")

    description = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "Explanation Attachment"
        verbose_name_plural = "Explanation Attachments"

    def __str__(self):
        return f"{self.explanation} - {self.filename}"


class InquiryExplanation(UUIDModel, TimeStampedModel):
    """
    Staff/recipient response to an inquiry via token-based link.

    Mirrors ComplaintExplanation pattern. Each staff member gets a unique
    token link to submit their response without logging in.
    """

    inquiry = models.ForeignKey(Inquiry, on_delete=models.CASCADE, related_name="explanations")

    staff = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="inquiry_explanations",
        help_text="Staff member who submitted the response",
    )

    explanation = models.TextField(blank=True, help_text="Staff's response to the inquiry")

    token = models.CharField(max_length=64, unique=True, help_text="Unique access token for response submission")

    is_used = models.BooleanField(
        default=False, db_index=True, help_text="Token expiry tracking - becomes True after submission"
    )

    submitted_via = models.CharField(
        max_length=20,
        choices=[
            ("email_link", _("Email Link")),
            ("direct", _("Direct Entry")),
        ],
        default="email_link",
    )

    email_sent_at = models.DateTimeField(null=True, blank=True, help_text="When the response request email was sent")

    responded_at = models.DateTimeField(null=True, blank=True, help_text="When the response was submitted")

    requested_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="requested_inquiry_explanations",
        help_text="User who requested the response",
    )

    request_message = models.TextField(blank=True, help_text="Optional message sent with the response request")

    # SLA tracking
    sla_due_at = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="SLA deadline for staff to submit response"
    )

    is_overdue = models.BooleanField(default=False, db_index=True)

    reminder_sent_at = models.DateTimeField(null=True, blank=True)
    second_reminder_sent_at = models.DateTimeField(null=True, blank=True)
    escalated_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "Inquiry Explanation"
        verbose_name_plural = "Inquiry Explanations"
        indexes = [
            models.Index(fields=["inquiry", "-created_at"]),
            models.Index(fields=["token", "is_used"]),
        ]

    def __str__(self):
        staff_name = str(self.staff) if self.staff else "Unknown"
        return f"{self.inquiry} - {staff_name} - {'Submitted' if self.is_used else 'Pending'}"

    @property
    def can_submit(self):
        return not self.is_used


class InquiryExplanationAttachment(UUIDModel, TimeStampedModel):
    """Attachment for inquiry explanation"""

    explanation = models.ForeignKey(InquiryExplanation, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(upload_to="inquiry_explanation_attachments/%Y/%m/%d/")
    filename = models.CharField(max_length=500)
    file_type = models.CharField(max_length=100, blank=True)
    file_size = models.IntegerField(help_text="File size in bytes")
    description = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "Inquiry Explanation Attachment"
        verbose_name_plural = "Inquiry Explanation Attachments"

    def __str__(self):
        return f"{self.explanation} - {self.filename}"


class ComplaintPRInteraction(UUIDModel, TimeStampedModel):
    """
    PR (Patient Relations) contact with complainant.

    Tracks when PR staff contact the complainant to take a formal statement
    and explain the complaint procedure.
    """

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="pr_interactions")

    contact_date = models.DateTimeField(help_text="Date and time of PR contact with complainant")

    contact_method = models.CharField(
        max_length=20,
        choices=[
            ("phone", _("Phone")),
            ("in_person", _("In Person")),
            ("email", _("Email")),
            ("other", _("Other")),
        ],
        default="in_person",
        help_text="Method of contact",
    )

    pr_staff = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="pr_interactions",
        help_text="PR staff member who made the contact",
    )

    statement_text = models.TextField(blank=True, help_text="Formal statement taken from the complainant")

    procedure_explained = models.BooleanField(
        default=False, help_text="Whether complaint procedure was explained to the complainant"
    )

    notes = models.TextField(blank=True, help_text="Additional notes from the PR interaction")

    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_pr_interactions",
        help_text="User who created this PR interaction record",
    )

    class Meta:
        ordering = ["-contact_date"]
        verbose_name = "PR Interaction"
        verbose_name_plural = "PR Interactions"
        indexes = [
            models.Index(fields=["complaint", "-contact_date"]),
        ]

    def __str__(self):
        method_display = self.get_contact_method_display()
        return f"{self.complaint} - {method_display} - {self.contact_date.strftime('%Y-%m-%d')}"


class ComplaintMeeting(UUIDModel, TimeStampedModel):
    """
    Meeting record for management intervention.

    Simple record of meetings scheduled/agreed upon between management
    and the complainant to resolve complaints.
    """

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="meetings")

    meeting_date = models.DateTimeField(help_text="Date and time of the meeting")

    meeting_type = models.CharField(
        max_length=50,
        choices=[
            ("management_intervention", _("Management Intervention")),
            ("pr_follow_up", _("PR Follow-up")),
            ("department_review", _("Department Review")),
            ("other", _("Other")),
        ],
        default="management_intervention",
        help_text="Type of meeting",
    )

    outcome = models.TextField(blank=True, help_text="Meeting outcome and agreed resolution")

    notes = models.TextField(blank=True, help_text="Additional meeting notes")

    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_meetings",
        help_text="User who created this meeting record",
    )

    class Meta:
        ordering = ["-meeting_date"]
        verbose_name = "Complaint Meeting"
        verbose_name_plural = "Complaint Meetings"
        indexes = [
            models.Index(fields=["complaint", "-meeting_date"]),
        ]

    def __str__(self):
        type_display = self.get_meeting_type_display()
        return f"{self.complaint} - {type_display} - {self.meeting_date.strftime('%Y-%m-%d')}"


class ComplaintInvolvedDepartment(UUIDModel, TimeStampedModel):
    """
    Tracks departments involved in a complaint.

    Allows multiple departments to be associated with a single complaint
    with specific roles (primary, secondary/supporting, coordination).
    """

    class RoleChoices(models.TextChoices):
        PRIMARY = "primary", _("Primary Department")
        SECONDARY = "secondary", _("Secondary/Supporting")
        COORDINATION = "coordination", _("Coordination Only")
        INVESTIGATING = "investigating", _("Investigating")

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="involved_departments")

    department = models.ForeignKey(
        "organizations.Department", on_delete=models.CASCADE, related_name="complaint_involvements"
    )

    role = models.CharField(
        max_length=20,
        choices=RoleChoices.choices,
        default=RoleChoices.SECONDARY,
        help_text="Role of this department in the complaint resolution",
    )

    is_primary = models.BooleanField(default=False, help_text="Mark as the primary responsible department")

    added_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="added_department_involvements"
    )

    notes = models.TextField(blank=True, help_text="Additional notes about this department's involvement")

    # Assignment within this department
    assigned_to = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="department_assigned_complaints",
        help_text="User assigned from this department to handle the complaint",
    )

    assigned_at = models.DateTimeField(null=True, blank=True)

    # Response tracking
    response_submitted = models.BooleanField(
        default=False, help_text="Whether this department has submitted their response"
    )

    response_submitted_at = models.DateTimeField(null=True, blank=True)

    response_notes = models.TextField(blank=True, help_text="Department's response/feedback on the complaint")

    response_notes_en = models.TextField(blank=True, verbose_name="Response (English)")
    response_notes_ar = models.TextField(blank=True, verbose_name="Response (Arabic)")

    # Acceptance review
    acceptance_status = models.CharField(
        max_length=20,
        choices=[
            ("pending", _("Pending Review")),
            ("acceptable", _("Acceptable")),
            ("not_acceptable", _("Not Acceptable")),
        ],
        default="pending",
        help_text="Review status of the department response",
    )
    accepted_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reviewed_complaint_dept_responses",
        help_text="User who reviewed the department response",
    )
    accepted_at = models.DateTimeField(null=True, blank=True, help_text="When the department response was reviewed")
    acceptance_notes = models.TextField(blank=True, help_text="Notes about the acceptance decision")

    # Reminder and delay tracking (Step 1 fields)
    forwarded_at = models.DateTimeField(null=True, blank=True, help_text="When complaint was sent to this department")
    sent = models.BooleanField(default=False, help_text="Whether this department has been sent the complaint")
    sent_at = models.DateTimeField(null=True, blank=True, help_text="When the complaint was sent to this department")
    first_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="When first reminder was sent to this department"
    )
    second_reminder_sent_at = models.DateTimeField(
        null=True, blank=True, help_text="When second reminder was sent to this department"
    )
    delay_reason = models.TextField(blank=True, help_text="Reason for department delay in response")
    delayed_person = models.CharField(max_length=200, blank=True, help_text="Name of person responsible for delay")

    manager_review_status = models.CharField(
        max_length=20,
        choices=[
            ("pending", _("Pending Manager Review")),
            ("approved", _("Manager Approved")),
            ("rejected", _("Manager Rejected")),
        ],
        null=True,
        blank=True,
        default="pending",
        help_text="Department manager review status of the champion response",
    )
    manager_reviewed_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="manager_reviewed_dept_responses",
        help_text="Department manager who reviewed the champion response",
    )
    manager_reviewed_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ["-is_primary", "-created_at"]
        verbose_name = "Complaint Involved Department"
        verbose_name_plural = "Complaint Involved Departments"
        unique_together = [["complaint", "department"]]
        indexes = [
            models.Index(fields=["complaint", "role"]),
            models.Index(fields=["department", "response_submitted"]),
            models.Index(fields=["department", "forwarded_at"]),
            models.Index(fields=["department", "acceptance_status"]),
        ]

    def __str__(self):
        role_display = self.get_role_display()
        primary_flag = " [PRIMARY]" if self.is_primary else ""
        return f"{self.complaint.reference_number} - {self.department.name} ({role_display}){primary_flag}"

    def save(self, *args, **kwargs):
        """Ensure only one primary department per complaint"""
        if self.is_primary:
            # Clear primary flag from other departments for this complaint
            ComplaintInvolvedDepartment.objects.filter(complaint=self.complaint, is_primary=True).exclude(
                pk=self.pk
            ).update(is_primary=False)
        super().save(*args, **kwargs)

    @property
    def sla_remaining(self):
        """Hours remaining for this department to respond (based on ExplanationSLAConfig)."""
        if self.response_submitted or not self.sent_at:
            return None
        from apps.complaints.tasks import get_explanation_sla_config
        sla_config = get_explanation_sla_config(self.complaint.hospital)
        sla_hours = sla_config.response_hours if sla_config else 48
        due_at = self.sent_at + timedelta(hours=sla_hours)
        remaining = due_at - timezone.now()
        if remaining.total_seconds() <= 0:
            return timedelta(0)
        return remaining


class ComplaintInvolvedStaff(UUIDModel, TimeStampedModel):
    """
    Tracks staff members involved in a complaint.

    Allows multiple staff to be associated with a single complaint
    with specific roles (accused, witness, responsible, etc.).
    """

    class RoleChoices(models.TextChoices):
        ACCUSED = "accused", _("Accused/Involved")
        WITNESS = "witness", _("Witness")
        RESPONSIBLE = "responsible", _("Responsible for Resolution")
        INVESTIGATOR = "investigator", _("Investigator")
        SUPPORT = "support", _("Support Staff")
        PX_MANAGEMENT = "px_management", _("PX Management")

    complaint = models.ForeignKey(Complaint, on_delete=models.CASCADE, related_name="involved_staff")

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

    role = models.CharField(
        max_length=20,
        choices=RoleChoices.choices,
        default=RoleChoices.ACCUSED,
        help_text="Role of this staff member in the complaint",
    )

    added_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="added_staff_involvements"
    )

    notes = models.TextField(blank=True, help_text="Additional notes about this staff member's involvement")

    # Explanation tracking
    explanation_requested = models.BooleanField(
        default=False, help_text="Whether an explanation has been requested from this staff"
    )

    explanation_requested_at = models.DateTimeField(null=True, blank=True)

    explanation_received = models.BooleanField(default=False, help_text="Whether an explanation has been received")

    explanation_received_at = models.DateTimeField(null=True, blank=True)

    explanation = models.TextField(blank=True, help_text="The staff member's explanation")

    class Meta:
        ordering = ["role", "-created_at"]
        verbose_name = "Complaint Involved Staff"
        verbose_name_plural = "Complaint Involved Staff"
        unique_together = [["complaint", "staff"]]
        indexes = [
            models.Index(fields=["complaint", "role"]),
            models.Index(fields=["staff", "explanation_received"]),
        ]

    def __str__(self):
        role_display = self.get_role_display()
        return f"{self.complaint.reference_number} - {self.staff} ({role_display})"


class OnCallAdminSchedule(UUIDModel, TimeStampedModel):
    """
    On-call admin schedule configuration for complaint notifications.

    Manages which PX Admins should be notified outside of working hours.
    During working hours, ALL PX Admins are notified.
    Outside working hours, only ON-CALL admins are notified.
    """

    # Working days configuration (stored as list of day numbers: 0=Monday, 6=Sunday)
    working_days = models.JSONField(
        default=list, help_text="List of working days (0=Monday, 6=Sunday). Default: [0,1,2,3,4] (Mon-Fri)"
    )

    # Working hours
    work_start_time = models.TimeField(default="08:00", help_text="Start of working hours (e.g., 08:00)")
    work_end_time = models.TimeField(default="17:00", help_text="End of working hours (e.g., 17:00)")

    # Timezone for the schedule
    timezone = models.CharField(
        max_length=50, default="Asia/Riyadh", help_text="Timezone for working hours calculation (e.g., Asia/Riyadh)"
    )

    # Whether this config is active
    is_active = models.BooleanField(default=True, help_text="Whether this on-call schedule is active")

    # Hospital scope (null = system-wide)
    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="on_call_schedules",
        help_text="Hospital scope. Leave empty for system-wide configuration.",
    )

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "On-Call Admin Schedule"
        verbose_name_plural = "On-Call Admin Schedules"
        constraints = [
            models.UniqueConstraint(
                fields=["hospital"], condition=models.Q(hospital__isnull=False), name="unique_oncall_per_hospital"
            ),
            models.UniqueConstraint(
                fields=["hospital"], condition=models.Q(hospital__isnull=True), name="unique_system_wide_oncall"
            ),
        ]

    def __str__(self):
        scope = f"{self.hospital.name}" if self.hospital else "System-wide"
        start_time = (
            self.work_start_time.strftime("%H:%M")
            if hasattr(self.work_start_time, "strftime")
            else str(self.work_start_time)[:5]
        )
        end_time = (
            self.work_end_time.strftime("%H:%M")
            if hasattr(self.work_end_time, "strftime")
            else str(self.work_end_time)[:5]
        )
        return f"On-Call Schedule - {scope} ({start_time}-{end_time})"

    def get_working_days_list(self):
        """Get list of working days, with default if empty"""
        if self.working_days:
            return self.working_days
        return [0, 1, 2, 3, 4]  # Default: Monday-Friday

    def is_working_time(self, check_datetime=None):
        """
        Check if the given datetime is within working hours.

        Args:
            check_datetime: datetime to check (default: now)

        Returns:
            bool: True if within working hours, False otherwise
        """
        from datetime import time as datetime_time
        from zoneinfo import ZoneInfo

        if check_datetime is None:
            check_datetime = timezone.now()

        tz = ZoneInfo(self.timezone)
        if timezone.is_aware(check_datetime):
            local_time = check_datetime.astimezone(tz)
        else:
            local_time = check_datetime.replace(tzinfo=tz)

        # Check if it's a working day
        working_days = self.get_working_days_list()
        if local_time.weekday() not in working_days:
            return False

        # Check if it's within working hours
        current_time = local_time.time()

        # Ensure work_start_time and work_end_time are time objects
        start_time = self.work_start_time
        end_time = self.work_end_time

        # Convert string to time if needed (handles string defaults from DB)
        if isinstance(start_time, str):
            parts = start_time.split(":")
            hours, minutes = int(parts[0]), int(parts[1])
            start_time = datetime_time(hours, minutes)

        if isinstance(end_time, str):
            parts = end_time.split(":")
            hours, minutes = int(parts[0]), int(parts[1])
            end_time = datetime_time(hours, minutes)

        return start_time <= current_time < end_time


class OnCallAdmin(UUIDModel, TimeStampedModel):
    """
    Individual on-call admin assignment.

    Links PX Admin users to an on-call schedule.
    """

    schedule = models.ForeignKey(OnCallAdminSchedule, on_delete=models.CASCADE, related_name="on_call_admins")

    admin_user = models.ForeignKey(
        "accounts.User",
        on_delete=models.CASCADE,
        related_name="on_call_schedules",
        help_text="User who is on-call (PX Admin, PX Coordinator, or Hospital Admin)",
    )

    # Optional: date range for this on-call assignment
    start_date = models.DateField(null=True, blank=True, help_text="Start date for this on-call assignment (optional)")

    end_date = models.DateField(null=True, blank=True, help_text="End date for this on-call assignment (optional)")

    # Priority/order for notifications (lower = higher priority)
    notification_priority = models.PositiveIntegerField(default=1, help_text="Priority for notifications (1 = highest)")

    is_active = models.BooleanField(default=True, help_text="Whether this on-call assignment is currently active")

    # Contact preferences for out-of-hours
    notify_email = models.BooleanField(default=True, help_text="Send email notifications")
    notify_sms = models.BooleanField(default=False, help_text="Send SMS notifications")

    # Custom phone for SMS (optional, uses user's phone if not set)
    sms_phone = models.CharField(
        max_length=20, blank=True, help_text="Custom phone number for SMS notifications (optional)"
    )

    class Meta:
        ordering = ["notification_priority", "-created_at"]
        verbose_name = "On-Call Admin"
        verbose_name_plural = "On-Call Admins"
        unique_together = [["schedule", "admin_user"]]

    def __str__(self):
        return f"{self.admin_user.get_full_name() or self.admin_user.email} - On-Call ({self.schedule})"

    def is_currently_active(self, check_date=None):
        """
        Check if this on-call assignment is active for the given date.

        Args:
            check_date: date to check (default: today)

        Returns:
            bool: True if active, False otherwise
        """
        if not self.is_active:
            return False

        if check_date is None:
            check_date = timezone.now().date()

        # Check date range
        if self.start_date and check_date < self.start_date:
            return False
        if self.end_date and check_date > self.end_date:
            return False

        return True

    def get_notification_phone(self):
        """Get phone number for SMS notifications"""
        if self.sms_phone:
            return self.sms_phone
        if hasattr(self.admin_user, "phone") and self.admin_user.phone:
            return self.admin_user.phone
        return None


class ComplaintAdverseAction(UUIDModel, TimeStampedModel):
    """
    Tracks adverse actions or damages to patients related to complaints.

    This model helps identify and address retaliation or negative treatment
    that patients may experience after filing a complaint.

    Examples:
    - Doctor refusing to see the patient in subsequent visits
    - Delayed or denied treatment
    - Verbal abuse or hostile behavior
    - Increased wait times
    - Unnecessary procedures
    - Dismissal from care
    """

    class ActionType(models.TextChoices):
        """Types of adverse actions"""

        REFUSED_SERVICE = "refused_service", _("Refused Service")
        DELAYED_TREATMENT = "delayed_treatment", _("Delayed Treatment")
        VERBAL_ABUSE = "verbal_abuse", _("Verbal Abuse / Hostility")
        INCREASED_WAIT = "increased_wait", _("Increased Wait Time")
        UNNECESSARY_PROCEDURE = "unnecessary_procedure", _("Unnecessary Procedure")
        DISMISSED_FROM_CARE = "dismissed_from_care", _("Dismissed from Care")
        POOR_TREATMENT = "poor_treatment", _("Poor Treatment Quality")
        DISCRIMINATION = "discrimination", _("Discrimination")
        RETALIATION = "retaliation", _("Retaliation")
        OTHER = "other", _("Other")

    class SeverityLevel(models.TextChoices):
        """Severity levels for adverse actions"""

        LOW = "low", _("Low - Minor inconvenience")
        MEDIUM = "medium", _("Medium - Moderate impact")
        HIGH = "high", _("High - Significant harm")
        CRITICAL = "critical", _("Critical - Severe harm / Life-threatening")

    class VerificationStatus(models.TextChoices):
        """Verification status of the adverse action report"""

        REPORTED = "reported", _("Reported - Awaiting Review")
        UNDER_INVESTIGATION = "under_investigation", _("Under Investigation")
        VERIFIED = "verified", _("Verified")
        UNFOUNDED = "unfounded", _("Unfounded")
        RESOLVED = "resolved", _("Resolved")

    # Link to complaint
    complaint = models.ForeignKey(
        Complaint,
        on_delete=models.CASCADE,
        related_name="adverse_actions",
        help_text=_("The complaint this adverse action is related to"),
    )

    # Action details
    action_type = models.CharField(
        max_length=30, choices=ActionType.choices, default=ActionType.OTHER, help_text=_("Type of adverse action")
    )

    severity = models.CharField(
        max_length=10,
        choices=SeverityLevel.choices,
        default=SeverityLevel.MEDIUM,
        help_text=_("Severity level of the adverse action"),
    )

    description = models.TextField(help_text=_("Detailed description of what happened to the patient"))

    # When it occurred
    incident_date = models.DateTimeField(help_text=_("Date and time when the adverse action occurred"))

    # Location/Context
    location = models.CharField(
        max_length=200, blank=True, help_text=_("Location where the incident occurred (e.g., Emergency Room, Clinic B)")
    )

    # Staff involved
    involved_staff = models.ManyToManyField(
        "organizations.Staff",
        blank=True,
        related_name="adverse_actions_involved",
        help_text=_("Staff members involved in the adverse action"),
    )

    # Impact on patient
    patient_impact = models.TextField(
        blank=True, help_text=_("Description of the impact on the patient (physical, emotional, financial)")
    )

    # Verification and handling
    status = models.CharField(
        max_length=30,
        choices=VerificationStatus.choices,
        default=VerificationStatus.REPORTED,
        help_text=_("Current status of the adverse action report"),
    )

    reported_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reported_adverse_actions",
        help_text=_("User who reported this adverse action"),
    )

    # Investigation
    investigation_notes = models.TextField(blank=True, help_text=_("Notes from the investigation"))

    investigated_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="investigated_adverse_actions",
        help_text=_("User who investigated this adverse action"),
    )

    investigated_at = models.DateTimeField(null=True, blank=True, help_text=_("When the investigation was completed"))

    # Resolution
    resolution = models.TextField(blank=True, help_text=_("How the adverse action was resolved"))

    resolved_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="resolved_adverse_actions",
        help_text=_("User who resolved this adverse action"),
    )

    resolved_at = models.DateTimeField(null=True, blank=True, help_text=_("When the adverse action was resolved"))

    # Metadata
    is_escalated = models.BooleanField(
        default=False, help_text=_("Whether this adverse action has been escalated to management")
    )

    escalated_at = models.DateTimeField(null=True, blank=True, help_text=_("When the adverse action was escalated"))

    class Meta:
        ordering = ["-incident_date", "-created_at"]
        verbose_name = _("Complaint Adverse Action")
        verbose_name_plural = _("Complaint Adverse Actions")
        indexes = [
            models.Index(fields=["complaint", "-incident_date"]),
            models.Index(fields=["action_type", "severity"]),
            models.Index(fields=["status", "-created_at"]),
        ]

    def __str__(self):
        return f"{self.complaint.reference_number} - {self.get_action_type_display()} ({self.get_severity_display()})"

    @property
    def is_high_severity(self):
        """Check if this is a high or critical severity adverse action"""
        return self.severity in [self.SeverityLevel.HIGH, self.SeverityLevel.CRITICAL]

    @property
    def days_since_incident(self):
        """Calculate days since the incident occurred"""
        from django.utils import timezone

        if self.incident_date:
            return (timezone.now() - self.incident_date).days
        return None

    @property
    def requires_investigation(self):
        """Check if this adverse action requires investigation"""
        return self.status in [self.VerificationStatus.REPORTED, self.VerificationStatus.UNDER_INVESTIGATION]


class ComplaintAdverseActionAttachment(UUIDModel, TimeStampedModel):
    """
    Attachments for adverse action reports (evidence, documents, etc.)
    """

    adverse_action = models.ForeignKey(ComplaintAdverseAction, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(
        upload_to="complaints/adverse_actions/%Y/%m/%d/",
        help_text=_("Attachment file (image, document, audio recording, etc.)"),
    )

    filename = models.CharField(max_length=255)
    file_type = models.CharField(max_length=100, blank=True)
    file_size = models.IntegerField(help_text=_("File size in bytes"))

    description = models.TextField(blank=True, help_text=_("Description of what this attachment shows"))

    uploaded_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, related_name="adverse_action_attachments"
    )

    class Meta:
        ordering = ["-created_at"]
        verbose_name = _("Adverse Action Attachment")
        verbose_name_plural = _("Adverse Action Attachments")

    def __str__(self):
        return f"{self.adverse_action.reference_number} - {self.filename}"


# ============================================================================
# COMPLAINT TEMPLATES
# ============================================================================


class ComplaintTemplate(UUIDModel, TimeStampedModel):
    """
    Pre-defined templates for common complaints.

    Allows quick selection of common complaint types with pre-filled
    description, category, severity, and auto-assignment.
    """

    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        related_name="complaint_templates",
        help_text=_("Hospital this template belongs to"),
    )

    name = models.CharField(max_length=200, help_text=_("Template name (e.g., 'Long Wait Time', 'Rude Staff')"))
    description = models.TextField(help_text=_("Default description template with placeholders"))

    # Pre-set classification
    category = models.ForeignKey(
        ComplaintCategory,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="templates",
        help_text=_("Default category for this template"),
    )

    # Default severity/priority
    default_severity = models.CharField(
        max_length=20,
        choices=SeverityChoices.choices,
        default=SeverityChoices.MEDIUM,
        help_text=_("Default severity level"),
    )
    default_priority = models.CharField(
        max_length=20,
        choices=PriorityChoices.choices,
        default=PriorityChoices.MEDIUM,
        help_text=_("Default priority level"),
    )

    # Auto-assignment
    auto_assign_department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="template_assignments",
        help_text=_("Auto-assign to this department when template is used"),
    )

    # Usage tracking
    usage_count = models.IntegerField(
        default=0, editable=False, help_text=_("Number of times this template has been used")
    )

    # Placeholders that can be used in description
    # e.g., "Patient waited for {{wait_time}} minutes"
    placeholders = models.JSONField(
        default=list, blank=True, help_text=_("List of placeholder names used in description")
    )

    is_active = models.BooleanField(
        default=True, db_index=True, help_text=_("Whether this template is available for selection")
    )

    class Meta:
        ordering = ["-usage_count", "name"]
        verbose_name = _("Complaint Template")
        verbose_name_plural = _("Complaint Templates")
        unique_together = [["hospital", "name"]]
        indexes = [
            models.Index(fields=["hospital", "is_active"]),
            models.Index(fields=["-usage_count"]),
        ]

    def __str__(self):
        return f"{self.hospital.name} - {self.name} ({self.usage_count} uses)"

    def use_template(self):
        """Increment usage count"""
        self.usage_count += 1
        self.save(update_fields=["usage_count"])

    def render_description(self, placeholder_values):
        """
        Render description with placeholder values.

        Args:
            placeholder_values: Dict of placeholder name -> value

        Returns:
            Rendered description string
        """
        description = self.description
        for key, value in placeholder_values.items():
            description = description.replace(f"{{{{{key}}}}}", str(value))
        return description


# ============================================================================
# COMMUNICATION LOG
# ============================================================================


class ComplaintCommunicationType(models.TextChoices):
    """Types of communication"""

    PHONE_CALL = "phone_call", _("Phone Call")
    EMAIL = "email", _("Email")
    SMS = "sms", _("SMS")
    MEETING = "meeting", _("Meeting")
    LETTER = "letter", _("Letter")
    OTHER = "other", _("Other")


class ComplaintCommunication(UUIDModel, TimeStampedModel):
    """
    Tracks all communications related to a complaint.

    Records phone calls, emails, meetings, and other communications
    with complainants, involved staff, or other stakeholders.
    """

    complaint = models.ForeignKey(
        Complaint, on_delete=models.CASCADE, related_name="communications", help_text=_("Related complaint")
    )

    # Communication details
    communication_type = models.CharField(
        max_length=20, choices=ComplaintCommunicationType.choices, help_text=_("Type of communication")
    )

    direction = models.CharField(
        max_length=20,
        choices=[
            ("inbound", _("Inbound")),
            ("outbound", _("Outbound")),
        ],
        help_text="Direction of communication",
    )

    # Participants
    contacted_person = models.CharField(max_length=200, help_text=_("Name of person contacted"))
    contacted_role = models.CharField(
        max_length=100, blank=True, help_text=_("Role/relation (e.g., Complainant, Patient, Staff)")
    )
    contacted_phone = models.CharField(max_length=20, blank=True, help_text=_("Phone number"))
    contacted_email = models.EmailField(blank=True, help_text=_("Email address"))

    # Communication content
    subject = models.CharField(max_length=500, blank=True, help_text=_("Subject/summary of communication"))
    notes = models.TextField(help_text=_("Details of what was discussed"))

    # Follow-up
    requires_followup = models.BooleanField(default=False, help_text=_("Whether this communication requires follow-up"))
    followup_date = models.DateField(null=True, blank=True, help_text=_("Date when follow-up is needed"))
    followup_notes = models.TextField(blank=True, help_text=_("Notes from follow-up"))

    # Attachments (emails, letters, etc.)
    attachment = models.FileField(
        upload_to="complaints/communications/%Y/%m/%d/",
        null=True,
        blank=True,
        help_text=_("Attached document (email export, letter, etc.)"),
    )

    # Created by
    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        related_name="complaint_communications",
        help_text=_("User who logged this communication"),
    )

    class Meta:
        ordering = ["-created_at"]
        verbose_name = _("Complaint Communication")
        verbose_name_plural = _("Complaint Communications")
        indexes = [
            models.Index(fields=["complaint", "-created_at"]),
            models.Index(fields=["communication_type"]),
            models.Index(fields=["requires_followup", "followup_date"]),
        ]

    def __str__(self):
        return f"{self.complaint.reference_number} - {self.get_communication_type_display()} - {self.contacted_person}"


class PatientComplaintSession(TimeStampedModel):
    """
    Token-based session for patients to submit complaints via SMS link.

    Flow:
    1. Staff creates session -> SMS sent to patient with link
    2. Patient opens link -> sees hospital cards grouped by visits
    3. Patient selects hospital -> sees visit list
    4. Patient selects visit -> fills complaint form
    """

    patient = models.ForeignKey("organizations.Patient", on_delete=models.CASCADE, related_name="complaint_sessions")
    token = models.CharField(max_length=64, unique=True)
    expires_at = models.DateTimeField(db_index=True)
    created_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="complaint_sessions"
    )
    is_active = models.BooleanField(default=True, db_index=True)

    def is_expired(self):
        from django.utils import timezone

        return timezone.now() > self.expires_at

    def generate_link(self, request=None):
        if request:
            return request.build_absolute_uri(f"/complaints/patient/{self.token}/")
        return f"/complaints/patient/{self.token}/"

    def save(self, *args, **kwargs):
        if not self.token:
            import secrets

            self.token = secrets.token_urlsafe(32)
        if not self.expires_at:
            from django.utils import timezone
            from django.conf import settings

            days = getattr(settings, "COMPLAINT_LINK_EXPIRY_DAYS", 7)
            self.expires_at = timezone.now() + timedelta(days=days)
        super().save(*args, **kwargs)

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["patient", "is_active"]),
        ]


class GovernmentTicket(UUIDModel, TimeStampedModel):
    """Tickets from government sources (MOH, CHI, etc.)"""

    class TicketStatus(models.TextChoices):
        PENDING = "pending", _("Pending")
        IN_PROGRESS = "in_progress", _("In Progress")
        RESOLVED = "resolved", _("Resolved")
        CLOSED = "closed", _("Closed")

    # Source (MOH or CCHI)
    source = models.ForeignKey(
        "px_sources.PXSource",
        on_delete=models.PROTECT,
        limit_choices_to={"source_type": "government", "is_active": True},
        related_name="government_tickets",
        help_text=_("Government source (MOH, CCHI, etc.)"),
    )

    # Ticket Info
    ticket_number = models.CharField(
        max_length=50, unique=True, db_index=True, help_text=_("Ticket number from source system (e.g., B2022807)")
    )
    status = models.CharField(
        max_length=20, choices=TicketStatus.choices, default=TicketStatus.PENDING, db_index=True
    )

    # Complainant Info
    complainant_name = models.CharField(max_length=200)
    national_id = models.CharField(max_length=20, blank=True)
    contact_number = models.CharField(max_length=20, blank=True)

    # Location hierarchy - legacy fields
    legacy_location = models.ForeignKey(
        "organizations.LegacyLocation",
        on_delete=models.PROTECT,
        related_name="government_tickets",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_main_section = models.ForeignKey(
        "organizations.LegacyMainSection",
        on_delete=models.PROTECT,
        related_name="government_tickets",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )
    legacy_subsection = models.ForeignKey(
        "organizations.LegacySubSection",
        on_delete=models.PROTECT,
        related_name="government_tickets",
        null=True,
        blank=True,
        help_text="[DEPRECATED] Use 'department' and 'section' fields instead. This field is read-only and will be removed in a future release.",
    )

    # Department (new hierarchy)
    department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.PROTECT,
        related_name="government_tickets",
        null=True,
        blank=True,
        help_text="Department",
    )

    # New hierarchy
    section = models.ForeignKey(
        "organizations.Section",
        on_delete=models.PROTECT,
        related_name="government_tickets",
        null=True,
        blank=True,
        help_text="Section within department",
    )

    # Legacy raw fields
    old_location_raw = models.CharField(max_length=200, blank=True, db_index=True)
    old_main_section_raw = models.CharField(max_length=200, blank=True, db_index=True)
    old_subsection_raw = models.CharField(max_length=200, blank=True, db_index=True)

    # Dates
    received_date = models.DateTimeField(help_text=_("Date/time the ticket was received from source"))

    # Content
    classification = models.CharField(max_length=100, blank=True)
    content = models.TextField()

    # Conversion tracking
    converted_to_complaint = models.BooleanField(default=False, db_index=True)
    complaint = models.OneToOneField(
        "complaints.Complaint",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="government_ticket",
    )

    # Assignment
    assigned_to = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="assigned_government_tickets",
    )

    class Meta:
        ordering = ["-received_date"]
        verbose_name = _("Government Ticket")
        verbose_name_plural = _("Government Tickets")

    def __str__(self):
        return f"{self.ticket_number} - {self.complainant_name}"


class ManagerReviewQuestionType(models.TextChoices):
    TEXT = "text", _("Short Text")
    TEXTAREA = "textarea", _("Long Text")
    YES_NO = "yes_no", _("Yes / No")
    RATING = "rating", _("Rating (1-5)")
    MULTIPLE_CHOICE = "multiple_choice", _("Multiple Choice")


class ManagerReviewQuestion(UUIDModel, TimeStampedModel):
    """
    Configurable questions that PX-Admin creates per hospital.
    Shown to the Department Manager when reviewing a champion's response.
    """

    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        related_name="manager_review_questions",
    )
    text_en = models.TextField(verbose_name="Question Text (English)")
    text_ar = models.TextField(blank=True, verbose_name="Question Text (Arabic)")
    question_type = models.CharField(
        max_length=20,
        choices=ManagerReviewQuestionType.choices,
        default=ManagerReviewQuestionType.TEXTAREA,
    )
    choices_json = models.JSONField(
        blank=True,
        default=list,
        help_text='List of choices for multiple_choice type, e.g. ["Option A","Option B"]',
    )
    order = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)
    created_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_manager_review_questions",
    )

    class Meta:
        ordering = ["order", "created_at"]
        verbose_name = "Manager Review Question"
        verbose_name_plural = "Manager Review Questions"

    def __str__(self):
        return self.text_en[:80]

    def get_localized_text(self):
        from django.utils.translation import get_language
        if get_language() == "ar" and self.text_ar:
            return self.text_ar
        return self.text_en


class DepartmentManagerReview(UUIDModel, TimeStampedModel):
    """
    Records the Department Manager's review of a champion's response.
    One review per involved-department response cycle.
    """

    involved_department = models.ForeignKey(
        ComplaintInvolvedDepartment,
        on_delete=models.CASCADE,
        related_name="manager_reviews",
    )
    reviewed_by = models.ForeignKey(
        "accounts.User",
        on_delete=models.SET_NULL,
        null=True,
        related_name="dept_manager_reviews",
    )
    status = models.CharField(
        max_length=20,
        choices=[
            ("approved", _("Approved")),
            ("rejected", _("Rejected")),
        ],
    )
    reviewed_at = models.DateTimeField(auto_now_add=True)
    rejection_reason = models.TextField(blank=True)

    class Meta:
        ordering = ["-reviewed_at"]
        verbose_name = "Department Manager Review"
        verbose_name_plural = "Department Manager Reviews"

    def __str__(self):
        return f"ManagerReview({self.involved_department}, {self.status})"


class ManagerReviewAnswer(UUIDModel, TimeStampedModel):
    """
    Individual answer to a ManagerReviewQuestion within a DepartmentManagerReview.
    """

    review = models.ForeignKey(
        DepartmentManagerReview,
        on_delete=models.CASCADE,
        related_name="answers",
    )
    question = models.ForeignKey(
        ManagerReviewQuestion,
        on_delete=models.CASCADE,
        related_name="answers",
    )
    text_value = models.TextField(blank=True)
    numeric_value = models.IntegerField(null=True, blank=True)

    class Meta:
        verbose_name = "Manager Review Answer"
        verbose_name_plural = "Manager Review Answers"

    def __str__(self):
        return f"Answer({self.question.text_en[:40]}): {self.text_value[:40]}"


class InvestigationStatus(models.TextChoices):
    QUESTIONS_SENT = "questions_sent", "Questions Sent"
    ANSWERS_RECEIVED = "answers_received", "Answers Received"
    REPLY_SUBMITTED = "reply_submitted", "Reply Submitted"


class ChampionInvestigation(UUIDModel, TimeStampedModel):
    complaint = models.ForeignKey(
        Complaint,
        on_delete=models.CASCADE,
        related_name="investigations",
    )
    champion = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="champion_investigations",
    )
    involved_department = models.ForeignKey(
        "ComplaintInvolvedDepartment",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="investigations",
    )
    explanation = models.ForeignKey(
        "ComplaintExplanation",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="investigation",
    )
    status = models.CharField(
        max_length=20,
        choices=InvestigationStatus.choices,
        default=InvestigationStatus.QUESTIONS_SENT,
    )
    final_reply = models.TextField(blank=True)

    class Meta:
        verbose_name = "Champion Investigation"
        verbose_name_plural = "Champion Investigations"
        ordering = ["-created_at"]

    def __str__(self):
        return f"Investigation({self.complaint.reference_number}) - {self.status}"

    @property
    def all_responses_received(self):
        return self.responses.exists() and not self.responses.filter(is_completed=False).exists()


class InvestigationQuestion(UUIDModel, TimeStampedModel):
    investigation = models.ForeignKey(
        ChampionInvestigation,
        on_delete=models.CASCADE,
        related_name="questions",
    )
    question_text = models.TextField()
    order = models.PositiveIntegerField(default=0)

    class Meta:
        verbose_name = "Investigation Question"
        verbose_name_plural = "Investigation Questions"
        ordering = ["order", "created_at"]

    def __str__(self):
        return f"Q{self.order}: {self.question_text[:80]}"


class InvestigationResponse(UUIDModel, TimeStampedModel):
    investigation = models.ForeignKey(
        ChampionInvestigation,
        on_delete=models.CASCADE,
        related_name="responses",
    )
    staff = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.CASCADE,
        related_name="investigation_responses",
    )
    token = models.CharField(max_length=64, unique=True, db_index=True)
    is_completed = models.BooleanField(default=False)
    completed_at = models.DateTimeField(null=True, blank=True)
    email_sent_at = models.DateTimeField(null=True, blank=True)
    sms_sent_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        verbose_name = "Investigation Response"
        verbose_name_plural = "Investigation Responses"

    def __str__(self):
        return f"Response({self.staff.get_full_name()}) - {'Done' if self.is_completed else 'Pending'}"


class InvestigationAnswer(UUIDModel, TimeStampedModel):
    response = models.ForeignKey(
        InvestigationResponse,
        on_delete=models.CASCADE,
        related_name="answers",
    )
    question = models.ForeignKey(
        InvestigationQuestion,
        on_delete=models.CASCADE,
        related_name="answers",
    )
    answer_text = models.TextField(blank=True)

    class Meta:
        verbose_name = "Investigation Answer"
        verbose_name_plural = "Investigation Answers"
        unique_together = [("response", "question")]

    def __str__(self):
        return f"A: {self.answer_text[:80]}"
