"""
Notification Settings Models - Configurable notification preferences

This module provides per-hospital notification configuration allowing
admins to toggle which notifications are sent via which channels.
"""
from django.db import models
from django.core.cache import cache

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


class NotificationCategory(BaseChoices):
    """Categories of notifications"""
    COMPLAINT = 'complaint', 'Complaint Notifications'
    SURVEY = 'survey', 'Survey Notifications'
    ACTION = 'action', 'Action Notifications'
    SYSTEM = 'system', 'System Notifications'


class NotificationEvent(BaseChoices):
    """
    All notification events that can be configured.
    Each event can have different channels enabled/disabled.
    """
    # Complaint Events
    COMPLAINT_ACKNOWLEDGMENT = 'complaint_acknowledgment', 'Complaint Acknowledgment'
    COMPLAINT_ASSIGNED = 'complaint_assigned', 'Complaint Assigned'
    COMPLAINT_STATUS_CHANGED = 'complaint_status_changed', 'Complaint Status Changed'
    COMPLAINT_RESOLVED = 'complaint_resolved', 'Complaint Resolved'
    COMPLAINT_CLOSED = 'complaint_closed', 'Complaint Closed'
    
    # Department Response Events
    EXPLANATION_REQUESTED = 'explanation_requested', 'Department Request Sent'
    EXPLANATION_REMINDER = 'explanation_reminder', 'Department Reminder (24h)'
    EXPLANATION_OVERDUE = 'explanation_overdue', 'Department Response Overdue/Escalation'
    EXPLANATION_RECEIVED = 'explanation_received', 'Department Response Received'
    
    # Survey Events
    SURVEY_INVITATION = 'survey_invitation', 'Survey Invitation'
    SURVEY_REMINDER = 'survey_reminder', 'Survey Reminder'
    SURVEY_COMPLETED = 'survey_completed', 'Survey Completed'
    
    # Action Events
    ACTION_ASSIGNED = 'action_assigned', 'Action Assigned'
    ACTION_DUE_SOON = 'action_due_soon', 'Action Due Soon'
    ACTION_OVERDUE = 'action_overdue', 'Action Overdue'
    
    # SLA Events
    SLA_REMINDER = 'sla_reminder', 'SLA Reminder'
    SLA_BREACH = 'sla_breach', 'SLA Breach Alert'
    
    # Onboarding Events
    ONBOARDING_INVITATION = 'onboarding_invitation', 'Onboarding Invitation'
    ONBOARDING_REMINDER = 'onboarding_reminder', 'Onboarding Reminder'
    ONBOARDING_COMPLETION = 'onboarding_completion', 'Onboarding Completion'


class HospitalNotificationSettings(UUIDModel, TimeStampedModel):
    """
    Per-hospital notification configuration.
    
    Allows hospital admins to customize which notifications are sent
    and via which channels (Email, SMS, WhatsApp).
    """
    
    hospital = models.OneToOneField(
        'organizations.Hospital',
        on_delete=models.CASCADE,
        related_name='notification_settings',
        help_text='Hospital these settings apply to'
    )
    
    # ==================== COMPLAINT NOTIFICATIONS ====================
    
    # Complaint Acknowledgment (to patient)
    complaint_acknowledgment_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint is acknowledged'
    )
    complaint_acknowledgment_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint is acknowledged'
    )
    complaint_acknowledgment_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint is acknowledged'
    )
    
    # Complaint Assigned (to assignee)
    complaint_assigned_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint is assigned'
    )
    complaint_assigned_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint is assigned'
    )
    complaint_assigned_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint is assigned'
    )
    
    # Complaint Status Changed (to relevant parties)
    complaint_status_changed_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint status changes'
    )
    complaint_status_changed_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint status changes'
    )
    complaint_status_changed_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint status changes'
    )
    
    # Complaint Resolved (to patient)
    complaint_resolved_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint is resolved'
    )
    complaint_resolved_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint is resolved'
    )
    complaint_resolved_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint is resolved'
    )
    
    # Complaint Closed (to patient)
    complaint_closed_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint is closed'
    )
    complaint_closed_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint is closed'
    )
    complaint_closed_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint is closed'
    )
    
    # ==================== EXPLANATION NOTIFICATIONS ====================
    
    # Department Request Sent
    explanation_requested_email = models.BooleanField(
        default=True,
        help_text='Send email when complaint is sent to department'
    )
    explanation_requested_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when complaint is sent to department'
    )
    explanation_requested_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when complaint is sent to department'
    )
    
    # Department Reminder at 24h
    explanation_reminder_email = models.BooleanField(
        default=True,
        help_text='Send email reminder when department response is nearing deadline'
    )
    explanation_reminder_sms = models.BooleanField(
        default=False,
        help_text='Send SMS reminder when department response is nearing deadline'
    )
    explanation_reminder_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp reminder when department response is nearing deadline'
    )
    
    # Department Response Overdue/Escalation
    explanation_overdue_email = models.BooleanField(
        default=True,
        help_text='Send email when department response is overdue and escalated'
    )
    explanation_overdue_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when department response is overdue and escalated'
    )
    explanation_overdue_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when department response is overdue and escalated'
    )
    
    # Department Response Received
    explanation_received_email = models.BooleanField(
        default=True,
        help_text='Send email when department response is received'
    )
    explanation_received_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when department response is received'
    )
    explanation_received_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when department response is received'
    )
    explanation_requested_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when explanation is requested from staff'
    )
    explanation_requested_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when explanation is requested from staff'
    )
    
    # Explanation Reminder at 24h (to staff)
    explanation_reminder_email = models.BooleanField(
        default=True,
        help_text='Send email reminder at 24h before SLA expires'
    )
    explanation_reminder_sms = models.BooleanField(
        default=False,
        help_text='Send SMS reminder at 24h before SLA expires'
    )
    explanation_reminder_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp reminder at 24h before SLA expires'
    )
    
    # Explanation Overdue/Escalation (to manager)
    explanation_overdue_email = models.BooleanField(
        default=True,
        help_text='Send email when explanation is overdue (escalation)'
    )
    explanation_overdue_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when explanation is overdue (escalation)'
    )
    explanation_overdue_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when explanation is overdue (escalation)'
    )
    
    # Explanation Received (to assignee)
    explanation_received_email = models.BooleanField(
        default=True,
        help_text='Send email when staff submits explanation'
    )
    explanation_received_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when staff submits explanation'
    )
    explanation_received_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when staff submits explanation'
    )
    
    # Manager CC on Explanation Request
    explanation_manager_cc = models.BooleanField(
        default=False,
        help_text='CC manager when explanation is requested from staff'
    )
    
    # ==================== SURVEY NOTIFICATIONS ====================
    
    # Survey Invitation (to patient)
    survey_invitation_email = models.BooleanField(
        default=True,
        help_text='Send email survey invitation to patient'
    )
    survey_invitation_sms = models.BooleanField(
        default=True,
        help_text='Send SMS survey invitation to patient'
    )
    survey_invitation_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp survey invitation to patient'
    )
    
    # Survey Reminder (to patient)
    survey_reminder_email = models.BooleanField(
        default=True,
        help_text='Send email survey reminder'
    )
    survey_reminder_sms = models.BooleanField(
        default=True,
        help_text='Send SMS survey reminder'
    )
    survey_reminder_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp survey reminder'
    )
    
    # Survey Completed (to admin)
    survey_completed_email = models.BooleanField(
        default=True,
        help_text='Send email when patient completes survey'
    )
    survey_completed_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when patient completes survey'
    )
    
    # ==================== ACTION NOTIFICATIONS ====================
    
    # Action Assigned (to assignee)
    action_assigned_email = models.BooleanField(
        default=True,
        help_text='Send email when action is assigned'
    )
    action_assigned_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when action is assigned'
    )
    action_assigned_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when action is assigned'
    )
    
    # Action Due Soon (to assignee)
    action_due_soon_email = models.BooleanField(
        default=True,
        help_text='Send email when action is due soon'
    )
    action_due_soon_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when action is due soon'
    )
    
    # Action Overdue (to manager)
    action_overdue_email = models.BooleanField(
        default=True,
        help_text='Send email when action is overdue'
    )
    action_overdue_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when action is overdue'
    )
    
    # ==================== SLA NOTIFICATIONS ====================
    
    # SLA Reminder (to assignee)
    sla_reminder_email = models.BooleanField(
        default=True,
        help_text='Send email SLA reminder'
    )
    sla_reminder_sms = models.BooleanField(
        default=False,
        help_text='Send SMS SLA reminder'
    )
    
    # SLA Breach (to manager)
    sla_breach_email = models.BooleanField(
        default=True,
        help_text='Send email when SLA is breached'
    )
    sla_breach_sms = models.BooleanField(
        default=False,
        help_text='Send SMS when SLA is breached'
    )
    sla_breach_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp when SLA is breached'
    )
    
    # ==================== ONBOARDING NOTIFICATIONS ====================
    
    # Onboarding Invitation (to new user)
    onboarding_invitation_email = models.BooleanField(
        default=True,
        help_text='Send email invitation to new provisional users'
    )
    onboarding_invitation_sms = models.BooleanField(
        default=False,
        help_text='Send SMS invitation to new provisional users'
    )
    onboarding_invitation_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp invitation to new provisional users'
    )
    
    # Onboarding Reminder (to pending user)
    onboarding_reminder_email = models.BooleanField(
        default=True,
        help_text='Send email reminder to complete onboarding'
    )
    onboarding_reminder_sms = models.BooleanField(
        default=False,
        help_text='Send SMS reminder to complete onboarding'
    )
    onboarding_reminder_whatsapp = models.BooleanField(
        default=False,
        help_text='Send WhatsApp reminder to complete onboarding'
    )
    
    # Onboarding Completion (to admins)
    onboarding_completion_email = models.BooleanField(
        default=True,
        help_text='Send email notification to admins when user completes onboarding'
    )
    onboarding_completion_sms = models.BooleanField(
        default=False,
        help_text='Send SMS notification to admins when user completes onboarding'
    )
    
    # ==================== GLOBAL SETTINGS ====================
    
    # Master switches
    notifications_enabled = models.BooleanField(
        default=True,
        help_text='Master switch to enable/disable all notifications'
    )
    
    # Quiet hours
    quiet_hours_enabled = models.BooleanField(
        default=False,
        help_text='Enable quiet hours (no SMS/WhatsApp during these hours)'
    )
    quiet_hours_start = models.TimeField(
        default='22:00',
        help_text='Start of quiet hours (e.g., 22:00 for 10 PM)'
    )
    quiet_hours_end = models.TimeField(
        default='08:00',
        help_text='End of quiet hours (e.g., 08:00 for 8 AM)'
    )
    
    # Retry configuration
    retry_failed_notifications = models.BooleanField(
        default=True,
        help_text='Automatically retry failed notifications'
    )
    max_retries = models.IntegerField(
        default=3,
        help_text='Maximum number of retry attempts'
    )
    
    class Meta:
        verbose_name = 'Hospital Notification Settings'
        verbose_name_plural = 'Hospital Notification Settings'
        
    def __str__(self):
        return f"Notification Settings for {self.hospital}"
    
    def save(self, *args, **kwargs):
        """Clear cache when settings are updated"""
        super().save(*args, **kwargs)
        cache.delete(f'notification_settings_{self.hospital_id}')
    
    @classmethod
    def get_for_hospital(cls, hospital_id):
        """
        Get or create settings for a hospital with caching.
        """
        cache_key = f'notification_settings_{hospital_id}'
        settings = cache.get(cache_key)
        
        if settings is None:
            settings, created = cls.objects.get_or_create(
                hospital_id=hospital_id,
                defaults={}
            )
            cache.set(cache_key, settings, 300)  # Cache for 5 minutes
        
        return settings
    
    def is_channel_enabled(self, event, channel):
        """
        Check if a specific channel is enabled for an event.
        
        Args:
            event: NotificationEvent value (e.g., 'explanation_requested')
            channel: 'email', 'sms', or 'whatsapp'
        
        Returns:
            bool: True if channel is enabled for this event
        """
        if not self.notifications_enabled:
            return False
        
        field_name = f"{event}_{channel}"
        return getattr(self, field_name, False)
    
    def get_enabled_channels(self, event):
        """
        Get list of enabled channels for a specific event.
        
        Args:
            event: NotificationEvent value
        
        Returns:
            list: List of enabled channel names ['email', 'sms', ...]
        """
        if not self.notifications_enabled:
            return []
        
        channels = []
        for channel in ['email', 'sms', 'whatsapp']:
            if self.is_channel_enabled(event, channel):
                channels.append(channel)
        
        return channels
    
    def is_quiet_hours(self, current_time=None):
        """
        Check if current time is within quiet hours.
        
        Returns:
            bool: True if quiet hours (SMS/WhatsApp should not be sent)
        """
        if not self.quiet_hours_enabled:
            return False
        
        from django.utils import timezone
        
        if current_time is None:
            current_time = timezone.now().time()
        
        start = self.quiet_hours_start
        end = self.quiet_hours_end
        
        # Handle overnight quiet hours (e.g., 22:00 - 08:00)
        if start > end:
            return current_time >= start or current_time <= end
        else:
            return start <= current_time <= end


class NotificationSettingsLog(UUIDModel, TimeStampedModel):
    """
    Audit log for notification settings changes.
    Tracks who changed what and when.
    """
    
    hospital = models.ForeignKey(
        'organizations.Hospital',
        on_delete=models.CASCADE,
        related_name='notification_settings_logs'
    )
    
    changed_by = models.ForeignKey(
        'accounts.User',
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    
    field_name = models.CharField(max_length=100)
    old_value = models.BooleanField(null=True)
    new_value = models.BooleanField(null=True)
    
    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Notification Settings Change Log'
        verbose_name_plural = 'Notification Settings Change Logs'
