"""
Integrations models - Inbound events from external systems

This module handles integration events from:
- HIS (Hospital Information System)
- Lab systems
- Radiology systems
- Pharmacy systems
- MOH (Ministry of Health)
- CHI (Council of Health Insurance)
- Other external systems
"""
from django.db import models

from apps.core.models import BaseChoices, TimeStampedModel, UUIDModel


class EventStatus(BaseChoices):
    """Event processing status"""
    PENDING = 'pending', 'Pending'
    PROCESSING = 'processing', 'Processing'
    PROCESSED = 'processed', 'Processed'
    FAILED = 'failed', 'Failed'
    IGNORED = 'ignored', 'Ignored'


class SourceSystem(BaseChoices):
    """Source system choices"""
    HIS = 'his', 'Hospital Information System'
    LAB = 'lab', 'Laboratory System'
    RADIOLOGY = 'radiology', 'Radiology System'
    PHARMACY = 'pharmacy', 'Pharmacy System'
    MOH = 'moh', 'Ministry of Health'
    CHI = 'chi', 'Council of Health Insurance'
    PXCONNECT = 'pxconnect', 'PX Connect'
    OTHER = 'other', 'Other'


class InboundEvent(UUIDModel, TimeStampedModel):
    """
    Inbound integration event from external systems.
    
    Events trigger journey stage completions. For example:
    - Event code: "OPD_VISIT_COMPLETED" → completes "MD Consultation" stage
    - Event code: "LAB_ORDER_COMPLETED" → completes "Lab" stage
    - Event code: "RADIOLOGY_REPORT_FINALIZED" → completes "Radiology" stage
    - Event code: "PHARMACY_DISPENSED" → completes "Pharmacy" stage
    
    Processing flow:
    1. Event received via API (POST /api/integrations/events/)
    2. Stored with status=PENDING
    3. Celery task processes event:
       a. Find journey instance by encounter_id
       b. Find matching stage by trigger_event_code
       c. Complete the stage
       d. Create survey instance if configured
       e. Update event status to PROCESSED
    """
    
    # Source information
    source_system = models.CharField(
        max_length=50,
        choices=SourceSystem.choices,
        db_index=True,
        help_text="System that sent this event"
    )
    event_code = models.CharField(
        max_length=100,
        db_index=True,
        help_text="Event type code (e.g., OPD_VISIT_COMPLETED, LAB_ORDER_COMPLETED)"
    )
    
    # Identifiers
    encounter_id = models.CharField(
        max_length=100,
        db_index=True,
        help_text="Encounter ID from HIS system"
    )
    patient_identifier = models.CharField(
        max_length=100,
        blank=True,
        db_index=True,
        help_text="Patient MRN or other identifier"
    )
    
    # Event data
    payload_json = models.JSONField(
        help_text="Full event payload from source system"
    )
    
    # Processing status
    status = models.CharField(
        max_length=20,
        choices=EventStatus.choices,
        default=EventStatus.PENDING,
        db_index=True
    )
    
    # Timestamps
    received_at = models.DateTimeField(auto_now_add=True, db_index=True)
    processed_at = models.DateTimeField(null=True, blank=True)
    
    # Processing results
    error = models.TextField(
        blank=True,
        help_text="Error message if processing failed"
    )
    processing_attempts = models.IntegerField(
        default=0,
        help_text="Number of processing attempts"
    )
    
    # Extracted context (from payload)
    physician_license = models.CharField(
        max_length=100,
        blank=True,
        help_text="Physician license number from event"
    )
    department_code = models.CharField(
        max_length=50,
        blank=True,
        help_text="Department code from event"
    )
    
    # Metadata
    metadata = models.JSONField(
        default=dict,
        blank=True,
        help_text="Additional processing metadata"
    )
    
    class Meta:
        ordering = ['-received_at']
        indexes = [
            models.Index(fields=['status', '-received_at']),
            models.Index(fields=['encounter_id', 'event_code']),
            models.Index(fields=['source_system', '-received_at']),
        ]
    
    def __str__(self):
        return f"{self.source_system} - {self.event_code} - {self.encounter_id} ({self.status})"
    
    def mark_processing(self):
        """Mark event as being processed"""
        self.status = EventStatus.PROCESSING
        self.processing_attempts += 1
        self.save(update_fields=['status', 'processing_attempts'])
    
    def mark_processed(self):
        """Mark event as successfully processed"""
        from django.utils import timezone
        self.status = EventStatus.PROCESSED
        self.processed_at = timezone.now()
        self.save(update_fields=['status', 'processed_at'])
    
    def mark_failed(self, error_message):
        """Mark event as failed with error message"""
        self.status = EventStatus.FAILED
        self.error = error_message
        self.save(update_fields=['status', 'error'])
    
    def mark_ignored(self, reason):
        """Mark event as ignored (e.g., no matching journey)"""
        self.status = EventStatus.IGNORED
        self.error = reason
        self.save(update_fields=['status', 'error'])


class IntegrationConfig(UUIDModel, TimeStampedModel):
    """
    Configuration for external system integrations.
    
    Stores API endpoints, credentials, and mapping rules.
    """
    name = models.CharField(max_length=200, unique=True)
    source_system = models.CharField(
        max_length=50,
        choices=SourceSystem.choices,
        unique=True
    )
    
    # Connection details
    api_url = models.URLField(blank=True, help_text="API endpoint URL")
    api_key = models.CharField(max_length=500, blank=True, help_text="API key (encrypted)")
    
    # Configuration
    is_active = models.BooleanField(default=True)
    config_json = models.JSONField(
        default=dict,
        blank=True,
        help_text="Additional configuration (event mappings, field mappings, etc.)"
    )
    
    # Metadata
    description = models.TextField(blank=True)
    last_sync_at = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        ordering = ['name']
    
    def __str__(self):
        return f"{self.name} ({self.source_system})"


class EventMapping(UUIDModel, TimeStampedModel):
    """
    Maps external event codes to internal trigger codes.
    
    Example:
    - External: "VISIT_COMPLETE" → Internal: "OPD_VISIT_COMPLETED"
    - External: "LAB_RESULT_READY" → Internal: "LAB_ORDER_COMPLETED"
    """
    integration_config = models.ForeignKey(
        IntegrationConfig,
        on_delete=models.CASCADE,
        related_name='event_mappings'
    )
    
    external_event_code = models.CharField(
        max_length=100,
        help_text="Event code from external system"
    )
    internal_event_code = models.CharField(
        max_length=100,
        help_text="Internal event code used in journey stages"
    )
    
    # Field mappings
    field_mappings = models.JSONField(
        default=dict,
        blank=True,
        help_text="Maps external field names to internal field names"
    )
    
    is_active = models.BooleanField(default=True)
    
    class Meta:
        unique_together = [['integration_config', 'external_event_code']]
        ordering = ['integration_config', 'external_event_code']
    
    def __str__(self):
        return f"{self.external_event_code} → {self.internal_event_code}"
