from django.db.models import Q
from django.shortcuts import get_object_or_404
from rest_framework import permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from api_core.application import mutation
from api_core.pagination import limited
from api_core.permissions import can_manage_club, is_platform_admin
from .api_serializers import ApprovalSerializer, CompleteSerializer, RejectSerializer, TransferCreateSerializer, TransferSerializer, TransferWindowSerializer, WindowCreateSerializer
from .exceptions import TransferError, TransferWindowError
from .models import Transfer, TransferWindow
from .services import TransferApprovalService, TransferLifecycleService, TransferService, TransferWindowService


def _participant(user, transfer):
    return is_platform_admin(user) or transfer.player.career.user_id == user.pk or (transfer.source_club_id and can_manage_club(user, transfer.source_club)) or can_manage_club(user, transfer.destination_club)


class TransferWindowListCreateAPIView(APIView):
    permission_classes=[permissions.IsAuthenticated]
    def get(self, request):
        qs=TransferWindow.objects.select_related("season").order_by("-season__year","start_at")
        return limited(request,qs,TransferWindowSerializer)
    def post(self, request):
        if not is_platform_admin(request.user): return Response({"detail":"Platform administration permission required."},status=403)
        s=WindowCreateSerializer(data=request.data); s.is_valid(raise_exception=True)
        return mutation(request=request,scope="transfers.window.create",operation=lambda:TransferWindowService.create_window(**s.validated_data),serialize=lambda x:TransferWindowSerializer(x).data,success_status=201,domain_errors=(TransferWindowError,))


class TransferWindowActionAPIView(APIView):
    permission_classes=[permissions.IsAuthenticated]
    def post(self,request,window_id,action):
        if not is_platform_admin(request.user): return Response({"detail":"Platform administration permission required."},status=403)
        actions={"open":TransferWindowService.open_window,"close":TransferWindowService.close_window,"cancel":TransferWindowService.cancel_window}
        if action not in actions:return Response({"detail":"Unknown action."},status=404)
        return mutation(request=request,scope=f"transfers.window.{window_id}.{action}",operation=lambda:actions[action](window_id=window_id),serialize=lambda x:TransferWindowSerializer(x).data,domain_errors=(TransferWindowError,))


class TransferListCreateAPIView(APIView):
    permission_classes=[permissions.IsAuthenticated]
    def get(self,request):
        qs=Transfer.objects.select_related("player__career__user","source_club__coach_career__user","source_club__ownership_record__owner","destination_club__coach_career__user","destination_club__ownership_record__owner","window__season").prefetch_related("party_approvals").order_by("-created_at")
        if not is_platform_admin(request.user):
            qs=qs.filter(Q(player__career__user=request.user)|Q(source_club__ownership_record__owner=request.user)|Q(source_club__coach_career__user=request.user)|Q(destination_club__ownership_record__owner=request.user)|Q(destination_club__coach_career__user=request.user)).distinct()
        return limited(request,qs,TransferSerializer)
    def post(self,request):
        s=TransferCreateSerializer(data=request.data); s.is_valid(raise_exception=True)
        d=s.validated_data; player=d["player"]; source=d.get("source_club"); destination=d["destination_club"]
        if not (is_platform_admin(request.user) or player.career.user_id==request.user.pk or (source and can_manage_club(request.user,source)) or can_manage_club(request.user,destination)):
            return Response({"detail":"Only a transfer participant may create this workflow."},status=403)
        return mutation(request=request,scope="transfers.create",operation=lambda:TransferService.create_transfer(**d),serialize=lambda x:TransferSerializer(x).data,success_status=201,domain_errors=(TransferError,))


class TransferDetailAPIView(APIView):
    permission_classes=[permissions.IsAuthenticated]
    def get(self,request,transfer_id):
        obj=get_object_or_404(Transfer.objects.select_related("player__career__user","source_club__coach_career__user","source_club__ownership_record__owner","destination_club__coach_career__user","destination_club__ownership_record__owner","window__season").prefetch_related("party_approvals"),pk=transfer_id)
        if not _participant(request.user,obj):return Response({"detail":"Not authorized."},status=403)
        return Response(TransferSerializer(obj).data)


class TransferActionAPIView(APIView):
    permission_classes=[permissions.IsAuthenticated]
    def post(self,request,transfer_id,action):
        obj=get_object_or_404(Transfer.objects.select_related("player__career__user","source_club__coach_career__user","source_club__ownership_record__owner","destination_club__coach_career__user","destination_club__ownership_record__owner","window__season"),pk=transfer_id)
        if not _participant(request.user,obj):return Response({"detail":"Not authorized."},status=403)
        if action=="approve-party":
            if obj.contract_terms is None:
                return Response({"detail":"Legacy transfer lacks agreed employment terms; cancel and recreate the proposal with contract_terms."},status=400)
            s=ApprovalSerializer(data=request.data);s.is_valid(raise_exception=True)
            op=lambda:TransferApprovalService.approve_party(transfer_id=transfer_id,role=s.validated_data["role"],actor=request.user)
        elif action=="reject":
            s=RejectSerializer(data=request.data);s.is_valid(raise_exception=True)
            op=lambda:TransferLifecycleService.reject_transfer(transfer_id=transfer_id,reason=s.validated_data["reason"])
        elif action=="cancel":
            op=lambda:TransferLifecycleService.cancel_transfer(transfer_id=transfer_id)
        elif action=="complete":
            if not (is_platform_admin(request.user) or can_manage_club(request.user,obj.destination_club)):
                return Response({"detail":"Destination club management permission required."},status=403)
            s=CompleteSerializer(data=request.data);s.is_valid(raise_exception=True)
            op=lambda:TransferLifecycleService.complete_transfer(transfer_id=transfer_id,**s.validated_data)
        else:return Response({"detail":"Unknown action."},status=404)
        return mutation(request=request,scope=f"transfers.transfer.{transfer_id}.{action}",operation=op,serialize=lambda x:TransferSerializer(x).data,domain_errors=(TransferError,TransferWindowError))
