"""
PX Action Center views and viewsets
"""

from django.utils import timezone
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 PXAction, PXActionAttachment, PXActionLog, PXActionSLAConfig, RoutingRule
from .serializers import (
    PXActionAttachmentSerializer,
    PXActionListSerializer,
    PXActionLogSerializer,
    PXActionSerializer,
    PXActionSLAConfigSerializer,
    RoutingRuleSerializer,
)


class PXActionViewSet(viewsets.ModelViewSet):
    """
    ViewSet for PX Actions with workflow actions.

    Permissions:
    - All authenticated users can view actions
    - PX Admins and PX Employee can create/manage actions
    """

    queryset = PXAction.objects.all()
    permission_classes = [IsAuthenticated]
    filterset_fields = [
        "status",
        "source_type",
        "severity",
        "priority",
        "category",
        "hospital",
        "department",
        "assigned_to",
        "is_overdue",
        "requires_approval",
    ]
    search_fields = ["title", "description"]
    ordering_fields = ["created_at", "due_at", "severity", "escalation_level"]
    ordering = ["-created_at"]

    def get_serializer_class(self):
        """Use simplified serializer for list view"""
        if self.action == "list":
            return PXActionListSerializer
        return PXActionSerializer

    def get_queryset(self):
        """Filter actions based on user role"""
        queryset = (
            super()
            .get_queryset()
            .select_related("hospital", "department", "assigned_to", "approved_by", "closed_by", "content_type")
            .prefetch_related("logs", "attachments")
        )

        user = self.request.user

        # Source Users don't have access to PX Actions
        if user.is_source_user():
            return queryset.none()

        if user.is_px_admin():
            if hasattr(self.request, "tenant_hospital") and self.request.tenant_hospital:
                return queryset.filter(hospital=self.request.tenant_hospital)
            return queryset

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

        # Department Managers see actions for their department
        if user.is_department_manager() and user.department:
            return queryset.filter(department=user.department)

        # Others see actions for their hospital
        if user.hospital:
            return queryset.filter(hospital=user.hospital)

        return queryset.none()

    def perform_create(self, serializer):
        """Log action creation"""
        action = serializer.save()

        from apps.px_action_center.services import RoutingRuleEvaluationService

        RoutingRuleEvaluationService.evaluate_and_route(action)

        AuditService.log_from_request(
            event_type="action_created",
            description=f"PX Action created: {action.title}",
            request=self.request,
            content_object=action,
            metadata={"source_type": action.source_type, "category": action.category, "severity": action.severity},
        )

    @action(detail=True, methods=["post"])
    def assign(self, request, pk=None):
        """Assign action to user"""
        action = self.get_object()
        user_id = request.data.get("user_id")

        if not user_id:
            return Response({"error": "user_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        from apps.accounts.models import User

        try:
            user = User.objects.get(id=user_id)
            action.assigned_to = user
            action.assigned_at = timezone.now()
            action.save(update_fields=["assigned_to", "assigned_at"])

            # Create log
            PXActionLog.objects.create(
                action=action,
                log_type="assignment",
                message=f"Assigned to {user.get_full_name()}",
                created_by=request.user,
            )

            AuditService.log_from_request(
                event_type="assignment",
                description=f"Action assigned to {user.get_full_name()}",
                request=request,
                content_object=action,
            )

            return Response({"message": "Action assigned successfully"})
        except User.DoesNotExist:
            return Response({"error": "User not found"}, status=status.HTTP_404_NOT_FOUND)

    @action(detail=True, methods=["post"])
    def change_status(self, request, pk=None):
        """Change action status"""
        action = self.get_object()
        new_status = request.data.get("status")
        note = request.data.get("note", "")

        if not new_status:
            return Response({"error": "status is required"}, status=status.HTTP_400_BAD_REQUEST)

        old_status = action.status
        action.status = new_status

        # Handle status-specific logic
        if new_status == "pending_approval":
            # Check if evidence is required
            if action.requires_approval:
                evidence_count = action.attachments.filter(is_evidence=True).count()
                if evidence_count == 0:
                    return Response(
                        {"error": "Evidence is required before requesting approval"}, status=status.HTTP_400_BAD_REQUEST
                    )

        elif new_status == "approved":
            # Only PX Admins can approve
            if not request.user.is_px_admin():
                return Response({"error": "Only PX Admins can approve actions"}, status=status.HTTP_403_FORBIDDEN)
            action.approved_by = request.user
            action.approved_at = timezone.now()

        elif new_status == "closed":
            action.closed_at = timezone.now()
            action.closed_by = request.user

        action.save()

        # Create log
        PXActionLog.objects.create(
            action=action,
            log_type="status_change",
            message=note or f"Status changed from {old_status} to {new_status}",
            created_by=request.user,
            old_status=old_status,
            new_status=new_status,
        )

        AuditService.log_from_request(
            event_type="status_change",
            description=f"Action status changed from {old_status} to {new_status}",
            request=request,
            content_object=action,
            metadata={"old_status": old_status, "new_status": new_status},
        )

        return Response({"message": "Status updated successfully"})

    @action(detail=True, methods=["post"])
    def add_note(self, request, pk=None):
        """Add note to action"""
        action = self.get_object()
        note = request.data.get("note")

        if not note:
            return Response({"error": "note is required"}, status=status.HTTP_400_BAD_REQUEST)

        # Create log
        log = PXActionLog.objects.create(action=action, log_type="note", message=note, created_by=request.user)

        serializer = PXActionLogSerializer(log)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=True, methods=["post"])
    def escalate(self, request, pk=None):
        """Manually escalate action"""
        action = self.get_object()

        # Queue escalation task
        from apps.px_action_center.tasks import escalate_action

        escalate_action.delay(str(action.id))

        return Response({"message": "Action queued for escalation"})

    @action(detail=True, methods=["post"])
    def reject(self, request, pk=None):
        """Reject action and reopen with reason"""
        action = self.get_object()
        reason = request.data.get("reason")

        if not reason:
            return Response({"error": "reason is required"}, status=status.HTTP_400_BAD_REQUEST)

        if action.status not in ["pending_approval", "approved"]:
            return Response(
                {"error": "Can only reject actions in pending_approval or approved status"},
                status=status.HTTP_400_BAD_REQUEST,
            )

        old_status = action.status
        action.status = "open"
        action.rejected_at = timezone.now()
        action.rejected_by = request.user
        action.rejection_reason = reason
        action.save()

        PXActionLog.objects.create(
            action=action,
            log_type="rejection",
            message=f"Action rejected: {reason}",
            created_by=request.user,
            old_status=old_status,
            new_status="open",
        )

        AuditService.log_from_request(
            event_type="action_rejected",
            description=f"Action rejected and reopened: {action.title}",
            request=request,
            content_object=action,
            metadata={"old_status": old_status, "reason": reason},
        )

        return Response({"message": "Action rejected and reopened successfully"})


class PXActionSLAConfigViewSet(viewsets.ModelViewSet):
    """
    ViewSet for PX Action SLA Configurations.

    Permissions:
    - Only PX Admins can manage SLA configurations
    """

    queryset = PXActionSLAConfig.objects.all()
    serializer_class = PXActionSLAConfigSerializer
    permission_classes = [IsPXAdmin]
    filterset_fields = ["hospital", "department", "is_active"]
    search_fields = ["name"]
    ordering = ["hospital", "name"]

    def get_queryset(self):
        return super().get_queryset().select_related("hospital", "department")


class RoutingRuleViewSet(viewsets.ModelViewSet):
    """
    ViewSet for Routing Rules.

    Permissions:
    - Only PX Admins can manage routing rules
    """

    queryset = RoutingRule.objects.all()
    serializer_class = RoutingRuleSerializer
    permission_classes = [IsPXAdmin]
    filterset_fields = ["source_type", "severity", "hospital", "is_active"]
    search_fields = ["name", "description"]
    ordering = ["-priority", "name"]

    def get_queryset(self):
        return super().get_queryset().select_related("hospital", "department", "assign_to_user", "assign_to_department")
