from rest_framework.views import APIView
from rest_framework import status
from .razorpay_serializers import RazorpayOrderSerializer, TranscationModelSerializer
from api.razorpay.main import RazorpayClient
from rest_framework.response import Response

import hmac
import hashlib
import json
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

from user.models import Plan, UserTransaction, User
from master.models import Transaction

rz_client = RazorpayClient()

class RazorpayOrderAPIView(APIView):
    """This API will create an order"""
    def post(self, request):
        serializer = RazorpayOrderSerializer(data=request.data)
        if serializer.is_valid():
            order_response = rz_client.create_order(
                amount=serializer.validated_data.get("amount"),
                currency=serializer.validated_data.get("currency")
            )
            return Response({
                "status_code": status.HTTP_201_CREATED,
                "message": "order created",
                "data": order_response
            }, status=status.HTTP_201_CREATED)
        return Response({
            "status_code": status.HTTP_400_BAD_REQUEST,
            "message": "bad request",
            "error": serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)


class TransactionAPIView(APIView):
    def post(self, request):
        serializer = TranscationModelSerializer(data=request.data)
        if serializer.is_valid():
            data = serializer.validated_data
            payment_id = data.get("payment_id")
            order_id = data.get("order_id")
            signature = data.get("signature")
            amount = data.get("amount")

            user_id = request.data.get("user")
            plan_id = request.data.get("plan")

            if not user_id or not plan_id:
                return Response({"status": "error", "message": "user_id and plan_id required."},
                                status=status.HTTP_400_BAD_REQUEST)

            try:
                rz_client.verify_payment_signature(
                    razorpay_payment_id=payment_id,
                    razorpay_order_id=order_id,
                    razorpay_signature=signature
                )
            except Exception as e:
                return Response({"status": "error", "message": "Invalid signature", "debug": str(e)},
                                status=status.HTTP_400_BAD_REQUEST)

            try:
                user = User.objects.get(id=user_id)
                plan = Plan.objects.get(id=plan_id)
            except (User.DoesNotExist, Plan.DoesNotExist):
                return Response({"status": "error", "message": "User or Plan not found"},
                                status=status.HTTP_400_BAD_REQUEST)

            serializer.save()

            UserTransaction.objects.create(
                user=user,
                plan=plan,
                coins=plan.coins,
                amount=plan.amount,
                payment_id=payment_id,
                duration="NA",
                status=3
            )

            user.available_coins += plan.coins

            if plan.type == 1:
                user.first_offer_used = True

            user.save()

            return Response({"status": "success", "message": "Transaction completed and coins updated."},
                            status=status.HTTP_201_CREATED)

        return Response({"status": "error", "message": "Invalid data", "error": serializer.errors},
                        status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_exempt, name='dispatch')
class RazorpayWebhookAPIView(APIView):
    def post(self, request):
        webhook_secret = "harmoni"
        received_signature = request.META.get('HTTP_X_RAZORPAY_SIGNATURE')
        body = request.body.decode('utf-8')

        expected_signature = hmac.new(
            key=bytes(webhook_secret, 'utf-8'),
            msg=bytes(body, 'utf-8'),
            digestmod=hashlib.sha256
        ).hexdigest()

        if not hmac.compare_digest(received_signature, expected_signature):
            return Response({"message": "Invalid signature"}, status=status.HTTP_400_BAD_REQUEST)

        data = json.loads(body)
        event = data.get('event')

        if event == "payment.captured":
            payment_data = data.get('payload', {}).get('payment', {}).get('entity', {})
            payment_id = payment_data.get("id")
            order_id = payment_data.get("order_id")
            metadata = payment_data.get("notes", {})

            user_id = metadata.get("user_id")
            plan_id = metadata.get("plan_id")

            try:
                user = User.objects.get(id=user_id)
                plan = Plan.objects.get(id=plan_id)

                Transaction.objects.create(
                    payment_id=payment_id,
                    order_id=order_id,
                    amount=int(float(payment_data.get("amount")) / 100),
                    signature="(Webhook)"
                )

                UserTransaction.objects.create(
                    user=user,
                    plan=plan,
                    coins=plan.coins,
                    amount=plan.amount,
                    payment_id=payment_id,
                    duration="NA",
                    status=3
                )

                user.available_coins += plan.coins

                if plan.type == 1:
                    user.first_offer_used = True

                user.save()

                return Response({"message": "Transaction completed and coins updated."}, status=status.HTTP_200_OK)

            except (User.DoesNotExist, Plan.DoesNotExist):
                return Response({"message": "User or Plan not found."}, status=status.HTTP_400_BAD_REQUEST)

        elif event == "payment.failed":
            payment_data = data.get('payload', {}).get('payment', {}).get('entity', {})
            payment_id = payment_data.get("id")
            order_id = payment_data.get("order_id")
            metadata = payment_data.get("notes", {})

            user_id = metadata.get("user_id")
            plan_id = metadata.get("plan_id")

            try:
                user = User.objects.get(id=user_id)
                plan = Plan.objects.get(id=plan_id)

                Transaction.objects.create(
                    payment_id=payment_id,
                    order_id=order_id,
                    amount=int(float(payment_data.get("amount")) / 100),
                    signature="(Webhook-Failed-Attempt)"
                )

                UserTransaction.objects.create(
                    user=user,
                    plan=plan,
                    coins=0,
                    amount=plan.amount,
                    payment_id=payment_id,
                    duration="NA",
                    status=4
                )

                return Response({"message": "Failed transaction recorded."}, status=status.HTTP_200_OK)

            except (User.DoesNotExist, Plan.DoesNotExist):
                return Response({"message": "User or Plan not found."}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"message": "Event ignored"}, status=status.HTTP_200_OK)