"""
PX Action Center Celery tasks

This module contains tasks for:
- Checking overdue actions
- Sending SLA reminders
- Escalating overdue actions
- Creating actions from negative feedback
"""
import logging

from celery import shared_task
from django.db import transaction
from django.utils import timezone

logger = logging.getLogger(__name__)


@shared_task
def check_overdue_actions():
    """
    Periodic task to check for overdue actions.
    
    Runs every 15 minutes (configured in config/celery.py).
    Updates is_overdue flag and triggers escalation if configured.
    """
    from apps.px_action_center.models import ActionStatus, PXAction
    
    # Get active actions (not closed or cancelled)
    active_actions = PXAction.objects.filter(
        status__in=[ActionStatus.OPEN, ActionStatus.IN_PROGRESS, ActionStatus.PENDING_APPROVAL]
    ).select_related('hospital', 'assigned_to')
    
    overdue_count = 0
    escalated_count = 0
    
    for action in active_actions:
        if action.check_overdue():
            overdue_count += 1
            logger.warning(
                f"Action {action.id} is overdue: {action.title} "
                f"(due: {action.due_at})"
            )
            
            # Trigger escalation
            escalate_action.delay(str(action.id))
            escalated_count += 1
    
    if overdue_count > 0:
        logger.info(f"Found {overdue_count} overdue actions, escalated {escalated_count}")
    
    return {'overdue_count': overdue_count, 'escalated_count': escalated_count}


@shared_task
def send_sla_reminders():
    """
    Periodic task to send SLA reminders.
    
    Runs every hour (configured in config/celery.py).
    Sends reminders for actions approaching their SLA deadline.
    """
    from apps.px_action_center.models import ActionStatus, PXAction
    
    # Get active actions without reminders sent
    active_actions = PXAction.objects.filter(
        status__in=[ActionStatus.OPEN, ActionStatus.IN_PROGRESS],
        reminder_sent_at__isnull=True
    ).select_related('hospital', 'assigned_to')
    
    reminder_count = 0
    
    for action in active_actions:
        # Check if within reminder window (4 hours before due by default)
        time_until_due = action.due_at - timezone.now()
        hours_until_due = time_until_due.total_seconds() / 3600
        
        if 0 < hours_until_due <= 4:  # Within 4 hours of due date
            # Send reminder
            if action.assigned_to and action.assigned_to.email:
                from apps.notifications.services import send_email, get_email_header_html
                send_email(
                    email=action.assigned_to.email,
                    subject=f"SLA Reminder: Action Due Soon - {action.title}",
                    message=f"Action {action.title} is due in {int(hours_until_due)} hours.",
                    html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">SLA Reminder: Action Due Soon</h2>
        <p style="margin: 0 0 12px 0;">Action <strong>{action.title}</strong> is due in <strong>{int(hours_until_due)} hours</strong>.</p>
        <p style="margin: 0; color: #6b7280;">Please take action before the deadline.</p>
    </div>
</div>
""",
                    related_object=action,
                    metadata={'action_id': str(action.id)}
                )
            
            # Mark reminder sent
            action.reminder_sent_at = timezone.now()
            action.save(update_fields=['reminder_sent_at'])
            
            # Log reminder
            from apps.px_action_center.models import PXActionLog
            PXActionLog.objects.create(
                action=action,
                log_type='sla_reminder',
                message=f"SLA reminder sent - due in {int(hours_until_due)} hours"
            )
            
            reminder_count += 1
            logger.info(f"SLA reminder sent for action {action.id}")
    
    if reminder_count > 0:
        logger.info(f"Sent {reminder_count} SLA reminders")
    
    return {'reminder_count': reminder_count}


@shared_task
def escalate_action(action_id):
    """
    Escalate an overdue action.
    
    Escalation logic:
    1. Increment escalation level
    2. Reassign to higher level (department manager → hospital admin → PX admin)
    3. Log escalation
    4. Send notification
    
    Args:
        action_id: UUID of the PXAction
    
    Returns:
        dict: Result with escalation details
    """
    from apps.px_action_center.models import PXAction, PXActionLog
    
    try:
        action = PXAction.objects.select_related(
            'hospital', 'department', 'assigned_to'
        ).get(id=action_id)
        
        # Check if already escalated recently
        if action.escalated_at:
            hours_since_escalation = (timezone.now() - action.escalated_at).total_seconds() / 3600
            if hours_since_escalation < 2:  # Don't escalate more than once every 2 hours
                return {'status': 'skipped', 'reason': 'recently_escalated'}
        
        # Increment escalation level
        action.escalation_level += 1
        action.escalated_at = timezone.now()
        
        # Determine escalation target based on current assignment
        old_assignee = action.assigned_to
        new_assignee = None
        
        # Simple escalation logic: assign to department manager or hospital admin
        if action.department and action.department.manager:
            new_assignee = action.department.manager
        elif action.hospital:
            # Find hospital admin for this hospital
            from apps.accounts.models import User
            hospital_admins = User.objects.filter(
                hospital=action.hospital,
                groups__name='Hospital Admin'
            ).first()
            if hospital_admins:
                new_assignee = hospital_admins
        
        if new_assignee and new_assignee != old_assignee:
            action.assigned_to = new_assignee
            action.assigned_at = timezone.now()
        
        action.save()
        
        # Log escalation
        PXActionLog.objects.create(
            action=action,
            log_type='escalation',
            message=f"Action escalated (level {action.escalation_level}). Assigned to {new_assignee.get_full_name() if new_assignee else 'unassigned'}",
            metadata={
                'escalation_level': action.escalation_level,
                'old_assignee': str(old_assignee.id) if old_assignee else None,
                'new_assignee': str(new_assignee.id) if new_assignee else None
            }
        )
        
        # Send notification
        if new_assignee and new_assignee.email:
            from apps.notifications.services import send_email, get_email_header_html
            send_email(
                email=new_assignee.email,
                subject=f"Escalated Action Assigned: {action.title}",
                message=f"An overdue action has been escalated to you: {action.title}",
                html_message=f"""
<div style="font-family: 'Segoe UI', Tahoma, sans-serif; max-width: 600px; margin: 0 auto; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden;">
    {get_email_header_html()}
    <div style="padding: 20px;">
        <h2 style="color: #005696; font-size: 18px; margin: 0 0 12px 0;">Escalated Action Assigned</h2>
        <p style="margin: 0 0 12px 0;">An overdue action has been escalated to you:</p>
        <div style="background: #f9fafb; padding: 12px; border-radius: 6px; margin: 0 0 12px 0;">
            <p style="margin: 0;"><strong>{action.title}</strong></p>
        </div>
        <p style="margin: 0; color: #6b7280;">Please take action at your earliest convenience.</p>
    </div>
</div>
""",
                related_object=action
            )
        
        logger.info(
            f"Action {action.id} escalated to level {action.escalation_level}, "
            f"assigned to {new_assignee.get_full_name() if new_assignee else 'unassigned'}"
        )
        
        return {
            'status': 'escalated',
            'escalation_level': action.escalation_level,
            'assigned_to': new_assignee.get_full_name() if new_assignee else None
        }
    
    except PXAction.DoesNotExist:
        error_msg = f"Action {action_id} not found"
        logger.error(error_msg)
        return {'status': 'error', 'reason': error_msg}
    
    except Exception as e:
        error_msg = f"Error escalating action: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {'status': 'error', 'reason': error_msg}


@shared_task
def create_action_from_survey(survey_instance_id):
    """
    Create PX Action from negative survey.
    
    Args:
        survey_instance_id: UUID of SurveyInstance with negative score
    
    Returns:
        dict: Result with action_id
    """
    from apps.core.services import create_audit_log
    from apps.px_action_center.models import PXAction
    from apps.surveys.models import SurveyInstance
    
    try:
        survey = SurveyInstance.objects.select_related(
            'survey_template', 'patient', 'journey_instance__hospital',
            'journey_instance__department'
        ).get(id=survey_instance_id)
        
        # Verify it's negative
        if not survey.is_negative:
            return {'status': 'skipped', 'reason': 'not_negative'}
        
        # Create action
        action = PXAction.objects.create(
            source_type='survey',
            content_object=survey,
            title=f"Negative Survey: {survey.survey_template.name} - {survey.patient.get_full_name()}",
            description=f"Patient {survey.patient.get_full_name()} gave a negative rating ({survey.total_score}) on {survey.survey_template.name}",
            hospital=survey.journey_instance.hospital if survey.journey_instance else survey.survey_template.hospital,
            department=survey.journey_instance.department if survey.journey_instance else None,
            category='service_quality',
            severity='medium',
            priority='medium',
            metadata={
                'survey_id': str(survey.id),
                'score': float(survey.total_score) if survey.total_score else None,
                'survey_template': survey.survey_template.name
            }
        )
        
        # Log action creation
        create_audit_log(
            event_type='action_created',
            description=f"PX Action created from negative survey: {action.title}",
            content_object=action,
            metadata={
                'source': 'survey',
                'survey_id': str(survey.id),
                'score': float(survey.total_score) if survey.total_score else None
            }
        )
        
        logger.info(f"PX Action created from negative survey {survey.id}: {action.id}")
        
        return {
            'status': 'created',
            'action_id': str(action.id)
        }
    
    except SurveyInstance.DoesNotExist:
        error_msg = f"Survey instance {survey_instance_id} not found"
        logger.error(error_msg)
        return {'status': 'error', 'reason': error_msg}
    
    except Exception as e:
        error_msg = f"Error creating action from survey: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {'status': 'error', 'reason': error_msg}


@shared_task
def create_action_from_complaint_resolution(survey_instance_id):
    """
    Create PX Action from negative complaint resolution satisfaction.
    
    Args:
        survey_instance_id: UUID of complaint resolution SurveyInstance
    
    Returns:
        dict: Result with action_id
    """
    from apps.core.services import create_audit_log
    from apps.px_action_center.models import PXAction
    from apps.surveys.models import SurveyInstance
    
    try:
        survey = SurveyInstance.objects.select_related(
            'survey_template', 'patient'
        ).get(id=survey_instance_id)
        
        # Verify it's negative
        if not survey.is_negative:
            return {'status': 'skipped', 'reason': 'not_negative'}
        
        # Get related complaint
        complaint = survey.complaint_resolution.first() if hasattr(survey, 'complaint_resolution') else None
        
        # Create action
        action = PXAction.objects.create(
            source_type='complaint_resolution',
            content_object=survey,
            title=f"Dissatisfied with Complaint Resolution - {survey.patient.get_full_name()}",
            description=f"Patient dissatisfied with complaint resolution (score: {survey.total_score})",
            hospital=complaint.hospital if complaint else survey.survey_template.hospital,
            department=complaint.department if complaint else None,
            category='service_quality',
            severity='high',  # Complaint resolution dissatisfaction is high priority
            priority='high',
            metadata={
                'survey_id': str(survey.id),
                'complaint_id': str(complaint.id) if complaint else None,
                'score': float(survey.total_score) if survey.total_score else None
            }
        )
        
        # Log action creation
        create_audit_log(
            event_type='action_created',
            description=f"PX Action created from negative complaint resolution: {action.title}",
            content_object=action,
            metadata={
                'source': 'complaint_resolution',
                'survey_id': str(survey.id),
                'score': float(survey.total_score) if survey.total_score else None
            }
        )
        
        logger.info(f"PX Action created from negative complaint resolution {survey.id}: {action.id}")
        
        return {
            'status': 'created',
            'action_id': str(action.id)
        }
    
    except SurveyInstance.DoesNotExist:
        error_msg = f"Survey instance {survey_instance_id} not found"
        logger.error(error_msg)
        return {'status': 'error', 'reason': error_msg}
    
    except Exception as e:
        error_msg = f"Error creating action from complaint resolution: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {'status': 'error', 'reason': error_msg}
