"""
Physicians API Views - Doctor Rating Import

API endpoints for HIS integration and manual rating import.
"""
import logging

from django.shortcuts import get_object_or_404
from rest_framework import status, serializers
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication

from apps.accounts.permissions import IsPXAdminOrHospitalAdmin
from apps.core.services import AuditService
from apps.organizations.models import Hospital

from .adapter import DoctorRatingAdapter
from .models import DoctorRatingImportJob, PhysicianIndividualRating
from .tasks import process_doctor_rating_job, aggregate_monthly_ratings_task

logger = logging.getLogger(__name__)


# ============================================================================
# Serializers
# ============================================================================

class DoctorRatingImportSerializer(serializers.Serializer):
    """Serializer for single doctor rating import via API."""
    uhid = serializers.CharField(required=True, help_text="Patient UHID/MRN")
    patient_name = serializers.CharField(required=True)
    gender = serializers.CharField(required=False, allow_blank=True)
    age = serializers.CharField(required=False, allow_blank=True)
    nationality = serializers.CharField(required=False, allow_blank=True)
    mobile_no = serializers.CharField(required=False, allow_blank=True)
    patient_type = serializers.CharField(required=False, allow_blank=True, help_text="IP, OP, ER, DC")
    admit_date = serializers.CharField(required=False, allow_blank=True, help_text="Format: DD-MMM-YYYY HH:MM:SS")
    discharge_date = serializers.CharField(required=False, allow_blank=True, help_text="Format: DD-MMM-YYYY HH:MM:SS")
    doctor_name = serializers.CharField(required=True, help_text="Format: ID-NAME (e.g., '10738-OMAYMAH YAQOUB')")
    rating = serializers.IntegerField(required=True, min_value=1, max_value=5)
    feedback = serializers.CharField(required=False, allow_blank=True)
    rating_date = serializers.CharField(required=True, help_text="Format: DD-MMM-YYYY HH:MM:SS")
    department = serializers.CharField(required=False, allow_blank=True)


class BulkDoctorRatingImportSerializer(serializers.Serializer):
    """Serializer for bulk doctor rating import via API."""
    hospital_id = serializers.UUIDField(required=True)
    ratings = DoctorRatingImportSerializer(many=True, required=True)
    source_reference = serializers.CharField(required=False, allow_blank=True, help_text="Reference ID from HIS system")


class DoctorRatingResponseSerializer(serializers.Serializer):
    """Serializer for doctor rating import response."""
    success = serializers.BooleanField()
    rating_id = serializers.UUIDField(required=False)
    message = serializers.CharField(required=False)
    staff_matched = serializers.BooleanField(required=False)
    staff_id = serializers.UUIDField(required=False)


# ============================================================================
# API Endpoints
# ============================================================================

@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def import_single_rating(request):
    """
    Import a single doctor rating from HIS.
    
    POST /api/physicians/ratings/import/single/
    
    Expected payload:
    {
        "hospital_id": "uuid",
        "uhid": "ALHH.0030223126",
        "patient_name": "Tamam Saud Aljunaybi",
        "gender": "Female",
        "age": "36 Years",
        "nationality": "Saudi Arabia",
        "mobile_no": "0504884011",
        "patient_type": "OP",
        "admit_date": "22-Dec-2024 19:12:24",
        "discharge_date": "",
        "doctor_name": "10738-OMAYMAH YAQOUB ELAMEIAN",
        "rating": 5,
        "feedback": "Great service",
        "rating_date": "28-Dec-2024 22:31:29",
        "department": "ACCIDENT AND EMERGENCY"
    }
    
    Returns:
    {
        "success": true,
        "rating_id": "uuid",
        "message": "Rating imported successfully",
        "staff_matched": true,
        "staff_id": "uuid"
    }
    """
    try:
        # Validate request data
        serializer = DoctorRatingImportSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {'success': False, 'errors': serializer.errors},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        data = serializer.validated_data
        
        # Get hospital
        hospital_id = request.data.get('hospital_id')
        if not hospital_id:
            return Response(
                {'success': False, 'message': 'hospital_id is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        hospital = get_object_or_404(Hospital, id=hospital_id)
        
        # Check permission
        user = request.user
        if not user.is_px_admin() and user.hospital != hospital:
            return Response(
                {'success': False, 'message': 'Permission denied for this hospital'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Process the rating
        result = DoctorRatingAdapter.process_single_rating(
            data=data,
            hospital=hospital,
            source=PhysicianIndividualRating.RatingSource.HIS_API
        )
        
        # Log audit
        if result['success']:
            AuditService.log_event(
                event_type='doctor_rating_import',
                description=f"Doctor rating imported for {data.get('doctor_name')}",
                user=user,
                metadata={
                    'hospital': hospital.name,
                    'doctor_name': data.get('doctor_name'),
                    'rating': data.get('rating'),
                    'staff_matched': result['staff_matched']
                }
            )
            return Response(result, status=status.HTTP_201_CREATED)
        else:
            return Response(result, status=status.HTTP_400_BAD_REQUEST)
        
    except Exception as e:
        logger.error(f"Error importing doctor rating: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def import_bulk_ratings(request):
    """
    Import multiple doctor ratings from HIS (background processing).
    
    POST /api/physicians/ratings/import/bulk/
    
    Expected payload:
    {
        "hospital_id": "uuid",
        "source_reference": "HIS_BATCH_20240115_001",
        "ratings": [
            {
                "uhid": "ALHH.0030223126",
                "patient_name": "Tamam Saud Aljunaybi",
                "doctor_name": "10738-OMAYMAH YAQOUB ELAMEIAN",
                "rating": 5,
                "rating_date": "28-Dec-2024 22:31:29",
                ...
            },
            ...
        ]
    }
    
    Returns:
    {
        "success": true,
        "job_id": "uuid",
        "job_status": "pending",
        "message": "Bulk import job queued",
        "total_records": 150
    }
    """
    try:
        # Validate request data
        serializer = BulkDoctorRatingImportSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {'success': False, 'errors': serializer.errors},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        data = serializer.validated_data
        hospital = get_object_or_404(Hospital, id=data['hospital_id'])
        
        # Check permission
        user = request.user
        if not user.is_px_admin() and user.hospital != hospital:
            return Response(
                {'success': False, 'message': 'Permission denied for this hospital'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Create import job
        ratings = data['ratings']
        job = DoctorRatingImportJob.objects.create(
            name=f"HIS Bulk Import - {hospital.name} - {len(ratings)} records",
            status=DoctorRatingImportJob.JobStatus.PENDING,
            source=DoctorRatingImportJob.JobSource.HIS_API,
            created_by=user,
            hospital=hospital,
            total_records=len(ratings),
            raw_data=[dict(r) for r in ratings],
            results={'source_reference': data.get('source_reference', '')}
        )
        
        # Queue background task
        process_doctor_rating_job.delay(str(job.id))
        
        # Log audit
        AuditService.log_event(
            event_type='doctor_rating_bulk_import',
            description=f"Bulk doctor rating import queued: {len(ratings)} records",
            user=user,
            metadata={
                'hospital': hospital.name,
                'job_id': str(job.id),
                'total_records': len(ratings),
                'source_reference': data.get('source_reference', '')
            }
        )
        
        return Response({
            'success': True,
            'job_id': str(job.id),
            'job_status': job.status,
            'message': 'Bulk import job queued for processing',
            'total_records': len(ratings)
        }, status=status.HTTP_202_ACCEPTED)
        
    except Exception as e:
        logger.error(f"Error queuing bulk doctor rating import: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def import_job_status(request, job_id):
    """
    Get status of a doctor rating import job.
    
    GET /api/physicians/ratings/import/jobs/{job_id}/
    
    Returns:
    {
        "job_id": "uuid",
        "name": "HIS Bulk Import - ...",
        "status": "completed",
        "progress_percentage": 100,
        "total_records": 150,
        "processed_count": 150,
        "success_count": 145,
        "failed_count": 5,
        "started_at": "2024-01-15T10:30:00Z",
        "completed_at": "2024-01-15T10:35:00Z",
        "duration_seconds": 300,
        "results": {...}
    }
    """
    try:
        job = get_object_or_404(DoctorRatingImportJob, id=job_id)
        
        # Check permission
        user = request.user
        if not user.is_px_admin() and job.hospital != user.hospital:
            return Response(
                {'success': False, 'message': 'Permission denied'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        return Response({
            'job_id': str(job.id),
            'name': job.name,
            'status': job.status,
            'progress_percentage': job.progress_percentage,
            'total_records': job.total_records,
            'processed_count': job.processed_count,
            'success_count': job.success_count,
            'failed_count': job.failed_count,
            'skipped_count': job.skipped_count,
            'is_complete': job.is_complete,
            'started_at': job.started_at,
            'completed_at': job.completed_at,
            'duration_seconds': job.duration_seconds,
            'results': job.results,
            'error_message': job.error_message
        })
        
    except Exception as e:
        logger.error(f"Error getting import job status: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def import_job_list(request):
    """
    List doctor rating import jobs for the user's hospital.
    
    GET /api/physicians/ratings/import/jobs/?hospital_id={uuid}&limit=50
    
    Returns list of jobs with status and progress.
    """
    try:
        user = request.user
        hospital_id = request.query_params.get('hospital_id')
        limit = int(request.query_params.get('limit', 50))
        
        # Build queryset
        queryset = DoctorRatingImportJob.objects.all()
        
        if not user.is_px_admin():
            if user.hospital:
                queryset = queryset.filter(hospital=user.hospital)
            else:
                queryset = queryset.filter(created_by=user)
        
        if hospital_id:
            queryset = queryset.filter(hospital_id=hospital_id)
        
        queryset = queryset.order_by('-created_at')[:limit]
        
        jobs = []
        for job in queryset:
            jobs.append({
                'job_id': str(job.id),
                'name': job.name,
                'status': job.status,
                'source': job.source,
                'progress_percentage': job.progress_percentage,
                'total_records': job.total_records,
                'success_count': job.success_count,
                'failed_count': job.failed_count,
                'is_complete': job.is_complete,
                'created_at': job.created_at,
                'hospital_name': job.hospital.name
            })
        
        return Response({'jobs': jobs})
        
    except Exception as e:
        logger.error(f"Error listing import jobs: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['POST'])
@permission_classes([IsPXAdminOrHospitalAdmin])
def trigger_monthly_aggregation(request):
    """
    Trigger monthly aggregation of individual ratings.
    
    POST /api/physicians/ratings/aggregate/
    
    Expected payload:
    {
        "year": 2024,
        "month": 12,
        "hospital_id": "uuid"  // optional
    }
    
    Returns:
    {
        "success": true,
        "task_id": "celery-task-id",
        "message": "Monthly aggregation queued"
    }
    """
    try:
        year = request.data.get('year')
        month = request.data.get('month')
        hospital_id = request.data.get('hospital_id')
        
        if not year or not month:
            return Response(
                {'success': False, 'message': 'year and month are required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        hospital = None
        if hospital_id:
            hospital = get_object_or_404(Hospital, id=hospital_id)
        
        # Check permission
        user = request.user
        if not user.is_px_admin():
            if hospital and hospital != user.hospital:
                return Response(
                    {'success': False, 'message': 'Permission denied'},
                    status=status.HTTP_403_FORBIDDEN
                )
            if not hospital and not user.hospital:
                return Response(
                    {'success': False, 'message': 'hospital_id required'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        
        # Queue aggregation task
        task = aggregate_monthly_ratings_task.delay(
            year=int(year),
            month=int(month),
            hospital_id=str(hospital.id) if hospital else None
        )
        
        return Response({
            'success': True,
            'task_id': task.id,
            'message': f'Monthly aggregation queued for {year}-{month:02d}'
        })
        
    except Exception as e:
        logger.error(f"Error triggering aggregation: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


# ============================================================================
# Simple HIS-compatible endpoint (similar to patient HIS endpoint)
# ============================================================================

@api_view(['POST'])
def his_doctor_rating_handler(request):
    """
    HIS Doctor Rating API Endpoint - Compatible with HIS format.
    
    This endpoint is designed to be compatible with HIS system integration,
    accepting data in the same format as the Doctor Rating Report CSV.
    
    POST /api/physicians/ratings/his/
    
    Expected payload (single or array):
    {
        "hospital_code": "ALHH",
        "ratings": [
            {
                "UHID": "ALHH.0030223126",
                "PatientName": "Tamam Saud Aljunaybi",
                "Gender": "Female",
                "Age": "36 Years",
                "Nationality": "Saudi Arabia",
                "MobileNo": "0504884011",
                "PatientType": "OP",
                "AdmitDate": "22-Dec-2024 19:12:24",
                "DischargeDate": "",
                "DoctorName": "10738-OMAYMAH YAQOUB ELAMEIAN",
                "Rating": 5,
                "Feedback": "Great service",
                "RatingDate": "28-Dec-2024 22:31:29",
                "Department": "ACCIDENT AND EMERGENCY"
            }
        ],
        "source_reference": "HIS_BATCH_001"
    }
    
    Or simplified single record:
    {
        "hospital_code": "ALHH",
        "UHID": "ALHH.0030223126",
        "PatientName": "Tamam Saud Aljunaybi",
        ...
    }
    
    Returns:
    {
        "success": true,
        "processed": 1,
        "failed": 0,
        "results": [...]
    }
    """
    try:
        data = request.data
        
        # Get hospital code
        hospital_code = data.get('hospital_code')
        if not hospital_code:
            return Response(
                {'success': False, 'message': 'hospital_code is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        try:
            hospital = Hospital.objects.get(code__iexact=hospital_code)
        except Hospital.DoesNotExist:
            return Response(
                {'success': False, 'message': f'Hospital with code {hospital_code} not found'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Normalize input to list of ratings
        if 'ratings' in data:
            ratings_list = data['ratings']
        else:
            # Single record format
            ratings_list = [data]
        
        # Map field names (HIS format -> internal format)
        field_mapping = {
            'UHID': 'uhid',
            'PatientName': 'patient_name',
            'Gender': 'gender',
            'FullAge': 'age',
            'Age': 'age',
            'Nationality': 'nationality',
            'MobileNo': 'mobile_no',
            'PatientType': 'patient_type',
            'AdmitDate': 'admit_date',
            'DischargeDate': 'discharge_date',
            'DoctorName': 'doctor_name',
            'Rating': 'rating',
            'FeedBack': 'feedback',
            'Feedback': 'feedback',
            'RatingDate': 'rating_date',
            'Department': 'department',
        }
        
        results = []
        success_count = 0
        failed_count = 0
        
        for record in ratings_list:
            # Map fields
            mapped_record = {}
            for his_field, internal_field in field_mapping.items():
                if his_field in record:
                    mapped_record[internal_field] = record[his_field]
            
            # Process the rating
            result = DoctorRatingAdapter.process_single_rating(
                data=mapped_record,
                hospital=hospital,
                source=PhysicianIndividualRating.RatingSource.HIS_API,
                source_reference=data.get('source_reference', '')
            )
            
            results.append(result)
            if result['success']:
                success_count += 1
            else:
                failed_count += 1
        
        return Response({
            'success': True,
            'processed': success_count,
            'failed': failed_count,
            'total': len(ratings_list),
            'results': results
        })
        
    except Exception as e:
        logger.error(f"Error in HIS doctor rating handler: {str(e)}", exc_info=True)
        return Response(
            {'success': False, 'message': f"Server error: {str(e)}"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
