"""
Appreciation models - Send and track appreciation to users and physicians

This module implements the appreciation system that:
- Allows sending appreciation messages to users and physicians
- Tracks appreciation statistics and leaderboards
- Manages appreciation categories and badges
- Integrates with the notification system
"""

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models

from apps.core.models import SoftDeleteModel, TimeStampedModel, UUIDModel


class AppreciationStatus(models.TextChoices):
    """Appreciation status choices"""

    DRAFT = "draft", "Draft"
    ACTIVATED = "activated", "Activated"
    AI_ANALYZED = "ai_analyzed", "AI Analyzed"
    SENT = "sent", "Sent"
    ACKNOWLEDGED = "acknowledged", "Acknowledged"


VALID_APPRECIATION_TRANSITIONS = {
    AppreciationStatus.DRAFT: {AppreciationStatus.ACTIVATED},
    AppreciationStatus.ACTIVATED: {AppreciationStatus.AI_ANALYZED, AppreciationStatus.SENT},
    AppreciationStatus.AI_ANALYZED: {AppreciationStatus.SENT},
    AppreciationStatus.SENT: {AppreciationStatus.ACKNOWLEDGED},
    AppreciationStatus.ACKNOWLEDGED: set(),
}


class AppreciationVisibility(models.TextChoices):
    """Appreciation visibility choices"""

    PRIVATE = "private", "Private"
    DEPARTMENT = "department", "Department"
    HOSPITAL = "hospital", "Hospital"
    PUBLIC = "public", "Public"


class AppreciationCategory(UUIDModel, TimeStampedModel):
    """
    Appreciation category with bilingual support.

    Pre-defined categories for sending appreciation (e.g., "Excellent Care", "Team Player").
    Can be hospital-specific or system-wide.
    """

    # Organization
    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        related_name="appreciation_categories",
        null=True,
        blank=True,
        help_text="Leave blank for system-wide categories",
    )

    # Category details
    code = models.CharField(max_length=50, 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)

    # Visual elements
    icon = models.CharField(max_length=50, blank=True, help_text="Icon class (e.g., 'fa-heart', 'fa-star')")
    color = models.CharField(max_length=7, blank=True, help_text="Hex color code (e.g., '#FF5733')")

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

    # Status
    is_active = models.BooleanField(default=True)

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

    def __str__(self):
        hospital_name = self.hospital.name if self.hospital else "System-wide"
        return f"{hospital_name} - {self.name_en}"

    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

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

        if get_language() == "ar" and self.description_ar:
            return self.description_ar
        return self.description_en


class Appreciation(UUIDModel, TimeStampedModel, SoftDeleteModel):
    """
    Appreciation model for sending appreciation to users and physicians.

    Workflow:
    1. DRAFT - Created but not yet sent
    2. SENT - Sent to recipient (triggers notification)
    3. ACKNOWLEDGED - Recipient has acknowledged/thanked sender

    Visibility:
    - PRIVATE - Only sender and recipient can view
    - DEPARTMENT - Visible to department members
    - HOSPITAL - Visible to all hospital staff
    - PUBLIC - Can be displayed publicly (e.g., on appreciation wall)
    """

    # Sender
    sender = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="sent_appreciations"
    )

    # Recipient (Generic FK to User or Physician)
    recipient_content_type = models.ForeignKey(
        ContentType, on_delete=models.SET_NULL, null=True, blank=True, related_name="appreciation_recipients"
    )
    recipient_object_id = models.UUIDField(null=True, blank=True)
    recipient = GenericForeignKey("recipient_content_type", "recipient_object_id")

    # Organization context
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="appreciations")
    legacy_location = models.ForeignKey(
        "organizations.LegacyLocation",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="appreciations",
        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="appreciations",
        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="appreciations",
        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="appreciations_new",
        help_text="Section within department",
    )
    department = models.ForeignKey(
        "organizations.Department",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="appreciations",
        help_text="Department context (if applicable)",
    )

    # Category and message
    category = models.ForeignKey(
        AppreciationCategory, on_delete=models.SET_NULL, null=True, blank=True, related_name="appreciations"
    )
    message_en = models.TextField()
    message_ar = models.TextField(blank=True)

    # Visibility and status
    visibility = models.CharField(
        max_length=20, choices=AppreciationVisibility.choices, default=AppreciationVisibility.PRIVATE, db_index=True
    )
    status = models.CharField(
        max_length=20, choices=AppreciationStatus.choices, default=AppreciationStatus.DRAFT, db_index=True
    )

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

    # Anonymous option
    is_anonymous = models.BooleanField(default=False, help_text="Hide sender identity from recipient")

    # Timestamps
    activated_at = models.DateTimeField(null=True, blank=True)
    activated_by = models.ForeignKey(
        "accounts.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="activated_appreciations"
    )
    ai_analyzed_at = models.DateTimeField(null=True, blank=True)
    sent_at = models.DateTimeField(null=True, blank=True)
    acknowledged_at = models.DateTimeField(null=True, blank=True)

    # Send options
    send_to_manager = models.BooleanField(default=False, help_text="Send notification to department manager")
    send_to_department = models.BooleanField(default=True, help_text="Send notification to department")
    cc_list = models.JSONField(default=list, blank=True, help_text="List of user IDs to CC")
    custom_message = models.TextField(blank=True, help_text="Custom message to include when sending")
    ai_analysis = models.JSONField(default=dict, blank=True, help_text="AI analysis results")

    # Notification tracking
    notification_sent = models.BooleanField(default=False)
    notification_sent_at = models.DateTimeField(null=True, blank=True)

    # 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"]),
            models.Index(fields=["department", "-created_at"]),
            models.Index(fields=["sender", "-created_at"]),
            models.Index(fields=["recipient_content_type", "recipient_object_id", "-created_at"]),
            models.Index(fields=["visibility", "-created_at"]),
        ]

    def __str__(self):
        recipient_name = self.get_recipient_name()
        return f"Appreciation to {recipient_name} ({self.status})"

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

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

    def get_owner(self):
        """
        Returns the owner of this appreciation.
        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_localized_message(self):
        from django.utils.translation import get_language

        if get_language() == "ar" and self.message_ar:
            return self.message_ar
        return self.message_en

    def get_recipient_name(self):
        """Get recipient's name"""
        try:
            return str(self.recipient)
        except Exception:
            return "Unknown"

    def get_recipient_email(self):
        """Get recipient's email"""
        try:
            if hasattr(self.recipient, "email"):
                return self.recipient.email
            elif hasattr(self.recipient, "user"):
                return self.recipient.user.email
        except Exception:
            pass
        return None

    def get_recipient_phone(self):
        """Get recipient's phone"""
        try:
            if hasattr(self.recipient, "phone"):
                return self.recipient.phone
            elif hasattr(self.recipient, "user"):
                return self.recipient.user.phone
        except Exception:
            pass
        return None

    def activate(self, activated_by=None):
        from django.utils import timezone

        if self.status != AppreciationStatus.DRAFT:
            raise ValueError(f"Cannot activate appreciation in '{self.status}' status. Must be in 'draft'.")

        self.status = AppreciationStatus.ACTIVATED
        self.activated_at = timezone.now()
        self.activated_by = activated_by
        self.save(update_fields=["status", "activated_at", "activated_by"])

    def mark_ai_analyzed(self, analysis_data):
        from django.utils import timezone

        if self.status != AppreciationStatus.ACTIVATED:
            raise ValueError(f"Cannot mark as AI analyzed from '{self.status}' status. Must be in 'activated'.")

        self.status = AppreciationStatus.AI_ANALYZED
        self.ai_analyzed_at = timezone.now()
        self.ai_analysis = analysis_data
        self.save(update_fields=["status", "ai_analyzed_at", "ai_analysis"])

    def send(self):
        """Send appreciation and trigger notification"""
        from django.utils import timezone

        if self.status not in (AppreciationStatus.ACTIVATED, AppreciationStatus.AI_ANALYZED):
            raise ValueError(f"Cannot send appreciation in '{self.status}' status. Must be 'activated' or 'ai_analyzed'.")

        self.status = AppreciationStatus.SENT
        self.sent_at = timezone.now()
        self.save(update_fields=["status", "sent_at"])

        self.send_notification()

    def acknowledge(self):
        """Mark appreciation as acknowledged"""
        from django.utils import timezone

        if self.status != AppreciationStatus.SENT:
            raise ValueError(f"Cannot acknowledge appreciation in '{self.status}' status. Must be in 'sent'.")

        self.status = AppreciationStatus.ACKNOWLEDGED
        self.acknowledged_at = timezone.now()
        self.save(update_fields=["status", "acknowledged_at"])

    def send_notification(self):
        """Send notification to recipient — handled by post_save signal."""
        pass


class AppreciationBadge(UUIDModel, TimeStampedModel):
    """
    Appreciation badge for gamification.

    Badges are awarded based on achievements (e.g., "10 Appreciations Received").
    """

    # Organization
    hospital = models.ForeignKey(
        "organizations.Hospital",
        on_delete=models.CASCADE,
        related_name="appreciation_badges",
        null=True,
        blank=True,
        help_text="Leave blank for system-wide badges",
    )

    # Badge details
    code = models.CharField(max_length=50, unique=True, help_text="Unique badge code")
    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)

    # Visual elements
    icon = models.CharField(max_length=50, blank=True, help_text="Icon class")
    color = models.CharField(max_length=7, blank=True, help_text="Hex color code")

    # Achievement criteria
    criteria_type = models.CharField(
        max_length=50,
        choices=[
            ("received_count", "Total Appreciations Received"),
            ("received_month", "Appreciations Received in a Month"),
            ("streak_weeks", "Consecutive Weeks with Appreciation"),
            ("diverse_senders", "Appreciations from Different Senders"),
        ],
        db_index=True,
    )
    criteria_value = models.IntegerField(help_text="Value to achieve (e.g., 10 for 10 appreciations)")

    # Display order
    order = models.IntegerField(default=0)

    # Status
    is_active = models.BooleanField(default=True)

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

    def __str__(self):
        hospital_name = self.hospital.name if self.hospital else "System-wide"
        return f"{hospital_name} - {self.name_en}"

    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

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

        if get_language() == "ar" and self.description_ar:
            return self.description_ar
        return self.description_en


class UserBadge(UUIDModel, TimeStampedModel):
    """
    User badge - tracks badges earned by users.

    Links users (or physicians) to badges they've earned.
    """

    # Recipient (Generic FK to User or Physician)
    recipient_content_type = models.ForeignKey(
        ContentType, on_delete=models.SET_NULL, null=True, blank=True, related_name="earned_badges_recipients"
    )
    recipient_object_id = models.UUIDField(null=True, blank=True)
    recipient = GenericForeignKey("recipient_content_type", "recipient_object_id")

    # Badge
    badge = models.ForeignKey(AppreciationBadge, on_delete=models.CASCADE, related_name="earned_by")

    # Achievement details
    earned_at = models.DateTimeField(auto_now_add=True)

    # Context
    appreciation_count = models.IntegerField(help_text="Count when badge was earned")

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

    class Meta:
        ordering = ["-earned_at"]
        indexes = [
            models.Index(fields=["recipient_content_type", "recipient_object_id", "-earned_at"]),
        ]

    def __str__(self):
        recipient_name = self.get_recipient_name()
        return f"{recipient_name} - {self.badge.name_en}"

    def get_recipient_name(self):
        """Get recipient's name"""
        try:
            return str(self.recipient)
        except Exception:
            return "Unknown"


class AppreciationStats(UUIDModel, TimeStampedModel):
    """
    Appreciation statistics - aggregated monthly.

    Provides monthly statistics for users and physicians.
    """

    # Recipient (Generic FK to User or Physician)
    recipient_content_type = models.ForeignKey(
        ContentType, on_delete=models.SET_NULL, null=True, blank=True, related_name="appreciation_stats_recipients"
    )
    recipient_object_id = models.UUIDField(null=True, blank=True)
    recipient = GenericForeignKey("recipient_content_type", "recipient_object_id")

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

    # Organization
    hospital = models.ForeignKey("organizations.Hospital", on_delete=models.CASCADE, related_name="appreciation_stats")
    department = models.ForeignKey(
        "organizations.Department", on_delete=models.SET_NULL, null=True, blank=True, related_name="appreciation_stats"
    )

    # Statistics
    received_count = models.IntegerField(default=0)
    sent_count = models.IntegerField(default=0)
    acknowledged_count = models.IntegerField(default=0)

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

    # Breakdown by category
    category_breakdown = models.JSONField(default=dict, blank=True, help_text="Breakdown by category ID and count")

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

    class Meta:
        ordering = ["-year", "-month", "-received_count"]
        unique_together = [["recipient_content_type", "recipient_object_id", "year", "month"]]
        indexes = [
            models.Index(fields=["hospital", "year", "month", "-received_count"]),
            models.Index(fields=["department", "year", "month", "-received_count"]),
        ]

    def __str__(self):
        recipient_name = self.get_recipient_name()
        return f"{recipient_name} - {self.year}-{self.month:02d}: {self.received_count} received"

    def get_recipient_name(self):
        """Get recipient's name"""
        try:
            return str(self.recipient)
        except Exception:
            return "Unknown"
