"""
Generate Monthly KPI Reports

This command generates KPI reports for the previous month (or specified month)
for all active hospitals. Should be run monthly via cron job.

Usage:
    # Generate for previous month
    python manage.py generate_monthly_kpi_reports
    
    # Generate for specific month
    python manage.py generate_monthly_kpi_reports --year 2024 --month 12
    
    # Generate for specific hospital
    python manage.py generate_monthly_kpi_reports --hospital-id <uuid>
    
    # Generate specific report type
    python manage.py generate_monthly_kpi_reports --report-type resolution_72h
    
    # Dry run (don't save)
    python manage.py generate_monthly_kpi_reports --dry-run
"""
import logging
from datetime import datetime

from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone

from apps.analytics.kpi_models import KPIReportType
from apps.analytics.kpi_service import KPICalculationService
from apps.organizations.models import Hospital

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = "Generate monthly KPI reports for all hospitals"

    def add_arguments(self, parser):
        parser.add_argument(
            '--year',
            type=int,
            help='Year to generate report for (default: previous month year)'
        )
        parser.add_argument(
            '--month',
            type=int,
            help='Month to generate report for (default: previous month)'
        )
        parser.add_argument(
            '--hospital-id',
            type=str,
            help='Generate report for specific hospital only'
        )
        parser.add_argument(
            '--report-type',
            type=str,
            choices=[rt[0] for rt in KPIReportType.choices],
            help='Generate specific report type only'
        )
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Show what would be generated without saving'
        )
        parser.add_argument(
            '--force',
            action='store_true',
            help='Regenerate even if report already exists'
        )

    def handle(self, *args, **options):
        # Determine year and month
        if options['year'] and options['month']:
            year = options['year']
            month = options['month']
        else:
            # Default to previous month
            today = timezone.now()
            if today.month == 1:
                year = today.year - 1
                month = 12
            else:
                year = today.year
                month = today.month - 1

        self.stdout.write(
            self.style.NOTICE(f'Generating KPI reports for {year}-{month:02d}')
        )

        # Get hospitals
        if options['hospital_id']:
            try:
                hospitals = Hospital.objects.filter(id=options['hospital_id'])
                if not hospitals.exists():
                    raise CommandError(f'Hospital with ID {options["hospital_id"]} not found')
            except Exception as e:
                raise CommandError(f'Invalid hospital ID: {e}')
        else:
            hospitals = Hospital.objects.filter(status='active')

        # Get report types
        if options['report_type']:
            report_types = [options['report_type']]
        else:
            report_types = [rt[0] for rt in KPIReportType.choices]

        # Statistics
        stats = {
            'created': 0,
            'updated': 0,
            'skipped': 0,
            'failed': 0,
        }

        # Generate reports
        for hospital in hospitals:
            self.stdout.write(f'\nProcessing hospital: {hospital.name}')

            for report_type in report_types:
                report_type_display = dict(KPIReportType.choices)[report_type]

                # Check if report already exists
                from apps.analytics.kpi_models import KPIReport
                existing = KPIReport.objects.filter(
                    report_type=report_type,
                    hospital=hospital,
                    year=year,
                    month=month
                ).first()

                if existing and not options['force']:
                    self.stdout.write(
                        f'  - {report_type_display}: Already exists (skipping)'
                    )
                    stats['skipped'] += 1
                    continue

                if options['dry_run']:
                    self.stdout.write(
                        self.style.SUCCESS(f'  - {report_type_display}: Would generate (dry run)')
                    )
                    continue

                try:
                    # Generate the report
                    report = KPICalculationService.generate_monthly_report(
                        report_type=report_type,
                        hospital=hospital,
                        year=year,
                        month=month,
                        generated_by=None  # Automated generation
                    )

                    if existing:
                        self.stdout.write(
                            self.style.SUCCESS(f'  - {report_type_display}: Regenerated')
                        )
                        stats['updated'] += 1
                    else:
                        self.stdout.write(
                            self.style.SUCCESS(f'  - {report_type_display}: Created')
                        )
                        stats['created'] += 1

                except Exception as e:
                    self.stdout.write(
                        self.style.ERROR(f'  - {report_type_display}: Failed - {str(e)}')
                    )
                    stats['failed'] += 1
                    logger.exception(f"Failed to generate {report_type} for {hospital.name}")

        # Summary
        self.stdout.write('\n' + '=' * 50)
        self.stdout.write(self.style.NOTICE('Summary:'))
        self.stdout.write(f'  Created:  {stats["created"]}')
        self.stdout.write(f'  Updated:  {stats["updated"]}')
        self.stdout.write(f'  Skipped:  {stats["skipped"]}')
        self.stdout.write(f'  Failed:   {stats["failed"]}')

        if stats['failed'] > 0:
            raise CommandError('Some reports failed to generate')
