import uuid

from django.contrib.contenttypes.models import ContentType
from rest_framework import generics, status, views
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response

from hotel.models import HotelBooking

from .models import CommissionConfig, Payment, Settlement
from .serializers import CommissionConfigSerializer, PaymentSerializer, SettlementSerializer
from .utils import PaytmMock

# Dummy Credentials
MERCHANT_KEY = "mock_merchant_key"
MID = "mock_merchant_id"
WEBSITE = "WEBSTAGING"
INDUSTRY_TYPE_ID = "Retail"
CHANNEL_ID = "WEB"
CALLBACK_URL = "http://localhost:8000/api/payments/callback/"  # Adjust port if needed


class InitiatePaymentView(views.APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        booking_id = request.data.get('booking_id')
        if not booking_id:
            return Response({"error": "booking_id is required"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            booking = HotelBooking.objects.get(id=booking_id, user=request.user)
        except HotelBooking.DoesNotExist:
            return Response({"error": "Booking not found"}, status=status.HTTP_404_NOT_FOUND)
            
        # Create Payment Record
        order_id = str(uuid.uuid4())
        amount = booking.total_amount
        
        payment = Payment.objects.create(
            content_type=ContentType.objects.get_for_model(HotelBooking),
            object_id=booking.id,
            amount=amount,
            transaction_id=order_id,
            payment_method="Paytm-Mock",
            status="pending"
        )

        # Prepare Payload for Paytm
        param_dict = {
            'MID': MID,
            'ORDER_ID': order_id,
            'CUST_ID': str(request.user.id),
            'TXN_AMOUNT': str(amount),
            'CHANNEL_ID': CHANNEL_ID,
            'INDUSTRY_TYPE_ID': INDUSTRY_TYPE_ID,
            'WEBSITE': WEBSITE,
            'CALLBACK_URL': CALLBACK_URL,
        }
        
        checksum = PaytmMock.generate_checksum(param_dict, MERCHANT_KEY)
        param_dict['CHECKSUMHASH'] = checksum
        
        return Response(param_dict, status=status.HTTP_200_OK)


class PaymentCallbackView(views.APIView):
    permission_classes = [AllowAny]  # Callback comes from Paytm, so no Auth header

    def post(self, request):
        data = request.data
        checksum = data.get('CHECKSUMHASH')
        
        # Verify Checksum
        is_valid = PaytmMock.verify_checksum(data, MERCHANT_KEY, checksum)
        
        transaction_id = data.get('ORDER_ID')
        resp_code = data.get('RESPCODE')
        
        try:
            payment = Payment.objects.get(transaction_id=transaction_id)
        except Payment.DoesNotExist:
            return Response({"error": "Invalid Order ID"}, status=status.HTTP_400_BAD_REQUEST)

        if is_valid and resp_code == '01': # 01 is usually success in Paytm
            payment.status = 'completed'
            payment.save()
            
            # Update Booking
            booking = payment.content_object
            if booking:
                booking.status = 'confirmed'
                booking.save()
                
            return Response({"status": "TXN_SUCCESS", "message": "Payment Successful"}, status=status.HTTP_200_OK)
        else:
            payment.status = 'failed'
            payment.save()
            return Response({"status": "TXN_FAILURE", "message": "Payment Failed"}, status=status.HTTP_400_BAD_REQUEST)


class SettlementListView(generics.ListAPIView):
    """
    List all settlements for the hotels owned by the authenticated user.
    Admins can see all settlements.
    """
    serializer_class = SettlementSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        if user.is_staff or user.is_superuser:
            return Settlement.objects.all().order_by('-created_at')
        return Settlement.objects.filter(hotel__owner=user).order_by('-created_at')


class SettlementDetailView(generics.RetrieveAPIView):
    """
    Retrieve specific settlement details.
    """
    serializer_class = SettlementSerializer
    permission_classes = [IsAuthenticated]
    lookup_field = 'id'

    def get_queryset(self):
        user = self.request.user
        if user.is_staff or user.is_superuser:
            return Settlement.objects.all()
        return Settlement.objects.filter(hotel__owner=user)


class CommissionConfigAPIView(generics.RetrieveUpdateAPIView):
    """
    Retrieve or Update Commission Config.
    Only Admins can update. Hotel owners can only retrieve their own.
    """
    serializer_class = CommissionConfigSerializer
    permission_classes = [IsAuthenticated]
    
    def get_object(self):
        hotel_id = self.kwargs.get('hotel_id')
        user = self.request.user
        
        # Check permissions
        if not (user.is_staff or user.is_superuser):
            from hotel.models import Hotel
            try:
                hotel = Hotel.objects.get(id=hotel_id, owner=user)
            except Hotel.DoesNotExist:
                from rest_framework.exceptions import PermissionDenied
                raise PermissionDenied("You do not own this hotel")
                
        config, created = CommissionConfig.objects.get_or_create(
            hotel_id=hotel_id,
            defaults={'percentage': 15.00}
        )
        return config

    def update(self, request, *args, **kwargs):
        if not (request.user.is_staff or request.user.is_superuser):
            return Response({"detail": "Only admins can update commission config"}, status=status.HTTP_403_FORBIDDEN)
        return super().update(request, *args, **kwargs)

class ProcessSettlementView(views.APIView):
    """
    Process a settlement (Admin only).
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, id):
        user = request.user
        if not (user.is_staff or user.is_superuser):
            return Response({"detail": "Only admins can process settlements"}, status=status.HTTP_403_FORBIDDEN)

        try:
            settlement = Settlement.objects.get(id=id)
        except Settlement.DoesNotExist:
            return Response({"error": "Settlement not found"}, status=status.HTTP_404_NOT_FOUND)

        if settlement.status == 'processed':
            return Response({"error": "Settlement is already processed"}, status=status.HTTP_400_BAD_REQUEST)

        # Mark as processed
        settlement.status = 'processed'
        settlement.save()
        
        return Response({"status": "SUCCESS", "message": "Settlement processed successfully"}, status=status.HTTP_200_OK)

