"""
Integrations views and viewsets
"""
import logging

from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apps.accounts.permissions import IsPXAdmin
from apps.core.services import AuditService

from .models import EventMapping, InboundEvent, IntegrationConfig
from .serializers import (
    EventMappingSerializer,
    InboundEventCreateSerializer,
    InboundEventListSerializer,
    InboundEventSerializer,
    IntegrationConfigSerializer,
)

logger = logging.getLogger('apps.integrations')


class InboundEventViewSet(viewsets.ModelViewSet):
    """
    ViewSet for Inbound Events.
    
    This is the main integration endpoint where external systems
    send events to trigger journey stage completions.
    
    POST /api/integrations/events/ - Create new event
    GET /api/integrations/events/ - List events (admin only)
    """
    queryset = InboundEvent.objects.all()
    permission_classes = [IsAuthenticated]
    filterset_fields = ['status', 'source_system', 'event_code', 'encounter_id']
    search_fields = ['encounter_id', 'patient_identifier', 'event_code']
    ordering_fields = ['received_at', 'processed_at']
    ordering = ['-received_at']
    
    def get_serializer_class(self):
        """Return appropriate serializer based on action"""
        if self.action == 'create':
            return InboundEventCreateSerializer
        elif self.action == 'list':
            return InboundEventListSerializer
        return InboundEventSerializer
    
    def get_permissions(self):
        """
        Allow event creation with API key or JWT.
        List/retrieve requires PX Admin.
        """
        if self.action == 'create':
            # TODO: Add API key authentication for external systems
            return [IsAuthenticated()]
        return [IsPXAdmin()]
    
    def perform_create(self, serializer):
        """
        Create event and queue for processing.
        
        The event will be processed asynchronously by Celery task.
        """
        event = serializer.save()
        
        logger.info(
            f"Inbound event received: {event.source_system} - "
            f"{event.event_code} - {event.encounter_id}"
        )
        
        # Log event receipt
        AuditService.log_from_request(
            event_type='integration_event',
            description=f"Integration event received: {event.event_code} for encounter {event.encounter_id}",
            request=self.request,
            content_object=event,
            metadata={
                'source_system': event.source_system,
                'event_code': event.event_code,
                'encounter_id': event.encounter_id
            }
        )
        
        # Queue event for processing
        from apps.integrations.tasks import process_inbound_event
        process_inbound_event.delay(str(event.id))
    
    @action(detail=False, methods=['post'])
    def bulk_create(self, request):
        """
        Bulk create events.
        
        Accepts array of events:
        {
            "events": [
                {"source_system": "his", "event_code": "...", ...},
                {"source_system": "lab", "event_code": "...", ...}
            ]
        }
        """
        events_data = request.data.get('events', [])
        
        if not events_data:
            return Response(
                {'error': 'No events provided'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        created_events = []
        errors = []
        
        for event_data in events_data:
            serializer = InboundEventCreateSerializer(data=event_data)
            if serializer.is_valid():
                event = serializer.save()
                created_events.append(event)
                
                # Queue for processing
                # from apps.integrations.tasks import process_inbound_event
                # process_inbound_event.delay(str(event.id))
            else:
                errors.append({
                    'data': event_data,
                    'errors': serializer.errors
                })
        
        return Response({
            'created': len(created_events),
            'failed': len(errors),
            'errors': errors
        }, status=status.HTTP_201_CREATED if created_events else status.HTTP_400_BAD_REQUEST)
    
    @action(detail=True, methods=['post'], permission_classes=[IsPXAdmin])
    def reprocess(self, request, pk=None):
        """
        Reprocess a failed event.
        
        Only PX Admins can manually trigger reprocessing.
        """
        event = self.get_object()
        
        if event.status not in ['failed', 'ignored']:
            return Response(
                {'error': 'Only failed or ignored events can be reprocessed'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Reset status and queue for processing
        event.status = 'pending'
        event.error = ''
        event.save()
        
        # Queue for processing
        # from apps.integrations.tasks import process_inbound_event
        # process_inbound_event.delay(str(event.id))
        
        logger.info(f"Event {event.id} queued for reprocessing")
        
        return Response({'message': 'Event queued for reprocessing'})


class IntegrationConfigViewSet(viewsets.ModelViewSet):
    """
    ViewSet for Integration Configurations.
    
    Permissions:
    - Only PX Admins can manage integration configurations
    """
    queryset = IntegrationConfig.objects.all()
    serializer_class = IntegrationConfigSerializer
    permission_classes = [IsPXAdmin]
    filterset_fields = ['source_system', 'is_active']
    search_fields = ['name', 'description']
    ordering_fields = ['name', 'created_at']
    ordering = ['name']
    
    def get_queryset(self):
        return super().get_queryset().prefetch_related('event_mappings')


class EventMappingViewSet(viewsets.ModelViewSet):
    """
    ViewSet for Event Mappings.
    
    Permissions:
    - Only PX Admins can manage event mappings
    """
    queryset = EventMapping.objects.all()
    serializer_class = EventMappingSerializer
    permission_classes = [IsPXAdmin]
    filterset_fields = ['integration_config', 'is_active']
    search_fields = ['external_event_code', 'internal_event_code']
    ordering_fields = ['external_event_code']
    ordering = ['integration_config', 'external_event_code']
    
    def get_queryset(self):
        return super().get_queryset().select_related('integration_config')
