"""
Survey Celery tasks

This module contains tasks for:
- Creating and sending surveys
- Sending survey reminders
- Processing survey responses
- Triggering actions based on 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(bind=True, max_retries=3)
def create_and_send_survey(self, stage_instance_id):
    """
    Create survey instance and send invitation.
    
    This task is triggered when a journey stage completes
    and auto_send_survey=True.
    
    Args:
        stage_instance_id: UUID of PatientJourneyStageInstance
    
    Returns:
        dict: Result with survey_instance_id and delivery status
    """
    from apps.core.services import create_audit_log
    from apps.journeys.models import PatientJourneyStageInstance
    from apps.notifications.services import NotificationService
    from apps.surveys.models import SurveyInstance
    
    try:
        # Get stage instance
        stage_instance = PatientJourneyStageInstance.objects.select_related(
            'stage_template__survey_template',
            'journey_instance__patient',
            'journey_instance__hospital'
        ).get(id=stage_instance_id)
        
        # Verify survey template exists
        if not stage_instance.stage_template.survey_template:
            logger.warning(f"No survey template for stage {stage_instance.stage_template.name}")
            return {'status': 'skipped', 'reason': 'no_survey_template'}
        
        # Check if survey already created
        if stage_instance.survey_instance:
            logger.info(f"Survey already exists for stage instance {stage_instance_id}")
            return {'status': 'skipped', 'reason': 'already_exists'}
        
        patient = stage_instance.journey_instance.patient
        
        # Determine delivery channel and recipient
        delivery_channel = 'sms'  # Default
        recipient_phone = patient.phone
        recipient_email = patient.email
        
        # Create survey instance
        with transaction.atomic():
            survey_instance = SurveyInstance.objects.create(
                survey_template=stage_instance.stage_template.survey_template,
                patient=patient,
                journey_instance=stage_instance.journey_instance,
                journey_stage_instance=stage_instance,
                encounter_id=stage_instance.journey_instance.encounter_id,
                delivery_channel=delivery_channel,
                recipient_phone=recipient_phone,
                recipient_email=recipient_email
            )
            
            # Link survey to stage
            stage_instance.survey_instance = survey_instance
            stage_instance.survey_sent_at = timezone.now()
            stage_instance.save(update_fields=['survey_instance', 'survey_sent_at'])
        
        # Send survey invitation
        notification_log = NotificationService.send_survey_invitation(
            survey_instance=survey_instance,
            language=patient.language if hasattr(patient, 'language') else 'en'
        )
        
        # Update survey instance status
        survey_instance.status = 'active'
        survey_instance.sent_at = timezone.now()
        survey_instance.save(update_fields=['status', 'sent_at'])
        
        # Log audit event
        create_audit_log(
            event_type='survey_sent',
            description=f"Survey sent to {patient.get_full_name()} for stage {stage_instance.stage_template.name}",
            content_object=survey_instance,
            metadata={
                'survey_template': stage_instance.stage_template.survey_template.name,
                'stage': stage_instance.stage_template.name,
                'encounter_id': stage_instance.journey_instance.encounter_id,
                'channel': delivery_channel
            }
        )
        
        logger.info(
            f"Survey created and sent: {survey_instance.id} to {patient.get_full_name()} "
            f"via {delivery_channel}"
        )
        
        return {
            'status': 'sent',
            'survey_instance_id': str(survey_instance.id),
            'notification_log_id': str(notification_log.id)
        }
    
    except PatientJourneyStageInstance.DoesNotExist:
        error_msg = f"Stage instance {stage_instance_id} not found"
        logger.error(error_msg)
        return {'status': 'error', 'reason': error_msg}
    
    except Exception as e:
        error_msg = f"Error creating/sending survey: {str(e)}"
        logger.error(error_msg, exc_info=True)
        
        # Retry the task
        raise self.retry(exc=e, countdown=60 * (self.request.retries + 1))


@shared_task
def send_survey_reminder(survey_instance_id):
    """
    Send reminder for incomplete survey.
    
    Args:
        survey_instance_id: UUID of SurveyInstance
    
    Returns:
        dict: Result with delivery status
    """
    from apps.notifications.services import NotificationService
    from apps.surveys.models import SurveyInstance
    
    try:
        survey_instance = SurveyInstance.objects.select_related(
            'patient', 'survey_template'
        ).get(id=survey_instance_id)
        
        # Only send reminder if survey is still pending/active
        if survey_instance.status not in ['pending', 'active']:
            return {'status': 'skipped', 'reason': f'survey_status_{survey_instance.status}'}
        
        # Send reminder
        patient = survey_instance.patient
        language = patient.language if hasattr(patient, 'language') else 'en'
        
        notification_log = NotificationService.send_survey_invitation(
            survey_instance=survey_instance,
            language=language
        )
        
        logger.info(f"Survey reminder sent for {survey_instance.id}")
        
        return {
            'status': 'sent',
            'notification_log_id': str(notification_log.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 sending survey reminder: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {'status': 'error', 'reason': error_msg}


@shared_task
def process_survey_completion(survey_instance_id):
    """
    Process completed survey.
    
    This task:
    1. Calculates the survey score
    2. Checks if score is negative
    3. Creates PXAction if negative (Phase 6)
    
    Args:
        survey_instance_id: UUID of SurveyInstance
    
    Returns:
        dict: Result with score and action status
    """
    from apps.core.services import create_audit_log
    from apps.surveys.models import SurveyInstance
    
    try:
        survey_instance = SurveyInstance.objects.select_related(
            'survey_template', 'patient'
        ).get(id=survey_instance_id)
        
        # Calculate score
        score = survey_instance.calculate_score()
        
        # Log completion
        create_audit_log(
            event_type='survey_completed',
            description=f"Survey completed by {survey_instance.patient.get_full_name()} with score {score}",
            content_object=survey_instance,
            metadata={
                'score': float(score) if score else None,
                'is_negative': survey_instance.is_negative,
                'survey_template': survey_instance.survey_template.name
            }
        )
        
        logger.info(
            f"Survey {survey_instance.id} completed with score {score} "
            f"(negative: {survey_instance.is_negative})"
        )
        
        # If negative, create PXAction
        if survey_instance.is_negative:
            logger.info(f"Negative survey detected - creating PXAction")
            
            # Check if it's a complaint resolution survey
            if survey_instance.survey_template.survey_type == 'complaint_resolution':
                from apps.px_action_center.tasks import create_action_from_complaint_resolution
                create_action_from_complaint_resolution.delay(str(survey_instance.id))
            else:
                # Regular survey
                from apps.px_action_center.tasks import create_action_from_survey
                create_action_from_survey.delay(str(survey_instance.id))
        
        return {
            'status': 'processed',
            'score': float(score) if score else None,
            'is_negative': survey_instance.is_negative
        }
    
    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 processing survey completion: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {'status': 'error', 'reason': error_msg}


@shared_task(bind=True, max_retries=3)
def send_satisfaction_feedback(self, survey_instance_id, user_id=None):
    """
    Send satisfaction feedback form to patient after negative survey contact.
    
    This creates a feedback form linked to the survey and sends it to the patient
    to assess their satisfaction with the resolution.
    
    Args:
        survey_instance_id: UUID of SurveyInstance
        user_id: UUID of User who initiated the feedback (optional)
    
    Returns:
        dict: Result with feedback_id and delivery status
    """
    from apps.core.services import create_audit_log
    from apps.feedback.models import Feedback, FeedbackType, FeedbackResponse
    from apps.notifications.services import NotificationService
    from apps.surveys.models import SurveyInstance
    
    try:
        # Get survey instance
        survey_instance = SurveyInstance.objects.select_related(
            'patient', 'survey_template', 'journey_instance__hospital'
        ).get(id=survey_instance_id)
        
        # Check if feedback already sent
        if survey_instance.satisfaction_feedback_sent:
            logger.warning(f"Satisfaction feedback already sent for survey {survey_instance_id}")
            return {'status': 'skipped', 'reason': 'already_sent'}
        
        # Check if patient was contacted
        if not survey_instance.patient_contacted:
            logger.warning(f"Patient not contacted yet for survey {survey_instance_id}")
            return {'status': 'skipped', 'reason': 'patient_not_contacted'}
        
        patient = survey_instance.patient
        hospital = survey_instance.journey_instance.hospital if survey_instance.journey_instance else patient.primary_hospital
        
        # Create satisfaction feedback
        with transaction.atomic():
            feedback = Feedback.objects.create(
                patient=patient,
                hospital=hospital,
                department=survey_instance.journey_stage_instance.stage_template.department if survey_instance.journey_stage_instance else None,
                feedback_type=FeedbackType.SATISFACTION_CHECK,
                title=f"Satisfaction Check - {survey_instance.survey_template.name}",
                message=f"Please rate your satisfaction with how we addressed your concerns regarding the survey.",
                category='communication',
                priority='medium',
                sentiment='neutral',
                status='submitted',
                related_survey=survey_instance,
                encounter_id=survey_instance.encounter_id,
                source='system',
                metadata={
                    'survey_id': str(survey_instance.id),
                    'survey_score': float(survey_instance.total_score) if survey_instance.total_score else None,
                    'auto_generated': True
                }
            )
            
            # Create initial response
            FeedbackResponse.objects.create(
                feedback=feedback,
                response_type='note',
                message=f"Satisfaction feedback automatically created following negative survey (Score: {survey_instance.total_score})",
                created_by_id=user_id,
                is_internal=True
            )
            
            # Update survey instance
            survey_instance.satisfaction_feedback_sent = True
            survey_instance.satisfaction_feedback_sent_at = timezone.now()
            survey_instance.save(update_fields=['satisfaction_feedback_sent', 'satisfaction_feedback_sent_at'])
        
        # Send notification to patient
        # TODO: Implement feedback form link notification
        # For now, we'll log it
        logger.info(f"Satisfaction feedback {feedback.id} created for survey {survey_instance.id}")
        
        # Log audit event
        create_audit_log(
            event_type='satisfaction_feedback_sent',
            description=f"Satisfaction feedback sent to {patient.get_full_name()} for survey {survey_instance.survey_template.name}",
            content_object=feedback,
            metadata={
                'survey_id': str(survey_instance.id),
                'survey_score': float(survey_instance.total_score) if survey_instance.total_score else None,
                'feedback_id': str(feedback.id)
            }
        )
        
        return {
            'status': 'sent',
            'feedback_id': str(feedback.id),
            'survey_id': str(survey_instance.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 sending satisfaction feedback: {str(e)}"
        logger.error(error_msg, exc_info=True)
        
        # Retry the task
        raise self.retry(exc=e, countdown=60 * (self.request.retries + 1))
