"""
Feedback models - Patient feedback and suggestions management

This module implements the feedback management system that:
- Tracks patient feedback (compliments, suggestions, general feedback)
- Manages feedback workflow (submitted → reviewed → acknowledged → closed)
- Maintains feedback responses and timeline
- Supports attachments and ratings
"""

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.models import PriorityChoices, SoftDeleteModel, TimeStampedModel, UUIDModel


class FeedbackType(models.TextChoices):
    """Feedback type choices"""

    COMPLIMENT = "compliment", _("Compliment")
    SUGGESTION = "suggestion", _("Suggestion")
    GENERAL = "general", _("General Feedback")
    INQUIRY = "inquiry", _("Inquiry")
    SATISFACTION_CHECK = "satisfaction_check", _("Satisfaction Check")


class FeedbackStatus(models.TextChoices):
    """Feedback status choices"""

    SUBMITTED = "submitted", _("Submitted")
    REVIEWED = "reviewed", _("Reviewed")
    ACKNOWLEDGED = "acknowledged", _("Acknowledged")
    CLOSED = "closed", _("Closed")
    REOPENED = "reopened", _("Reopened")


VALID_FEEDBACK_TRANSITIONS = {
    FeedbackStatus.SUBMITTED: [FeedbackStatus.REVIEWED, FeedbackStatus.CLOSED],
    FeedbackStatus.REVIEWED: [FeedbackStatus.ACKNOWLEDGED, FeedbackStatus.CLOSED],
    FeedbackStatus.ACKNOWLEDGED: [FeedbackStatus.CLOSED],
    FeedbackStatus.CLOSED: [FeedbackStatus.REOPENED],
    FeedbackStatus.REOPENED: [FeedbackStatus.REVIEWED, FeedbackStatus.ACKNOWLEDGED, FeedbackStatus.CLOSED],
}


class FeedbackCategory(models.TextChoices):
    """Feedback category choices"""

    CLINICAL_CARE = "clinical_care", _("Clinical Care")
    STAFF_SERVICE = "staff_service", _("Staff Service")
    FACILITY = "facility", _("Facility & Environment")
    COMMUNICATION = "communication", _("Communication")
    APPOINTMENT = "appointment", _("Appointment & Scheduling")
    BILLING = "billing", _("Billing & Insurance")
    FOOD_SERVICE = "food_service", _("Food Service")
    CLEANLINESS = "cleanliness", _("Cleanliness")
    TECHNOLOGY = "technology", _("Technology & Systems")
    OTHER = "other", _("Other")


class SentimentChoices(models.TextChoices):
    """Sentiment analysis choices"""

    POSITIVE = "positive", _("Positive")
    NEUTRAL = "neutral", _("Neutral")
    NEGATIVE = "negative", _("Negative")


class Feedback(UUIDModel, TimeStampedModel, SoftDeleteModel):
    """
    Feedback model for patient feedback, compliments, and suggestions.

    Workflow:
    1. SUBMITTED - Feedback received
    2. REVIEWED - Being reviewed by staff
    3. ACKNOWLEDGED - Response provided
    4. CLOSED - Feedback closed
    """

    # Patient and encounter information
    patient = models.ForeignKey(
        "organizations.Patient",
        on_delete=models.CASCADE,
        related_name="feedbacks",
        null=True,
        blank=True,
        help_text="Patient who provided feedback (optional for anonymous feedback)",
    )

    # Anonymous feedback support
    is_anonymous = models.BooleanField(default=False)
    contact_name = models.CharField(max_length=200, blank=True)
    contact_email = models.EmailField(blank=True)
    contact_phone = models.CharField(max_length=20, blank=True)

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

    # Survey linkage (for satisfaction checks after negative surveys)
    related_survey = models.ForeignKey(
        "surveys.SurveyInstance",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="follow_up_feedbacks",
        help_text="Survey that triggered this satisfaction check feedback",
    )

    # Organization
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="feedbacks")
    legacy_location = models.ForeignKey(
        "organizations.LegacyLocation",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="feedbacks",
        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="feedbacks",
        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="feedbacks",
        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.SET_NULL,
        null=True,
        blank=True,
        related_name="feedbacks_new",
        help_text="Section within department",
    )
    department = models.ForeignKey(
        "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="feedbacks"
    )
    staff = models.ForeignKey(
        "organizations.Staff",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="feedbacks",
        help_text="Staff member being mentioned in feedback",
    )

    # Feedback details
    feedback_type = models.CharField(
        max_length=20, choices=FeedbackType.choices, default=FeedbackType.GENERAL, db_index=True
    )

    title = models.CharField(max_length=500)
    message = models.TextField(help_text="Feedback message")

    # Reference number (unified format SGT-YYYYMM-HOSP-NNNN; internal-only, not publicly trackable)
    reference_number = models.CharField(max_length=40, unique=True, blank=True, null=True, db_index=True)

    # Classification
    category = models.CharField(max_length=50, choices=FeedbackCategory.choices, db_index=True)
    subcategory = models.CharField(max_length=100, blank=True)

    # Rating (1-5 stars)
    rating = models.IntegerField(null=True, blank=True, help_text="Rating from 1 to 5 stars")

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

    # Sentiment analysis
    sentiment = models.CharField(
        max_length=20,
        choices=SentimentChoices.choices,
        default=SentimentChoices.NEUTRAL,
        db_index=True,
        help_text="Sentiment analysis result",
    )
    sentiment_score = models.FloatField(
        null=True, blank=True, help_text="Sentiment score from -1 (negative) to 1 (positive)"
    )

    # Status and workflow
    status = models.CharField(
        max_length=20, choices=FeedbackStatus.choices, default=FeedbackStatus.SUBMITTED, db_index=True
    )

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

    # Review tracking
    reviewed_at = models.DateTimeField(null=True, blank=True)
    reviewed_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="reviewed_feedbacks"
    )

    # Acknowledgment
    acknowledged_at = models.DateTimeField(null=True, blank=True)
    acknowledged_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="acknowledged_feedbacks"
    )

    # 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_feedbacks"
    )

    # Flags
    is_featured = models.BooleanField(default=False, help_text="Feature this feedback (e.g., for testimonials)")
    is_public = models.BooleanField(default=False, help_text="Make this feedback public")
    requires_follow_up = models.BooleanField(default=False)

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

    # 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=["department", "status", "-created_at"]),
            models.Index(fields=["assigned_to", "status", "-created_at"]),
            models.Index(fields=["feedback_type", "-created_at"]),
            models.Index(fields=["is_deleted", "-created_at"]),
        ]
        verbose_name_plural = "Feedback"

    def __str__(self):
        if self.patient:
            return f"{self.title} - {self.patient.get_full_name()} ({self.feedback_type})"
        return f"{self.title} - Anonymous ({self.feedback_type})"

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

            self.reference_number = generate_reference("SGT", self.hospital)
        super().save(*args, **kwargs)

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

        return reverse("feedback:feedback_detail", kwargs={"pk": self.pk})

    @property
    def has_ai_analysis(self):
        return bool(self.metadata and self.metadata.get("ai_analysis"))

    @property
    def ai_analysis(self):
        return self.metadata.get("ai_analysis", {}) if self.metadata else {}

    @property
    def ai_short_description_en(self):
        return self.ai_analysis.get("short_description_en", "")

    @property
    def ai_short_description_ar(self):
        return self.ai_analysis.get("short_description_ar", "")

    @property
    def ai_suggested_actions(self):
        return self.ai_analysis.get("suggested_actions", [])

    @property
    def ai_suggested_action_en(self):
        return self.ai_analysis.get("suggested_action_en", "")

    @property
    def ai_suggested_action_ar(self):
        return self.ai_analysis.get("suggested_action_ar", "")

    @property
    def ai_priority(self):
        return self.ai_analysis.get("priority", "")

    @property
    def ai_category(self):
        return self.ai_analysis.get("category", "")

    @property
    def ai_reasoning_en(self):
        return self.ai_analysis.get("reasoning_en", "")

    @property
    def ai_reasoning_ar(self):
        return self.ai_analysis.get("reasoning_ar", "")

    def get_contact_name(self):
        """Get contact name (patient or anonymous)"""
        if self.patient:
            return self.patient.get_full_name()
        return self.contact_name or "Anonymous"


class FeedbackAttachment(UUIDModel, TimeStampedModel):
    """Feedback attachment (images, documents, etc.)"""

    feedback = models.ForeignKey(Feedback, on_delete=models.CASCADE, related_name="attachments")

    file = models.FileField(upload_to="feedback/%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, blank=True, related_name="feedback_attachments"
    )

    description = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]

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


class FeedbackResponse(UUIDModel, TimeStampedModel):
    """
    Feedback response/timeline entry.

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

    feedback = models.ForeignKey(Feedback, on_delete=models.CASCADE, related_name="responses")

    # Response details
    response_type = models.CharField(
        max_length=50,
        choices=[
            ("status_change", "Status Change"),
            ("assignment", "Assignment"),
            ("note", "Internal Note"),
            ("response", "Response to Patient"),
            ("acknowledgment", "Acknowledgment"),
        ],
        db_index=True,
    )

    message = models.TextField()

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

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

    # Visibility
    is_internal = models.BooleanField(default=False, help_text="Internal note (not visible to patient)")

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

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

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


class CommentSourceCategory(models.TextChoices):
    """Source category from IT department data export (Step 0)"""

    APPOINTMENT = "appointment", _("Appointment")
    INPATIENT = "inpatient", _("Inpatient")
    OUTPATIENT = "outpatient", _("Outpatient")


class CommentClassification(models.TextChoices):
    """Comment classification categories (Step 1 — Colors sheet)"""

    HOSPITAL = "hospital", _("Hospital")
    MEDICAL = "medical", _("Medical")
    NON_MEDICAL = "non_medical", _("Non-Medical")
    NURSING = "nursing", _("Nursing")
    ER = "er", _("Emergency")
    SUPPORT_SERVICES = "support_services", _("Support Services")


class CommentSubCategory(models.TextChoices):
    """Comment sub-categories (Step 1 — Colors sheet dropdown)"""

    PHARMACY = "pharmacy", _("Pharmacy")
    RAD = "rad", _("RAD")
    LAB = "lab", _("LAB")
    PHYSIOTHERAPY = "physiotherapy", _("Physiotherapy")
    DOCTORS = "doctors", _("Doctors")
    MEDICAL_REPORTS = "medical_reports", _("Medical Reports")
    RECEPTION = "reception", _("Reception")
    INSURANCE_APPROVALS = "insurance_approvals", _("Insurance/Approvals")
    OPD_CLINICS = "opd_clinics", _("OPD - Clinics")
    APPOINTMENTS = "appointments", _("Appointments")
    IT_APP = "it_app", _("IT - App")
    ADMINISTRATION = "administration", _("Administration")
    BILLING = "billing", _("Billing")
    FACILITIES = "facilities", _("Facilities")
    FOOD_SERVICES = "food_services", _("Food Services")
    PARKING = "parking", _("Parking")
    HOUSEKEEPING = "housekeeping", _("Housekeeping")
    OTHER = "other", _("Other")


COMMENT_SUB_CATEGORY_MAP = {
    CommentClassification.MEDICAL: [
        CommentSubCategory.PHARMACY,
        CommentSubCategory.RAD,
        CommentSubCategory.LAB,
        CommentSubCategory.PHYSIOTHERAPY,
        CommentSubCategory.DOCTORS,
        CommentSubCategory.MEDICAL_REPORTS,
    ],
    CommentClassification.NON_MEDICAL: [
        CommentSubCategory.RECEPTION,
        CommentSubCategory.INSURANCE_APPROVALS,
        CommentSubCategory.OPD_CLINICS,
        CommentSubCategory.APPOINTMENTS,
        CommentSubCategory.IT_APP,
        CommentSubCategory.ADMINISTRATION,
        CommentSubCategory.BILLING,
    ],
    CommentClassification.NURSING: [],
    CommentClassification.ER: [
        CommentSubCategory.DOCTORS,
        CommentSubCategory.RECEPTION,
    ],
    CommentClassification.SUPPORT_SERVICES: [
        CommentSubCategory.FACILITIES,
        CommentSubCategory.FOOD_SERVICES,
        CommentSubCategory.PARKING,
        CommentSubCategory.HOUSEKEEPING,
    ],
    CommentClassification.HOSPITAL: [],
}


class CommentImport(UUIDModel, TimeStampedModel):
    """
    Tracks IT department comment data imports (Step 0).

    Each import represents a monthly batch of raw patient comments
    exported from the IT system.
    """

    IMPORT_STATUS_CHOICES = [
        ("pending", _("Pending")),
        ("processing", _("Processing")),
        ("completed", _("Completed")),
        ("failed", _("Failed")),
    ]

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

    month = models.IntegerField(help_text="Month number (1-12)")
    year = models.IntegerField(help_text="Year")

    source_file = models.FileField(
        upload_to="comments/imports/%Y/%m/",
        blank=True,
        help_text="Uploaded source file from IT department",
    )

    status = models.CharField(max_length=20, choices=IMPORT_STATUS_CHOICES, default="pending")

    total_rows = models.IntegerField(default=0, help_text="Total rows in the import file")
    imported_count = models.IntegerField(default=0, help_text="Number of comments successfully imported")
    error_count = models.IntegerField(default=0)
    error_log = models.TextField(blank=True)

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

    class Meta:
        ordering = ["-year", "-month"]
        unique_together = [["hospital", "year", "month"]]
        verbose_name = "Comment Import"
        verbose_name_plural = "Comment Imports"

    def __str__(self):
        return f"{self.hospital} - {self.year}-{self.month:02d} ({self.imported_count} comments)"


class PatientComment(UUIDModel, TimeStampedModel):
    """
    Patient comment from IT department data export.

    Workflow (Steps 0-5):
    - Step 0: Raw import from IT (source_category, comment_text)
    - Step 1: Classification (classification, sub_category, sentiment keywords)
    - Step 2: Department filtering (grouped by department for review)
    - Step 3: Action plan creation (linked action plans)
    - Step 5: Action plan tracking (status, timeframe, evidence)

    One comment can have multiple classifications (multi-category).
    Use PatientCommentClassification for multi-category support.
    """

    comment_import = models.ForeignKey(
        CommentImport,
        on_delete=models.CASCADE,
        related_name="comments",
        null=True,
        blank=True,
        help_text="Import batch this comment came from",
    )

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

    serial_number = models.IntegerField(null=True, blank=True, help_text="Serial number from the source file")

    source_category = models.CharField(
        max_length=20,
        choices=CommentSourceCategory.choices,
        blank=True,
        db_index=True,
        help_text="Source category from IT export (Appointment/Inpatient/Outpatient)",
    )

    comment_text = models.TextField(help_text="Original comment text (Arabic/English)")

    comment_text_en = models.TextField(blank=True, help_text="English translation of the comment")

    classification = models.CharField(
        max_length=20,
        choices=CommentClassification.choices,
        blank=True,
        db_index=True,
        help_text="Primary classification (Hospital/Medical/Non-Medical/Nursing/ER/Support)",
    )

    sub_category = models.CharField(
        max_length=30,
        choices=CommentSubCategory.choices,
        blank=True,
        db_index=True,
        help_text="Sub-category classification (e.g., Pharmacy, Reception, etc.)",
    )

    negative_keywords = models.TextField(blank=True, help_text="Negative sentiment keywords/phrases extracted")

    positive_keywords = models.TextField(blank=True, help_text="Positive sentiment keywords/phrases extracted")

    gratitude_keywords = models.TextField(blank=True, help_text="Gratitude keywords/phrases extracted")

    suggestions = models.TextField(blank=True, help_text="Suggestion text extracted from the comment")

    sentiment = models.CharField(
        max_length=20,
        choices=SentimentChoices.choices,
        blank=True,
        db_index=True,
        help_text="Overall sentiment classification",
    )

    is_classified = models.BooleanField(
        default=False,
        db_index=True,
        help_text="Whether this comment has been classified",
    )

    mentioned_doctor_name = models.CharField(
        max_length=200,
        blank=True,
        help_text="Name of doctor mentioned in the comment",
    )

    mentioned_doctor_name_en = models.CharField(
        max_length=200,
        blank=True,
        help_text="English name of mentioned doctor",
    )

    frequency = models.IntegerField(
        default=1,
        help_text="How many times this comment/problem has been reported",
    )

    month = models.IntegerField(null=True, blank=True, help_text="Month the comment was collected")

    year = models.IntegerField(null=True, blank=True, help_text="Year the comment was collected")

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

    class Meta:
        ordering = ["-year", "-month", "-serial_number"]
        indexes = [
            models.Index(fields=["hospital", "classification", "sub_category"]),
            models.Index(fields=["hospital", "year", "month"]),
            models.Index(fields=["hospital", "source_category"]),
        ]
        verbose_name = "Patient Comment"
        verbose_name_plural = "Patient Comments"

    def __str__(self):
        text = self.comment_text[:50] if self.comment_text else "No text"
        return f"#{self.serial_number or '—'} {text}"


class CommentActionPlanStatus(models.TextChoices):
    COMPLETED = "completed", _("Completed")
    ON_PROCESS = "on_process", _("On Process")
    PENDING = "pending", _("Pending")


class CommentActionPlan(UUIDModel, TimeStampedModel):
    """
    Action plan derived from classified patient comments (Step 3/5).

    Tracks recommendations/action plans with responsible departments,
    timeframes, and completion status.
    """

    comment = models.ForeignKey(
        PatientComment,
        on_delete=models.CASCADE,
        related_name="action_plans",
        null=True,
        blank=True,
        help_text="Source comment (may be null if aggregated from multiple)",
    )

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

    department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="comment_action_plans",
        help_text="Responsible department",
    )

    department_label = models.CharField(
        max_length=200,
        blank=True,
        help_text="Free-text department name (for when no FK exists)",
    )

    problem_number = models.IntegerField(null=True, blank=True, help_text="Problem number within the department")

    comment_text = models.TextField(blank=True, help_text="Related comment text")
    comment_text_en = models.TextField(blank=True, help_text="English translation of the comment")

    frequency = models.IntegerField(default=1, help_text="Number of times this problem was reported")

    recommendation = models.TextField(help_text="Recommendation / Action Plan")

    recommendation_en = models.TextField(blank=True, help_text="English translation of the recommendation")

    responsible_department = models.CharField(
        max_length=200,
        blank=True,
        help_text="Free-text responsible department name",
    )

    status = models.CharField(
        max_length=20,
        choices=CommentActionPlanStatus.choices,
        default=CommentActionPlanStatus.PENDING,
        db_index=True,
    )

    timeframe = models.CharField(
        max_length=100,
        blank=True,
        help_text="Target timeframe (e.g., Q3, 3 months, 2025-Q1)",
    )

    evidences = models.TextField(blank=True, help_text="Evidence of completion / notes")

    month = models.IntegerField(null=True, blank=True)
    year = models.IntegerField(null=True, blank=True)

    class Meta:
        ordering = ["department_label", "problem_number"]
        indexes = [
            models.Index(fields=["hospital", "status"]),
            models.Index(fields=["hospital", "year", "month"]),
        ]
        verbose_name = "Comment Action Plan"
        verbose_name_plural = "Comment Action Plans"

    def __str__(self):
        dept = self.department_label or (self.department.name if self.department else "—")
        return f"{dept} - Problem #{self.problem_number or '—'} ({self.get_status_display()})"
