"""
Reports models - Custom Report Builder for PX360.

Supports creating, saving, and scheduling custom reports
across multiple data sources (Complaints, Inquiries, Observations, etc.)
"""
from django.conf import settings
from django.db import models
from django.utils import timezone
from apps.core.models import TimeStampedModel, UUIDModel


class DataSource(models.TextChoices):
    """Available data sources for reports."""
    COMPLAINTS = 'complaints', 'Complaints'
    INQUIRIES = 'inquiries', 'Inquiries'
    OBSERVATIONS = 'observations', 'Observations'
    PX_ACTIONS = 'px_actions', 'PX Actions'
    SURVEYS = 'surveys', 'Surveys'
    PHYSICIANS = 'physicians', 'Physician Ratings'


class ReportFrequency(models.TextChoices):
    """Report schedule frequency options."""
    ONCE = 'once', 'One Time'
    DAILY = 'daily', 'Daily'
    WEEKLY = 'weekly', 'Weekly'
    MONTHLY = 'monthly', 'Monthly'
    QUARTERLY = 'quarterly', 'Quarterly'


class ReportFormat(models.TextChoices):
    """Export format options."""
    HTML = 'html', 'View Online'
    PDF = 'pdf', 'PDF'
    EXCEL = 'excel', 'Excel'
    CSV = 'csv', 'CSV'


class ChartType(models.TextChoices):
    """Chart type options."""
    BAR = 'bar', 'Bar Chart'
    LINE = 'line', 'Line Chart'
    PIE = 'pie', 'Pie Chart'
    DONUT = 'donut', 'Donut Chart'
    AREA = 'area', 'Area Chart'
    TABLE = 'table', 'Table Only'


class SavedReport(UUIDModel, TimeStampedModel):
    """
    Saved report configuration.
    
    Stores all settings for a custom report that can be
    regenerated on demand or scheduled.
    """
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    
    # Data source
    data_source = models.CharField(
        max_length=50,
        choices=DataSource.choices,
        default=DataSource.COMPLAINTS
    )
    
    # Filter configuration (JSON)
    # Example: {"date_range": "30d", "hospital": "uuid", "status": ["open", "in_progress"]}
    filter_config = models.JSONField(default=dict, blank=True)
    
    # Column configuration (JSON)
    # Example: ["title", "status", "severity", "department__name", "created_at"]
    column_config = models.JSONField(default=list, blank=True)
    
    # Grouping configuration (JSON)
    # Example: {"field": "department__name", "aggregation": "count"}
    grouping_config = models.JSONField(default=dict, blank=True)
    
    # Sort configuration (JSON)
    # Example: [{"field": "created_at", "direction": "desc"}]
    sort_config = models.JSONField(default=list, blank=True)
    
    # Chart configuration (JSON)
    # Example: {"type": "bar", "x_axis": "department__name", "y_axis": "count"}
    chart_config = models.JSONField(default=dict, blank=True)
    
    # Owner and sharing
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='saved_reports'
    )
    is_shared = models.BooleanField(
        default=False,
        help_text="Share with other users in the same hospital"
    )
    is_template = models.BooleanField(
        default=False,
        help_text="Available as a template for others to use"
    )
    
    # Organization scope
    hospital = models.ForeignKey(
        'organizations.Hospital',
        on_delete=models.CASCADE,
        related_name='saved_reports',
        null=True,
        blank=True
    )
    
    # Metadata
    last_run_at = models.DateTimeField(null=True, blank=True)
    last_run_count = models.IntegerField(default=0)
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['data_source', '-created_at']),
            models.Index(fields=['created_by', '-created_at']),
            models.Index(fields=['hospital', 'is_shared']),
        ]
    
    def __str__(self):
        return self.name


class ReportSchedule(UUIDModel, TimeStampedModel):
    """
    Schedule for automated report generation and delivery.
    """
    report = models.ForeignKey(
        SavedReport,
        on_delete=models.CASCADE,
        related_name='schedules'
    )
    
    # Schedule settings
    frequency = models.CharField(
        max_length=20,
        choices=ReportFrequency.choices,
        default=ReportFrequency.WEEKLY
    )
    
    # Delivery time (hour:minute in 24h format)
    # Stored as "HH:MM" string
    delivery_time = models.CharField(
        max_length=5,
        default='09:00',
        help_text="Time to send report (HH:MM format)"
    )
    
    # Day of week for weekly reports (0=Monday, 6=Sunday)
    day_of_week = models.IntegerField(
        null=True,
        blank=True,
        help_text="For weekly reports: 0=Monday, 6=Sunday"
    )
    
    # Day of month for monthly reports (1-31)
    day_of_month = models.IntegerField(
        null=True,
        blank=True,
        help_text="For monthly reports: 1-31"
    )
    
    # Export format for scheduled reports
    export_format = models.CharField(
        max_length=20,
        choices=ReportFormat.choices,
        default=ReportFormat.PDF
    )
    
    # Recipients
    recipients = models.JSONField(
        default=list,
        help_text="List of email addresses to receive the report"
    )
    
    # Status
    is_active = models.BooleanField(default=True)
    last_run_at = models.DateTimeField(null=True, blank=True)
    next_run_at = models.DateTimeField(null=True, blank=True)
    last_error = models.TextField(blank=True)
    
    class Meta:
        ordering = ['next_run_at']
    
    def __str__(self):
        return f"{self.report.name} - {self.get_frequency_display()}"
    
    def save(self, *args, **kwargs):
        if self.is_active and not self.next_run_at:
            self.next_run_at = self.calculate_next_run()
        super().save(*args, **kwargs)
    
    def calculate_next_run(self):
        """Calculate the next run time based on frequency."""
        from datetime import datetime, timedelta
        
        now = timezone.now()
        hour, minute = map(int, self.delivery_time.split(':'))
        
        if self.frequency == ReportFrequency.DAILY:
            next_run = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
            if next_run <= now:
                next_run += timedelta(days=1)
            return next_run
        
        elif self.frequency == ReportFrequency.WEEKLY and self.day_of_week is not None:
            days_ahead = self.day_of_week - now.weekday()
            if days_ahead <= 0:
                days_ahead += 7
            next_run = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
            next_run += timedelta(days=days_ahead)
            return next_run
        
        elif self.frequency == ReportFrequency.MONTHLY and self.day_of_month:
            next_run = now.replace(day=min(self.day_of_month, 28), hour=hour, minute=minute, second=0, microsecond=0)
            if next_run <= now:
                if now.month == 12:
                    next_run = next_run.replace(year=now.year + 1, month=1)
                else:
                    next_run = next_run.replace(month=now.month + 1)
            return next_run
        
        return None


class GeneratedReport(UUIDModel, TimeStampedModel):
    """
    Record of a generated report instance.
    
    Stores the actual data and metadata for each report run.
    """
    saved_report = models.ForeignKey(
        SavedReport,
        on_delete=models.CASCADE,
        related_name='generated_reports',
        null=True,
        blank=True
    )
    
    # Report name (copied from saved report for standalone reports)
    name = models.CharField(max_length=200)
    data_source = models.CharField(max_length=50, choices=DataSource.choices)
    
    # Configuration snapshots
    filter_config = models.JSONField(default=dict)
    column_config = models.JSONField(default=list)
    grouping_config = models.JSONField(default=dict)
    chart_config = models.JSONField(default=dict)
    
    # Generated data
    data = models.JSONField(default=dict, help_text="The actual report data")
    summary = models.JSONField(default=dict, help_text="Summary statistics")
    chart_data = models.JSONField(default=dict, help_text="Chart-formatted data")
    
    # Row count
    row_count = models.IntegerField(default=0)
    
    # Generation metadata
    generated_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='generated_reports'
    )
    
    # Export files
    pdf_file = models.FileField(upload_to='reports/pdf/', null=True, blank=True)
    excel_file = models.FileField(upload_to='reports/excel/', null=True, blank=True)
    csv_file = models.FileField(upload_to='reports/csv/', null=True, blank=True)
    
    # Organization scope
    hospital = models.ForeignKey(
        'organizations.Hospital',
        on_delete=models.CASCADE,
        related_name='generated_reports',
        null=True,
        blank=True
    )
    
    # Expiry (auto-delete old reports)
    expires_at = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['data_source', '-created_at']),
            models.Index(fields=['generated_by', '-created_at']),
            models.Index(fields=['expires_at']),
        ]
    
    def __str__(self):
        return f"{self.name} - {self.created_at.strftime('%Y-%m-%d %H:%M')}"
    
    def is_expired(self):
        """Check if the report has expired."""
        if self.expires_at:
            return timezone.now() > self.expires_at
        return False


class ReportTemplate(UUIDModel, TimeStampedModel):
    """
    Pre-built report templates for quick access.
    
    These are system-provided templates that users can use
    as starting points for their custom reports.
    """
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    category = models.CharField(max_length=100, blank=True)
    
    # Data source
    data_source = models.CharField(
        max_length=50,
        choices=DataSource.choices,
        default=DataSource.COMPLAINTS
    )
    
    # Template configuration
    filter_config = models.JSONField(default=dict)
    column_config = models.JSONField(default=list)
    grouping_config = models.JSONField(default=dict)
    sort_config = models.JSONField(default=list)
    chart_config = models.JSONField(default=dict)
    
    # Display
    icon = models.CharField(max_length=50, blank=True, help_text="Bootstrap icon class")
    sort_order = models.IntegerField(default=0)
    is_active = models.BooleanField(default=True)
    
    class Meta:
        ordering = ['sort_order', 'name']
    
    def __str__(self):
        return self.name
    
    def create_report(self, user, overrides=None):
        """Create a SavedReport from this template."""
        from apps.reports.services import ReportBuilderService
        
        config = {
            'filter_config': self.filter_config.copy(),
            'column_config': self.column_config.copy(),
            'grouping_config': self.grouping_config.copy(),
            'sort_config': self.sort_config.copy(),
            'chart_config': self.chart_config.copy(),
        }
        
        if overrides:
            for key, value in overrides.items():
                if key in config and isinstance(config[key], dict):
                    config[key].update(value)
                else:
                    config[key] = value
        
        report = SavedReport.objects.create(
            name=f"{self.name} - {timezone.now().strftime('%Y-%m-%d')}",
            description=self.description,
            data_source=self.data_source,
            created_by=user,
            hospital=user.hospital,
            **config
        )
        return report