"""
SLA Functionality Test Script

This script tests the SLA system including:
- First SLA reminder
- Second SLA reminder (NEW)
- Escalation based on reminders
- Thank you email (when complaint is closed)

Usage:
    python test_sla_functionality.py
"""

import os
import django
from datetime import timedelta
from django.utils import timezone

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()

from apps.complaints.models import (
    Complaint, ComplaintStatus, ComplaintSLAConfig, 
    EscalationRule, ComplaintUpdate
)
from apps.organizations.models import Hospital, Department, Staff
from apps.accounts.models import User
from apps.complaints.tasks import send_sla_reminders, check_overdue_complaints, escalate_after_reminder


def print_section(title):
    """Print a section header"""
    print("\n" + "="*70)
    print(f"  {title}")
    print("="*70)


def print_subsection(title):
    """Print a subsection header"""
    print(f"\n--- {title} ---")


def setup_test_data():
    """Setup test data for SLA testing"""
    print_section("Setting Up Test Data")
    
    # Get or create test hospital
    hospital = Hospital.objects.first()
    if not hospital:
        hospital = Hospital.objects.create(
            name="Test Hospital",
            name_ar="مستشفى الاختبار",
            code="TEST",
            status='active'
        )
        print(f"✓ Created test hospital: {hospital.name}")
    else:
        print(f"✓ Using existing hospital: {hospital.name}")
    
    # Get or create test department
    department = Department.objects.filter(hospital=hospital).first()
    if not department:
        department = Department.objects.create(
            hospital=hospital,
            name="Test Department",
            name_ar="قسم الاختبار",
            code="TEST-DEPT",
            status='active'
        )
        print(f"✓ Created test department: {department.name}")
    else:
        print(f"✓ Using existing department: {department.name}")
    
    # Get or create test user
    test_user = User.objects.filter(email='test@example.com').first()
    if not test_user:
        test_user = User.objects.create_user(
            email='test@example.com',
            first_name='Test',
            last_name='User',
            password='testpass123'
        )
        test_user.hospital = hospital
        test_user.save()
        print(f"✓ Created test user: {test_user.get_full_name()}")
    else:
        print(f"✓ Using existing user: {test_user.get_full_name()}")
    
    # Get or create test staff
    test_staff = Staff.objects.filter(hospital=hospital).first()
    if not test_staff:
        test_staff = Staff.objects.create(
            hospital=hospital,
            department=department,
            first_name='John',
            last_name='Doe',
            first_name_ar='جون',
            last_name_ar='دو',
            job_title='Nurse',
            job_title_ar='ممرض',
            status='active'
        )
        print(f"✓ Created test staff: {test_staff.first_name} {test_staff.last_name}")
    else:
        print(f"✓ Using existing staff: {test_staff.first_name} {test_staff.last_name}")
    
    return hospital, department, test_user, test_staff


def setup_sla_config(hospital):
    """Setup SLA configuration with second reminder enabled"""
    print_section("Setting Up SLA Configuration")
    
    # Create or update SLA config with second reminder enabled
    sla_config, created = ComplaintSLAConfig.objects.get_or_create(
        hospital=hospital,
        severity='medium',
        priority='medium',
        defaults={
            'sla_hours': 48,  # 48 hour SLA
            'reminder_hours_before': 24,  # First reminder at 24 hours
            'second_reminder_enabled': True,  # Enable second reminder
            'second_reminder_hours_before': 6,  # Second reminder at 6 hours
            'thank_you_email_enabled': True,  # Enable thank you email
            'is_active': True
        }
    )
    
    if created:
        print(f"✓ Created SLA config:")
        print(f"  - SLA: {sla_config.sla_hours} hours")
        print(f"  - First reminder: {sla_config.reminder_hours_before} hours before")
        print(f"  - Second reminder: {sla_config.second_reminder_hours_before} hours before (enabled)")
        print(f"  - Thank you email: enabled")
    else:
        print(f"✓ Using existing SLA config")
        sla_config.second_reminder_enabled = True
        sla_config.second_reminder_hours_before = 6
        sla_config.thank_you_email_enabled = True
        sla_config.save()
        print(f"  - Updated: Second reminder enabled")
    
    return sla_config


def setup_escalation_rules(hospital):
    """Setup escalation rules"""
    print_section("Setting Up Escalation Rules")
    
    # Level 1 escalation (first overdue)
    rule1, created = EscalationRule.objects.get_or_create(
        hospital=hospital,
        name="First Escalation - Department Manager",
        escalation_level=1,
        defaults={
            'description': 'Escalate to department manager when overdue',
            'trigger_on_overdue': True,
            'trigger_hours_overdue': 0,  # Immediately when overdue
            'escalate_to_role': 'department_manager',
            'reminder_escalation_enabled': False,
            'is_active': True
        }
    )
    
    if created:
        print(f"✓ Created escalation rule Level 1: {rule1.name}")
    else:
        print(f"✓ Using existing escalation rule Level 1")
    
    # Level 2 escalation (second reminder-based)
    rule2, created = EscalationRule.objects.get_or_create(
        hospital=hospital,
        name="Second Escalation - After Reminder",
        escalation_level=2,
        defaults={
            'description': 'Escalate after first reminder if no action',
            'trigger_on_overdue': False,
            'reminder_escalation_enabled': True,
            'reminder_escalation_hours': 12,  # Escalate 12 hours after first reminder
            'escalate_to_role': 'hospital_admin',
            'max_escalation_level': 3,
            'is_active': True
        }
    )
    
    if created:
        print(f"✓ Created escalation rule Level 2: {rule2.name}")
    else:
        print(f"✓ Using existing escalation rule Level 2")
    
    return [rule1, rule2]


def create_test_complaint(hospital, department, test_user, test_staff):
    """Create a test complaint with specific SLA timing"""
    print_section("Creating Test Complaint")
    
    # Create a complaint due in 26 hours (triggers first reminder at 24h)
    due_time = timezone.now() + timedelta(hours=26)
    
    complaint = Complaint.objects.create(
        title="Test SLA Complaint",
        description="This is a test complaint to verify SLA functionality including second reminders.",
        hospital=hospital,
        department=department,
        staff=test_staff,
        status=ComplaintStatus.OPEN,
        priority='medium',
        severity='medium',
        assigned_to=test_user,
        due_at=due_time,
        is_overdue=False
    )
    
    print(f"✓ Created complaint: {complaint.title}")
    print(f"  - ID: {complaint.id}")
    print(f"  - Status: {complaint.status}")
    print(f"  - Priority: {complaint.priority}")
    print(f"  - Severity: {complaint.severity}")
    print(f"  - Due at: {complaint.due_at}")
    print(f"  - Time until due: {(complaint.due_at - timezone.now()).total_seconds() / 3600:.1f} hours")
    print(f"  - First reminder at: {complaint.due_at - timedelta(hours=24)}")
    print(f"  - Second reminder at: {complaint.due_at - timedelta(hours=6)}")
    
    return complaint


def test_first_reminder(complaint):
    """Test first SLA reminder"""
    print_section("Testing First SLA Reminder")
    
    print(f"\nCurrent time: {timezone.now()}")
    print(f"Reminder threshold: {complaint.due_at - timedelta(hours=24)}")
    
    # Check if first reminder should be sent
    hours_remaining = (complaint.due_at - timezone.now()).total_seconds() / 3600
    
    print_subsection("Reminder Status")
    print(f"Hours until due: {hours_remaining:.1f}")
    print(f"First reminder already sent: {complaint.reminder_sent_at is not None}")
    print(f"Second reminder already sent: {complaint.second_reminder_sent_at is not None}")
    
    if hours_remaining <= 24 and complaint.reminder_sent_at is None:
        print_subsection("Sending First Reminder")
        # Manually trigger reminder for testing
        result = send_sla_reminders.delay()
        print(f"✓ First SLA reminder task triggered")
        print(f"  Result: {result.get()}")
        
        # Refresh complaint
        complaint.refresh_from_db()
        print(f"  Reminder sent at: {complaint.reminder_sent_at}")
    else:
        print("ℹ First reminder not yet due or already sent")


def test_second_reminder(complaint):
    """Test second SLA reminder"""
    print_section("Testing Second SLA Reminder")
    
    print(f"\nCurrent time: {timezone.now()}")
    print(f"Second reminder threshold: {complaint.due_at - timedelta(hours=6)}")
    
    hours_remaining = (complaint.due_at - timezone.now()).total_seconds() / 3600
    
    print_subsection("Reminder Status")
    print(f"Hours until due: {hours_remaining:.1f}")
    print(f"First reminder already sent: {complaint.reminder_sent_at is not None}")
    print(f"Second reminder already sent: {complaint.second_reminder_sent_at is not None}")
    
    # For testing, we'll simulate time passing by updating the complaint
    # In a real scenario, the Celery task would run periodically
    if complaint.reminder_sent_at and complaint.second_reminder_sent_at is None:
        print_subsection("Simulating Second Reminder Trigger")
        print("Note: In production, Celery Beat runs this task hourly")
        print("For this test, we're showing the logic without waiting")
        
        # Check if second reminder should be sent (at 6 hours before due)
        if hours_remaining <= 6:
            print(f"✓ Second reminder condition met (<= 6 hours remaining)")
            result = send_sla_reminders.delay()
            print(f"  Task triggered: {result.get()}")
            
            # Refresh complaint
            complaint.refresh_from_db()
            if complaint.second_reminder_sent_at:
                print(f"  Second reminder sent at: {complaint.second_reminder_sent_at}")
        else:
            print(f"ℹ Second reminder not yet due ({hours_remaining:.1f} hours > 6 hours)")
    else:
        print("ℹ First reminder not sent yet or second reminder already sent")


def test_escalation(complaint):
    """Test escalation functionality"""
    print_section("Testing Escalation")
    
    print_subsection("Current Escalation Status")
    escalation_level = complaint.metadata.get('escalation_level', 0)
    print(f"Current escalation level: {escalation_level}")
    print(f"Last escalation: {complaint.escalated_at}")
    
    if complaint.escalated_at:
        print(f"Escalation history: {complaint.metadata.get('last_escalation_rule', {})}")
    
    print_subsection("Escalation Rules")
    rules = EscalationRule.objects.filter(
        hospital=complaint.hospital,
        is_active=True
    ).order_by('escalation_level')
    
    for rule in rules:
        print(f"Level {rule.escalation_level}: {rule.name}")
        print(f"  - Trigger: {'Overdue' if rule.trigger_on_overdue else 'After reminder'}")
        if rule.trigger_on_overdue:
            print(f"  - Hours overdue: {rule.trigger_hours_overdue}")
        else:
            print(f"  - Hours after reminder: {rule.reminder_escalation_hours}")
        print(f"  - Escalate to: {rule.escalate_to_role}")
    
    # Test escalation check
    print_subsection("Checking Escalation Eligibility")
    if complaint.is_overdue:
        print(f"✓ Complaint is overdue")
        print(f"  Hours overdue: {(timezone.now() - complaint.due_at).total_seconds() / 3600:.1f}")
    else:
        print(f"ℹ Complaint is not overdue yet")
        print(f"  Hours until due: {(complaint.due_at - timezone.now()).total_seconds() / 3600:.1f}")
    
    if complaint.reminder_sent_at:
        hours_since_reminder = (timezone.now() - complaint.reminder_sent_at).total_seconds() / 3600
        print(f"Hours since first reminder: {hours_since_reminder:.1f}")


def test_timeline(complaint):
    """Display complaint timeline"""
    print_section("Complaint Timeline")
    
    updates = complaint.updates.all().order_by('-created_at')
    
    if not updates:
        print("ℹ No timeline updates yet")
    else:
        for update in updates:
            print(f"\n[{update.created_at.strftime('%Y-%m-%d %H:%M:%S')}] {update.update_type.upper()}")
            print(f"  {update.message}")
            if update.metadata:
                print(f"  Metadata: {update.metadata}")


def run_all_tests():
    """Run all SLA tests"""
    print("\n" + "="*70)
    print("  SLA FUNCTIONALITY TEST SUITE")
    print("="*70)
    print("\nThis script tests the complete SLA system including:")
    print("  - First SLA reminder")
    print("  - Second SLA reminder (NEW FEATURE)")
    print("  - Escalation based on reminders")
    print("  - Complaint timeline tracking")
    
    try:
        # Setup test data
        hospital, department, test_user, test_staff = setup_test_data()
        
        # Setup SLA configuration
        sla_config = setup_sla_config(hospital)
        
        # Setup escalation rules
        rules = setup_escalation_rules(hospital)
        
        # Create test complaint
        complaint = create_test_complaint(hospital, department, test_user, test_staff)
        
        # Test first reminder
        test_first_reminder(complaint)
        
        # Test second reminder
        test_second_reminder(complaint)
        
        # Test escalation
        test_escalation(complaint)
        
        # Display timeline
        test_timeline(complaint)
        
        # Summary
        print_section("Test Summary")
        print("✓ Test data setup completed")
        print("✓ SLA configuration verified")
        print("✓ Escalation rules verified")
        print("✓ Test complaint created")
        print("✓ First reminder logic tested")
        print("✓ Second reminder logic tested")
        print("✓ Escalation logic tested")
        print("✓ Timeline tracking verified")
        
        print("\n" + "="*70)
        print("  SLA FUNCTIONALITY TEST COMPLETED SUCCESSFULLY")
        print("="*70)
        
        print("\nNext Steps:")
        print("1. Configure SLA settings via admin panel for production")
        print("2. Test with real time (let Celery Beat run automatically)")
        print("3. Verify email sending is configured correctly")
        print("4. Test escalation with different severity/priority levels")
        print("5. Monitor logs for SLA reminder tasks")
        
    except Exception as e:
        print(f"\n❌ Error during testing: {str(e)}")
        import traceback
        traceback.print_exc()


if __name__ == '__main__':
    run_all_tests()
