# payments/views.py
# payments/views.py

from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
from django.utils import timezone
from django.db import IntegrityError
from .models import Payment
from .serializers import PaymentSerializer
from users.models import User
from users.permissions import IsCustomer, IsDriver, IsAdminOrManager
from notifications.utils import send_notification


class PaymentCreateView(generics.CreateAPIView):
    serializer_class = PaymentSerializer
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        order = serializer.validated_data.get("order")
        method = serializer.validated_data.get("method")
        screenshot = serializer.validated_data.get("screenshot", None)
        if screenshot is None:
            screenshot = (
                request.FILES.get("screenshot")
                or request.FILES.get("paymentScreenshot")
                or request.FILES.get("proof")
            )

        user_role = str(getattr(request.user, "role", "")).upper()
        if user_role == "CUSTOMER" and order and getattr(order, "customer_id", None) != request.user.id:
            return Response(
                {"error": "You can only submit payment for your own orders."},
                status=status.HTTP_403_FORBIDDEN,
            )

        existing = Payment.objects.filter(order=order).first()
        if existing:
            if method:
                existing.method = method
            if screenshot is not None:
                existing.screenshot = screenshot
            elif existing.method == "BANK" and not existing.screenshot:
                return Response(
                    {"error": "Payment screenshot is required for bank transfer."},
                    status=status.HTTP_400_BAD_REQUEST,
                )

            if existing.method == "BANK":
                existing.status = "PENDING"
                existing.paid_at = timezone.now()
            elif existing.method == "CASH":
                existing.status = "PENDING"
                existing.paid_at = None

            existing.save()
            return Response(PaymentSerializer(existing).data, status=status.HTTP_200_OK)

        if method == "BANK" and screenshot is None:
            return Response(
                {"error": "Payment screenshot is required for bank transfer."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            if method == "BANK":
                if screenshot is not None:
                    payment = serializer.save(status="PENDING", paid_at=timezone.now(), screenshot=screenshot)
                else:
                    payment = serializer.save(status="PENDING", paid_at=timezone.now())
            elif method == "CASH":
                payment = serializer.save(status="PENDING")
            else:
                payment = serializer.save()
        except IntegrityError:
            return Response(
                {"error": "Payment for this order already exists."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        data = PaymentSerializer(payment).data
        headers = self.get_success_headers(data)
        return Response(data, status=status.HTTP_201_CREATED, headers=headers)


class DriverPaymentUpdateView(generics.UpdateAPIView):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer
    permission_classes = [IsAuthenticated]

    def update(self, request, *args, **kwargs):
        payment = self.get_object()

        if payment.method != "CASH":
            return Response(
                {"error": "Driver can only update CASH payments"},
                status=status.HTTP_400_BAD_REQUEST
            )

        payment.status = "CASH_COLLECTED"
        payment.paid_at = timezone.now()
        payment.save()
        send_notification(
            payment.order.customer,
            "Paid by Cash",
            f"Order #{payment.order.id} was paid by cash.",
            order_id=payment.order.id,
        )
        for manager in User.objects.filter(role__in=["ADMIN", "MANAGER"]):
            send_notification(
                manager,
                "Cash Collected",
                f"Order #{payment.order.id} was marked paid on cash by driver.",
                order_id=payment.order.id,
            )

        return Response({"message": "Cash payment collected successfully"})
    
    
class PaymentListView(generics.ListAPIView):
    serializer_class = PaymentSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
      user = self.request.user

      if user.role in ['ADMIN', 'MANAGER']:
        return Payment.objects.all()

      elif user.role == 'CUSTOMER':
        return Payment.objects.filter(order__customer=user)

      elif user.role == 'DRIVER':
        return Payment.objects.filter(order__order_type='DELIVERY')

      return Payment.objects.none()
    
class AdminPaymentVerifyView(generics.UpdateAPIView):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer
    permission_classes = [IsAuthenticated]

    def update(self, request, *args, **kwargs):
        payment = self.get_object()

        if payment.method == "BANK":
            payment.status = "PAID"
        elif payment.method == "CASH":
            payment.status = "CASH_COLLECTED"
        else:
            return Response(
                {"error": "Unsupported payment method"},
                status=status.HTTP_400_BAD_REQUEST
            )
        payment.paid_at = timezone.now()
        payment.save()
        if payment.status == "CASH_COLLECTED":
            send_notification(
                payment.order.customer,
                "Paid by Cash",
                f"Order #{payment.order.id} was paid by cash.",
                order_id=payment.order.id,
            )
        return Response({"message": "Payment updated successfully"})
