from django.core.management.base import BaseCommand
from django.utils import timezone
from django.db import transaction
from django.db.models import Avg
from datetime import timedelta, datetime
import random
from tqdm import tqdm

from apps.surveys.models import (
    SurveyTemplate, SurveyQuestion, SurveyInstance, 
    SurveyResponse, SurveyTracking, SurveyStatus
)
from apps.organizations.models import Hospital, Patient


class Command(BaseCommand):
    help = 'Seed historical survey data for analytics (1 year timeframe)'

    def add_arguments(self, parser):
        parser.add_argument(
            '--months',
            type=int,
            default=12,
            help='Number of months of historical data to generate (default: 12)'
        )
        parser.add_argument(
            '--surveys-per-month',
            type=int,
            default=300,
            help='Number of surveys to generate per month (default: 300)'
        )
        parser.add_argument(
            '--clear',
            action='store_true',
            help='Clear existing survey instances before seeding'
        )

    def handle(self, *args, **options):
        months = options['months']
        surveys_per_month = options['surveys_per_month']
        clear = options['clear']
        
        self.stdout.write(self.style.SUCCESS('='*70))
        self.stdout.write(self.style.SUCCESS('SEEDING HISTORICAL SURVEY DATA'))
        self.stdout.write(self.style.SUCCESS('='*70))
        
        # Get hospital
        hospital = Hospital.objects.filter(status='active').first()
        if not hospital:
            self.stdout.write(self.style.ERROR('No active hospital found!'))
            return
        
        self.stdout.write(f'Using hospital: {hospital.name}')
        
        # Clear existing data if requested
        if clear:
            self.stdout.write('\nClearing existing survey instances...')
            deleted_count = SurveyInstance.objects.all().delete()[0]
            self.stdout.write(f'✓ Deleted {deleted_count} survey instances')
        
        # Get or create survey templates
        self.stdout.write('\nChecking survey templates...')
        templates = self.get_or_create_templates(hospital)
        self.stdout.write(f'✓ Found/created {len(templates)} survey templates')
        
        # Get patients
        patients = list(Patient.objects.all())
        if not patients:
            self.stdout.write(self.style.ERROR('No patients found! Please create patients first.'))
            return
        
        self.stdout.write(f'✓ Found {len(patients)} patients')
        
        # Generate surveys
        total_surveys = months * surveys_per_month
        self.stdout.write(f'\nGenerating {total_surveys} surveys over {months} months...\n')
        
        with transaction.atomic():
            # Generate surveys month by month
            current_date = timezone.now()
            all_surveys = []
            
            for month_offset in tqdm(range(months), desc="Generating surveys", unit="month"):
                month_date = current_date - timedelta(days=month_offset * 30)
                surveys_for_month = self.generate_monthly_surveys(
                    templates, patients, hospital, month_date, surveys_per_month
                )
                all_surveys.extend(surveys_for_month)
                
                self.stdout.write(f'\n  Generated {len(surveys_for_month)} surveys for month {month_offset + 1}')
        
        # Display summary
        self.stdout.write('\n' + '='*70)
        self.stdout.write(self.style.SUCCESS('GENERATION COMPLETE'))
        self.stdout.write('='*70)
        
        # Statistics
        completed = SurveyInstance.objects.filter(status='completed').count()
        negative = SurveyInstance.objects.filter(is_negative=True).count()
        with_comments = SurveyInstance.objects.exclude(comment='').count()
        
        # Score distribution
        self.stdout.write(f'\nTotal Surveys: {SurveyInstance.objects.count()}')
        self.stdout.write(f'Completed: {completed} ({completed/total_surveys*100:.1f}%)')
        self.stdout.write(f'Negative: {negative} ({negative/completed*100 if completed > 0 else 0:.1f}% of completed)')
        self.stdout.write(f'With Comments: {with_comments}')
        
        # By template
        self.stdout.write('\nBy Survey Template:')
        for template in templates:
            count = SurveyInstance.objects.filter(survey_template=template).count()
            avg_score = SurveyInstance.objects.filter(
                survey_template=template, 
                total_score__isnull=False
            ).aggregate(avg=Avg('total_score'))['avg']
            avg_score_display = f'{avg_score:.2f}' if avg_score else 'N/A'
            self.stdout.write(
                f'  {template.name}: {count} surveys '
                f'(avg score: {avg_score_display})'
            )
        
        self.stdout.write(self.style.SUCCESS('\n✓ Historical survey data seeded successfully!'))
    
    def get_or_create_templates(self, hospital):
        """Get or create survey templates for all patient types"""
        
        template_definitions = [
            {
                'name': 'Inpatient Post-Discharge Survey',
                'survey_type': 'stage',
                'questions': [
                    'How satisfied were you with the nursing care?',
                    'How satisfied were you with the doctor\'s care?',
                    'How clean was your room?',
                    'How satisfied were you with the food quality?',
                    'How well were you informed about your treatment?',
                    'How likely are you to recommend this hospital to others?'
                ]
            },
            {
                'name': 'OPD Patient Experience Survey',
                'survey_type': 'stage',
                'questions': [
                    'How satisfied were you with the registration process?',
                    'How satisfied were you with the waiting time?',
                    'How satisfied were you with the doctor\'s consultation?',
                    'How satisfied were you with the pharmacy service?',
                    'How likely are you to recommend this hospital to others?'
                ]
            },
            {
                'name': 'EMS Emergency Services Survey',
                'survey_type': 'stage',
                'questions': [
                    'How satisfied were you with the ambulance response time?',
                    'How satisfied were you with the paramedic care?',
                    'How satisfied were you with the emergency department care?',
                    'How satisfied were you with the communication from staff?',
                    'How likely are you to recommend this hospital to others?'
                ]
            },
            {
                'name': 'Day Case Patient Survey',
                'survey_type': 'stage',
                'questions': [
                    'How satisfied were you with the pre-procedure preparation?',
                    'How satisfied were you with the procedure itself?',
                    'How satisfied were you with the post-procedure care?',
                    'How satisfied were you with the discharge process?',
                    'How likely are you to recommend this hospital to others?'
                ]
            }
        ]
        
        templates = []
        
        for template_def in template_definitions:
            template, created = SurveyTemplate.objects.get_or_create(
                name=template_def['name'],
                hospital=hospital,
                defaults={
                    'survey_type': template_def['survey_type'],
                    'is_active': True
                }
            )
            
            # Create questions if template was just created
            if created:
                for order, question_text in enumerate(template_def['questions'], start=1):
                    question_type = 'nps' if 'recommend' in question_text.lower() else 'rating'
                    SurveyQuestion.objects.create(
                        survey_template=template,
                        text=question_text,
                        question_type=question_type,
                        order=order,
                        is_required=True
                    )
            
            templates.append(template)
        
        return templates
    
    def generate_monthly_surveys(self, templates, patients, hospital, month_date, count):
        """Generate surveys for a specific month"""
        surveys = []
        
        # Distribute surveys across the month
        for i in range(count):
            # Random day within the month
            day_offset = random.randint(0, 29)
            survey_date = month_date + timedelta(days=day_offset)
            
            # Select random template and patient
            template = random.choice(templates)
            patient = random.choice(patients)
            
            # Determine status (weighted distribution)
            status_roll = random.random()
            if status_roll < 0.85:
                status = SurveyStatus.COMPLETED
            elif status_roll < 0.95:
                status = SurveyStatus.ABANDONED
            elif status_roll < 0.98:
                status = SurveyStatus.IN_PROGRESS
            else:
                status = SurveyStatus.VIEWED
            
            # Create survey instance
            survey = SurveyInstance.objects.create(
                survey_template=template,
                patient=patient,
                hospital=hospital,
                status=status,
                sent_at=survey_date,
                delivery_channel=random.choice(['sms', 'whatsapp', 'email']),
                recipient_phone=patient.phone,
                recipient_email=patient.email,
            )
            
            # Set timestamps based on status
            if status == SurveyStatus.COMPLETED:
                survey.opened_at = survey.sent_at + timedelta(minutes=random.randint(5, 60))
                survey.completed_at = survey.opened_at + timedelta(minutes=random.randint(2, 15))
                survey.time_spent_seconds = random.randint(60, 900)
                survey.open_count = random.randint(1, 3)
                survey.last_opened_at = survey.completed_at
            elif status == SurveyStatus.ABANDONED:
                survey.opened_at = survey.sent_at + timedelta(minutes=random.randint(5, 60))
                survey.time_spent_seconds = random.randint(30, 300)
                survey.open_count = 1
                survey.last_opened_at = survey.opened_at
            elif status == SurveyStatus.IN_PROGRESS:
                survey.opened_at = survey.sent_at + timedelta(minutes=random.randint(5, 60))
                survey.open_count = random.randint(1, 2)
                survey.last_opened_at = survey.opened_at
            elif status == SurveyStatus.VIEWED:
                survey.opened_at = survey.sent_at + timedelta(minutes=random.randint(5, 60))
                survey.open_count = 1
                survey.last_opened_at = survey.opened_at
            
            survey.save()
            
            # Generate responses for completed surveys
            if status == SurveyStatus.COMPLETED:
                self.generate_survey_responses(survey, template)
                
                # Add comment for some surveys (more common for negative ones)
                comment_roll = random.random()
                should_add_comment = (
                    comment_roll < 0.25 if survey.is_negative else comment_roll < 0.15
                )
                
                if should_add_comment:
                    survey.comment = self.generate_comment(survey.is_negative)
                    survey.save(update_fields=['comment'])
                
                # Create tracking events
                self.create_tracking_events(survey)
            
            surveys.append(survey)
        
        return surveys
    
    def generate_survey_responses(self, survey, template):
        """Generate responses for a survey instance"""
        questions = template.questions.all()
        
        # Determine target score range (weighted distribution)
        score_roll = random.random()
        if score_roll < 0.35:
            # Excellent (4.5-5.0)
            min_score, max_score = 4.5, 5.0
        elif score_roll < 0.65:
            # Good (4.0-4.4)
            min_score, max_score = 4.0, 4.4
        elif score_roll < 0.85:
            # Average (3.5-3.9)
            min_score, max_score = 3.5, 3.9
        elif score_roll < 0.95:
            # Poor (3.0-3.4)
            min_score, max_score = 3.0, 3.4
        else:
            # Negative (below 3.0)
            min_score, max_score = 1.5, 2.9
        
        # Generate responses for each question
        for question in questions:
            # Generate score within target range
            if question.question_type == 'rating':
                score = round(random.uniform(min_score, max_score), 1)
                SurveyResponse.objects.create(
                    survey_instance=survey,
                    question=question,
                    numeric_value=score
                )
            elif question.question_type == 'nps':
                # NPS: 0-10 scale
                if min_score >= 4.5:
                    nps_score = random.randint(9, 10)  # Promoters
                elif min_score >= 4.0:
                    nps_score = random.randint(7, 8)  # Passive
                elif min_score >= 3.5:
                    nps_score = random.randint(5, 6)  # Passive
                elif min_score >= 3.0:
                    nps_score = random.randint(3, 4)  # Detractors
                else:
                    nps_score = random.randint(0, 2)  # Detractors
                
                SurveyResponse.objects.create(
                    survey_instance=survey,
                    question=question,
                    numeric_value=nps_score
                )
        
        # Calculate score
        score = survey.calculate_score()
    
    def create_tracking_events(self, survey):
        """Create tracking events for a survey"""
        # Page view
        SurveyTracking.objects.create(
            survey_instance=survey,
            event_type='page_view',
            user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)',
            ip_address='192.168.1.' + str(random.randint(1, 254)),
            device_type=random.choice(['mobile', 'mobile', 'desktop']),
            browser='Safari 14.0',
            created_at=survey.sent_at
        )
        
        # Survey started
        if survey.opened_at:
            SurveyTracking.objects.create(
                survey_instance=survey,
                event_type='survey_started',
                user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)',
                ip_address='192.168.1.' + str(random.randint(1, 254)),
                device_type=random.choice(['mobile', 'mobile', 'desktop']),
                browser='Safari 14.0',
                created_at=survey.opened_at,
                metadata={'referrer': 'https://wa.me/'}
            )
        
        # Survey completed
        if survey.completed_at:
            SurveyTracking.objects.create(
                survey_instance=survey,
                event_type='survey_completed',
                user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)',
                ip_address='192.168.1.' + str(random.randint(1, 254)),
                device_type=random.choice(['mobile', 'mobile', 'desktop']),
                browser='Safari 14.0',
                created_at=survey.completed_at,
                total_time_spent=survey.time_spent_seconds,
                metadata={
                    'response_count': survey.survey_template.questions.count()
                }
            )
    
    def generate_comment(self, is_negative):
        """Generate a realistic comment based on sentiment"""
        
        positive_comments = [
            "Excellent service, very satisfied with everything!",
            "Staff was very professional and caring. Great experience.",
            "Clean facilities and friendly staff. Highly recommend.",
            "The doctors and nurses were amazing. Thank you!",
            "Very good care, would definitely come back.",
            "Professional service and attentive staff.",
            "Everything was perfect, no complaints at all.",
            "Best hospital experience I've ever had.",
            "Staff went above and beyond to help me.",
            "Quick service and excellent medical care."
        ]
        
        negative_comments = [
            "The waiting time was too long, very frustrating.",
            "Staff seemed rushed and didn't explain things well.",
            "Facilities were not clean enough, needs improvement.",
            "Communication with staff was poor and confusing.",
            "Had to wait too long for test results.",
            "The staff was not very friendly or helpful.",
            "Overall experience was disappointing, needs work.",
            "Not satisfied with the level of care provided.",
            "The process was disorganized and slow.",
            "Expected better service and attention to detail."
        ]
        
        if is_negative:
            return random.choice(negative_comments)
        else:
            return random.choice(positive_comments)
