"""
Physicians API views and viewsets
"""
from django.db.models import Avg, Count, Q
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 IsPXAdminOrHospitalAdmin
from apps.organizations.models import Staff

from .models import PhysicianMonthlyRating
from .serializers import (
    PhysicianLeaderboardSerializer,
    PhysicianMonthlyRatingSerializer,
    PhysicianPerformanceSerializer,
    PhysicianSerializer,
)


class PhysicianViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for Physicians.

    Permissions:
    - All authenticated users can view physicians
    - Filtered by hospital based on user role
    """
    queryset = Staff.objects.all()
    serializer_class = PhysicianSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ['hospital', 'department', 'specialization', 'status']
    search_fields = ['first_name', 'last_name', 'license_number', 'specialization']
    ordering_fields = ['last_name', 'first_name', 'specialization', 'created_at']
    ordering = ['last_name', 'first_name']

    def get_queryset(self):
        """Filter physicians based on user role"""
        queryset = super().get_queryset().select_related('hospital', 'department')
        user = self.request.user

        # PX Admins see all physicians
        if user.is_px_admin():
            return queryset

        # Hospital Admins and staff see physicians for their hospital
        if user.hospital:
            return queryset.filter(hospital=user.hospital)

        return queryset.none()

    @action(detail=True, methods=['get'])
    def performance(self, request, pk=None):
        """
        Get physician performance summary.

        GET /api/physicians/{id}/performance/

        Returns:
        - Current month rating
        - Previous month rating
        - Year-to-date average
        - Best/worst months
        - Trend analysis
        """
        physician = self.get_object()

        from django.utils import timezone
        now = timezone.now()
        current_year = now.year
        current_month = now.month

        # Get current month rating
        current_month_rating = PhysicianMonthlyRating.objects.filter(
            staff=physician,
            year=current_year,
            month=current_month
        ).first()

        # Get previous month rating
        prev_month = current_month - 1 if current_month > 1 else 12
        prev_year = current_year if current_month > 1 else current_year - 1
        previous_month_rating = PhysicianMonthlyRating.objects.filter(
            staff=physician,
            year=prev_year,
            month=prev_month
        ).first()

        # Get year-to-date stats
        ytd_ratings = PhysicianMonthlyRating.objects.filter(
            staff=physician,
            year=current_year
        )

        ytd_stats = ytd_ratings.aggregate(
            avg_rating=Avg('average_rating'),
            total_surveys=Count('id')
        )

        # Get best and worst months (last 12 months)
        last_12_months = PhysicianMonthlyRating.objects.filter(
            staff=physician
        ).order_by('-year', '-month')[:12]

        best_month = last_12_months.order_by('-average_rating').first()
        worst_month = last_12_months.order_by('average_rating').first()

        # Determine trend
        trend = 'stable'
        if current_month_rating and previous_month_rating:
            if current_month_rating.average_rating > previous_month_rating.average_rating:
                trend = 'improving'
            elif current_month_rating.average_rating < previous_month_rating.average_rating:
                trend = 'declining'

        # Build response
        data = {
            'physician': PhysicianSerializer(physician).data,
            'current_month_rating': PhysicianMonthlyRatingSerializer(current_month_rating).data if current_month_rating else None,
            'previous_month_rating': PhysicianMonthlyRatingSerializer(previous_month_rating).data if previous_month_rating else None,
            'year_to_date_average': ytd_stats['avg_rating'],
            'total_surveys_ytd': ytd_stats['total_surveys'],
            'best_month': PhysicianMonthlyRatingSerializer(best_month).data if best_month else None,
            'worst_month': PhysicianMonthlyRatingSerializer(worst_month).data if worst_month else None,
            'trend': trend
        }

        serializer = PhysicianPerformanceSerializer(data)
        return Response(serializer.data)

    @action(detail=True, methods=['get'])
    def ratings_history(self, request, pk=None):
        """
        Get physician ratings history.

        GET /api/physicians/{id}/ratings_history/?months=12

        Returns monthly ratings for the specified number of months.
        """
        physician = self.get_object()
        months = int(request.query_params.get('months', 12))

        ratings = PhysicianMonthlyRating.objects.filter(
            staff=physician
        ).order_by('-year', '-month')[:months]

        serializer = PhysicianMonthlyRatingSerializer(ratings, many=True)
        return Response(serializer.data)


class PhysicianMonthlyRatingViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for Physician Monthly Ratings.

    Permissions:
    - All authenticated users can view ratings
    - Filtered by hospital based on user role
    """
    queryset = PhysicianMonthlyRating.objects.all()
    serializer_class = PhysicianMonthlyRatingSerializer
    permission_classes = [IsAuthenticated]
    filterset_fields = ['staff', 'year', 'month', 'staff__hospital', 'staff__department']
    search_fields = ['staff__first_name', 'staff__last_name', 'staff__license_number']
    ordering_fields = ['year', 'month', 'average_rating', 'total_surveys', 'hospital_rank', 'department_rank']
    ordering = ['-year', '-month', '-average_rating']

    def get_queryset(self):
        """Filter ratings based on user role"""
        queryset = super().get_queryset().select_related(
            'staff',
            'staff__hospital',
            'staff__department'
        )
        user = self.request.user

        # PX Admins see all ratings
        if user.is_px_admin():
            return queryset

        # Hospital Admins and staff see ratings for their hospital
        if user.hospital:
            return queryset.filter(staff__hospital=user.hospital)

        return queryset.none()

    @action(detail=False, methods=['get'])
    def leaderboard(self, request):
        """
        Get physician leaderboard.

        GET /api/physicians/ratings/leaderboard/?year=2024&month=12&hospital={id}&department={id}&limit=10

        Returns top-rated physicians for the specified period.
        """
        from django.utils import timezone

        # Get parameters
        year = int(request.query_params.get('year', timezone.now().year))
        month = int(request.query_params.get('month', timezone.now().month))
        hospital_id = request.query_params.get('hospital')
        department_id = request.query_params.get('department')
        limit = int(request.query_params.get('limit', 10))

        # Build queryset
        queryset = PhysicianMonthlyRating.objects.filter(
            year=year,
            month=month
        ).select_related('staff', 'staff__hospital', 'staff__department')

        # Apply RBAC filters
        user = request.user
        if not user.is_px_admin() and user.hospital:
            queryset = queryset.filter(staff__hospital=user.hospital)

        # Apply filters
        if hospital_id:
            queryset = queryset.filter(staff__hospital_id=hospital_id)

        if department_id:
            queryset = queryset.filter(staff__department_id=department_id)

        # Order by rating and limit
        queryset = queryset.order_by('-average_rating')[:limit]

        # Get previous month for trend
        prev_month = month - 1 if month > 1 else 12
        prev_year = year if month > 1 else year - 1

        # Build leaderboard data
        leaderboard = []
        for rank, rating in enumerate(queryset, start=1):
            # Get previous month rating for trend
            prev_rating = PhysicianMonthlyRating.objects.filter(
                staff=rating.staff,
                year=prev_year,
                month=prev_month
            ).first()

            trend = 'stable'
            if prev_rating:
                if rating.average_rating > prev_rating.average_rating:
                    trend = 'up'
                elif rating.average_rating < prev_rating.average_rating:
                    trend = 'down'

            leaderboard.append({
                'physician_id': rating.staff.id,
                'physician_name': rating.staff.get_full_name(),
                'physician_license': rating.staff.license_number,
                'specialization': rating.staff.specialization,
                'department_name': rating.staff.department.name if rating.staff.department else '',
                'average_rating': rating.average_rating,
                'total_surveys': rating.total_surveys,
                'rank': rank,
                'trend': trend
            })

        serializer = PhysicianLeaderboardSerializer(leaderboard, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def statistics(self, request):
        """
        Get physician rating statistics.

        GET /api/physicians/ratings/statistics/?year=2024&month=12&hospital={id}

        Returns aggregate statistics for the specified period.
        """
        from django.utils import timezone

        # Get parameters
        year = int(request.query_params.get('year', timezone.now().year))
        month = int(request.query_params.get('month', timezone.now().month))
        hospital_id = request.query_params.get('hospital')

        # Build queryset
        queryset = PhysicianMonthlyRating.objects.filter(
            year=year,
            month=month
        )

        # Apply RBAC filters
        user = request.user
        if not user.is_px_admin() and user.hospital:
            queryset = queryset.filter(staff__hospital=user.hospital)

        # Apply filters
        if hospital_id:
            queryset = queryset.filter(staff__hospital_id=hospital_id)

        # Calculate statistics
        stats = queryset.aggregate(
            total_physicians=Count('id'),
            average_rating=Avg('average_rating'),
            total_surveys=Count('total_surveys'),
            total_positive=Count('positive_count'),
            total_neutral=Count('neutral_count'),
            total_negative=Count('negative_count')
        )

        # Get distribution
        excellent = queryset.filter(average_rating__gte=4.5).count()
        good = queryset.filter(average_rating__gte=3.5, average_rating__lt=4.5).count()
        average = queryset.filter(average_rating__gte=2.5, average_rating__lt=3.5).count()
        poor = queryset.filter(average_rating__lt=2.5).count()

        return Response({
            'year': year,
            'month': month,
            'total_physicians': stats['total_physicians'],
            'average_rating': stats['average_rating'],
            'total_surveys': stats['total_surveys'],
            'distribution': {
                'excellent': excellent,  # 4.5+
                'good': good,  # 3.5-4.5
                'average': average,  # 2.5-3.5
                'poor': poor  # <2.5
            },
            'sentiment': {
                'positive': stats['total_positive'],
                'neutral': stats['total_neutral'],
                'negative': stats['total_negative']
            }
        })
