import datetime
import random
import string
import requests
import environ
import threading
import json
from rest_framework.views import APIView
from rest_framework.response import Response
from distributors.models import Distributors
from helper import getCumulativeAmount
from quickKYC import sendAadharOTP, verifyAadharOTP, verifyPANCard
from retailers.models import (
    Notification,
    Retailer,
    Recharge,
    RetailerAadhaarData,
    RetailerPANInfo,
    Transaction,
    Wallet,
)
from settings.models import DefaultDistributor, MRobotics, WhatsappMessages
from api.retailers.serializers import (
    NotificationSerializer,
    RetailerSerializer,
    RechargeSerializer,
    SaveTransactionSerializer,
    TransactionSerializer,
    WalletSerializer,
)
from django.db.models import Sum

from sschedule import scheduleAnyTask
from whatsapp import replace_keys_with_values, send_message
from django.db import transaction

env = environ.Env()


class RetailerAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, id=0, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            retailer = []
            if id > 0:
                retailer = Retailer.objects.filter(id=id)
                data = RetailerSerializer(retailer, many=True).data

                wlt = Wallet.objects.filter(id=retailer[0].id)
                if len(wlt) > 0:
                    data[0]["balance"] = wlt.amount
                else:
                    data[0]["balance"] = 0

                __rslt["data"] = data
                __rslt["ok"] = 1
            else:
                retailer = Retailer.objects.filter(is_active=True).order_by("-id")
                __rslt["data"] = RetailerSerializer(retailer, many=True).data
                __rslt["ok"] = 1

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data
            serializer = RetailerSerializer(data=data)
            if serializer.is_valid():
                serializer.save()
                saved_object = serializer.instance
                dis = None
                if "distributor_code" in data:
                    if data["distributor_code"] != "":
                        dis = Distributors.objects.filter(code=data["distributor_code"])
                        if len(dis) > 0:
                            saved_object.distributor = dis[0]
                            saved_object.save()
                if dis is None or dis.count() == 0:
                    dis = DefaultDistributor.objects.all().last()
                    if dis:
                        dis = Distributors.objects.filter(id=dis.distributor.id)

                if dis is not None and len(dis) > 0:
                    saved_object.distributor = dis[0]
                    saved_object.save()

                Wallet.objects.create(retailer=saved_object, amount=0)
                __rslt["ok"] = 1
                rtr = Retailer.objects.get(id=saved_object.id)
                # data["balance"] = wlt.amount
                __rslt["data"] = RetailerSerializer(rtr).data

                msg = WhatsappMessages.objects.filter(type=1).latest("-id")
                if msg:
                    key_value_map = {}
                    message = replace_keys_with_values(msg.message, key_value_map)
                    mobile = data["mobile"]
                    scheduleAnyTask(
                        send_message,
                        (mobile, message),
                    )

            else:
                __rslt["error"] = "mobile number already exist!"
        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)

    def put(self, request, id=0, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data
            retailer = Retailer.objects.filter(id=id, password=data["password"])
            if len(retailer) > 0:
                retailer = retailer[0]
                retailer.mpin = data["mpin"]

                retailer.save()
                __rslt["ok"] = 1

                # serializer = RetailerSerializer(retailer, data=data)
                # if serializer.is_valid():
                #     serializer.save()
                #     saved_object = serializer.instance
                #     wlt = Wallet.objects.filter(retailer=saved_object)

                #     data["balance"] = 0
                #     if len(wlt) > 0:
                #         data["balance"] = wlt[0].amount

                #     __rslt["data"] = data
                # else:
                #     __rslt["error"] = "mobile number already exist!"
            else:
                __rslt["error"] = "Invalid Retailer!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class RetailerLoginAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            retailer = []
            data = request.data
            if "mobile" in data and data["mobile"] != "":
                retailer = Retailer.objects.filter(
                    mobile=data["mobile"], password=data["password"]
                )
                if len(retailer) > 0:
                    retailer = retailer[0]
                    # data["name"] = retailer.name
                    # wlt = Wallet.objects.filter(id=retailer.id)
                    # if len(wlt) > 0:
                    #     data["balance"] = wlt[0].amount
                    # else:
                    # data["balance"] = 0

                    # data["id"] = retailer.id
                    __rslt["data"] = RetailerSerializer(retailer).data
                    __rslt["ok"] = 1
                else:
                    __rslt["error"] = "Retailer Does not exist"
                    __rslt["ok"] = 0
            else:
                __rslt["error"] = "Retailer Does not exist"
                __rslt["ok"] = 0

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class RetailerMpinVerificationAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data
            if "mpin" in data and data["mpin"] != "":
                retailer = Retailer.objects.filter(
                    is_active=True, mpin=data["mpin"], id=data["id"]
                ).order_by("-id")
                if len(retailer) > 0:
                    __rslt["ok"] = 1
                    __rslt["data"] = data
            else:
                __rslt["error"] = "mobile number already exist!"
        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class StatsAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = {}

            data["retailers"] = Retailer.objects.filter(is_active=True).count()
            data["recharge"] = Recharge.objects.filter(is_active=True).count()
            wlt = Wallet.objects.filter(is_active=True, amount__gt=0)

            amount = 0
            for item in wlt:
                amount += item.amount
            data["wallet"] = amount

            if len(data) > 0:
                __rslt["data"] = data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class LatestRechargeAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            data = Recharge.objects.filter(is_active=True).order_by("-id")[:10]

            if len(data) > 0:
                __rslt["data"] = RechargeSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class RechargeAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailer_id=0, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            if retailer_id > 0:
                data = Recharge.objects.filter(retailer__id=retailer_id)
            else:
                data = Recharge.objects.filter(is_active=True).order_by("-id")

            if len(data) > 0:
                __rslt["data"] = RechargeSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)

    def post(self, request, format=None):

        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data

            userData = data[0]

            api = env("Mr_TOKEN")
            myData = {
                "api_token": api,
                "mobile_no": userData["mobile"],
                "amount": userData["amount"],
                "company_id": userData["operator"],
                "order_id": userData["order_id"],
                "is_stv": "false",
            }

            # myData = json.dumps(myData)
            # print(myData)
            mroboData = requests.post("https://mrobotics.in/api/recharge/", data=myData)

            mroboData = mroboData.json()
            print(mroboData)
            if mroboData["status"] != "failure":
                sts = 2  # for pending
                if mroboData["status"] == "success":
                    sts = 1

                Recharge.objects.create(
                    order_id=mroboData["order_id"],
                    recharge_id=mroboData["id"],
                    user_id=mroboData["user_id"],
                    lapu_id=mroboData["lapu_id"],
                    status=sts,
                    source=int(userData["source"]),
                    retailer_id=int(userData["retailer"]),
                    operator_id=int(userData["operator"]),
                    operator_no=mroboData["mobile_no"],
                    amount=mroboData["balance"],
                    date=mroboData["recharge_date"],
                )

                Transaction.objects.create(
                    order_id=mroboData["order_id"],
                    tnx_id=mroboData["tnx_id"],
                    source=int(userData["source"]),
                    retailer_id=int(userData["retailer"]),
                    operator_id=int(userData["operator"]),
                    amount=mroboData["balance"],
                    date=mroboData["recharge_date"],
                    transaction_type=userData["transaction_type"],
                    status=sts,
                    remark=mroboData["response"],
                )

                operator = MRobotics.objects.filter(
                    operator=mroboData["company_id"], lapu_id=mroboData["lapu_id"]
                )
                if len(operator) > 0:
                    opr = operator[0]
                    opr.balance = mroboData["balance"]
                    opr.save()

                __rslt["ok"] = 1
                __rslt["data"] = mroboData
            else:
                __rslt["data"] = mroboData
        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class TransactionAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def paytm(self, orderID):
        import requests
        import json

        # import checksum generation utility
        # You can get this utility from https://developer.paytm.com/docs/checksum/
        import PaytmChecksum

        paytmParams = dict()

        paytmParams["body"] = {
            "requestType": "Payment",
            "mid": "RdSOMK30068535532554",
            "websiteName": "www.zirupay.in",
            "orderId": orderID,
            "callbackUrl": "https://zirupay.in/",
            "txnAmount": {
                "value": "1.00",
                "currency": "INR",
            },
            # "userInfo": {
            #     "custId": "CUST_001",
            # },
        }

        # Generate checksum by parameters we have in body
        # Find your Merchant Key in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys
        checksum = PaytmChecksum.generateSignature(
            json.dumps(paytmParams["body"]), "RdSOMK30068535532554"
        )

        paytmParams["head"] = {"signature": checksum}

        post_data = json.dumps(paytmParams)

        # for Staging
        # url = "https://securegw-stage.paytm.in/theia/api/v1/initiateTransaction?mid=YOUR_MID_HERE&orderId=ORDERID_98765"

        # for Production
        url = "https://securegw.paytm.in/theia/api/v1/initiateTransaction?mid=YOUR_MID_HERE&orderId=ORDERID_98765"
        response = requests.post(
            url, data=post_data, headers={"Content-type": "application/json"}
        ).json()
        print(response)

    def get(self, request, retailer_id=0, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            if retailer_id > 0:
                data = Transaction.objects.filter(retailer__id=retailer_id).order_by(
                    "-id"
                )
            else:
                data = Transaction.objects.filter(is_active=True).order_by("-id")

            if len(data) > 0:
                __rslt["data"] = TransactionSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)

    def create_gateway_request(self, data, retailer):

        url = "https://api.ekqr.in/api/create_order"
        # print(data)
        # {"id":0,"wallet":0,"retailer":1,"amount":1.0,"tnx_id":"MT0942531867","remark":"","status":2,"date":""}
        payload = json.dumps(
            {
                "key": "d838789c-5c48-45a7-9fbc-c7945a95fe12",
                "client_txn_id": data["tnx_id"],
                "amount": str(data["amount"]),
                "p_info": "Wallet Recharge",
                "customer_name": retailer.name,
                "customer_email": "rechargepay10@gmail.com",
                "customer_mobile": retailer.mobile,
                "redirect_url": "https://zirupay.in/thankyou/",
                "udf1": "user defined field 1",
                "udf2": "user defined field 2",
                "udf3": "user defined field 3",
            }
        )
        headers = {"Content-Type": "application/json"}

        response = requests.request("POST", url, headers=headers, data=payload)
        # print(response.json())
        return response.json()

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:

            data = request.data
            retailer = Retailer.objects.get(id=data["retailer"])
            res = self.create_gateway_request(data, retailer)

            if "status" in res and res["status"]:
                serializer = SaveTransactionSerializer(data=data)
                if serializer.is_valid():
                    serializer.save()
                    id = serializer.data["id"]
                    order_id = "".join(random.choices("0123456789", k=10))

                    trans = Transaction.objects.get(id=id)
                    trans.order_id = order_id
                    trans.deduction_amount = trans.amount
                    trans.save()

                    # .update(order_id=order_id)

                    __rslt["ok"] = 1
                    __rslt["data"] = res
                else:
                    __rslt["error"] = serializer.errors
            else:
                __rslt["error"] = res["msg"]

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class RecentTransactionAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailer_id, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            data = Transaction.objects.filter(retailer__id=retailer_id).order_by("-id")[
                :10
            ]
            if len(data) > 0:
                __rslt["data"] = TransactionSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class MinimumWalletAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []

            data = Wallet.objects.filter(is_active=True, amount__lte=0).order_by(
                "amount"
            )

            if len(data) > 0:
                __rslt["data"] = WalletSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class WalletAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailer_id=0, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            if retailer_id > 0:
                data = Wallet.objects.filter(retailer__id=retailer_id)
            else:
                data = Wallet.objects.filter(is_active=True)

            if len(data) > 0:
                __rslt["data"] = WalletSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class WalletVerifyAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, tnx_id=None, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = {}
            if tnx_id != None:
                transaction = Transaction.objects.filter(tnx_id=tnx_id)
                if len(transaction) > 0:
                    tnx = transaction[0]
                    tnx.status = 1

                    wallet = Wallet.objects.filter(retailer__id=tnx.retailer.id)
                    if len(wallet) > 0:
                        wlt = wallet[0]
                        wlt.amount = wlt.amount + tnx.amount
                        wlt.save()
                        tnx.save()

                        __rslt["ok"] = 1
                        data["id"] = wlt.id
                        data["wallet_amount"] = wlt.amount
                        data["amount"] = tnx.amount
                        data["status"] = tnx.status

                        __rslt["data"] = data
                    else:
                        __rslt["error"] = "Wallet does not match"

                else:
                    __rslt["error"] = "Transaction does not match"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class NotificationAPI(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailer_id, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = []
            data = Notification.objects.filter(retailer__id=retailer_id).order_by("-id")

            if len(data) > 0:
                __rslt["data"] = NotificationSerializer(data, many=True).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "No record found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class VerifyRetailerMobile(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, mobile="", format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            retailer = Retailer.objects.filter(mobile=mobile)
            if len(retailer) > 0:
                __rslt["ok"] = 0
            else:
                __rslt["ok"] = 1

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class UpdateRetailerPassword(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data
            rtr = Retailer.objects.filter(mobile=data["mobile"])
            if len(rtr) > 0:
                rtr.update(password=data["password"])
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "Retailer Not found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class UpdateRetailerProfile(APIView):
    authentication_classes = []
    permission_classes = []

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            data = request.data
            rtr = Retailer.objects.filter(mobile=data["mobile"])
            if len(rtr) > 0:
                rtr.update(
                    email=data["email"], name=data["name"], address=data["address"]
                )
                rtr = Retailer.objects.get(mobile=data["mobile"])
                __rslt["data"] = RetailerSerializer(rtr).data
                __rslt["ok"] = 1
            else:
                __rslt["error"] = "Retailer Not found!"

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class RetailerReport(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailerID, year, month, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            rtr = Retailer.objects.get(id=retailerID)

            recharges = Recharge.objects.filter(retailer=rtr)
            recharges = recharges.filter(date__year=year)
            months = [
                "january",
                "february",
                "march",
                "april",
                "may",
                "june",
                "july",
                "august",
                "september",
                "october",
                "november",
                "december",
            ]

            index = months.index(month)
            index += 1
            recharges = recharges.filter(date__month=index)

            if len(recharges) > 0:
                commission_amount = recharges.aggregate(
                    total_sum=Sum("commission_amount")
                )["total_sum"]
                __rslt["data"] = {"earning": commission_amount}
            else:
                __rslt["data"] = {"earning": 0}

            __rslt["ok"] = 1

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


class UPIGatewayWebhook(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:

            __rslt["ok"] = 1

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)

    def post(self, request, format=None):

        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            # Extract POST data
            amount = request.data.get("amount")
            client_txn_id = request.data.get("client_txn_id")
            order_id = request.data.get("id")
            remark = request.data.get("remark")
            status_txn = request.data.get("status")

            # Basic validation checks
            if not amount or not client_txn_id or not order_id or not status_txn:
                __rslt["message"] = "Required fields missing"
                __rslt["error"] = "Invalid data"
                return Response(__rslt)

            # Additional processing (e.g., saving to DB, business logic)

            trans = Transaction.objects.filter(tnx_id=client_txn_id)

            if len(trans) > 0:
                if status_txn == "success":
                    trans.update(status=1, order_id=order_id)
                    __trans = trans[0]
                    amt = float(__trans.amount)
                    __trans.cumulative_amount = getCumulativeAmount(
                        __trans.retailer, 1, amt, __trans.id
                    )
                    __trans.save()
                    wlt = Wallet.objects.filter(retailer__id=trans[0].retailer.id)
                    if len(wlt) > 0:
                        wlt = wlt[0]

                        wlt.amount = float(wlt.amount) + float(trans[0].amount)
                        wlt.save()
                        __rslt["message"] = (
                            f"Transaction status updated to {status_txn}. Amount added to wallet"
                        )
                    else:
                        Wallet.objects.create(
                            retailer=trans[0].retailer, amount=trans[0].amount
                        )

                    msg = WhatsappMessages.objects.filter(type=3).latest("-id")
                    if msg:
                        key_value_map = {
                            "name": trans[0].retailer.name,
                            "amount": float(msg.amount),
                        }
                        message = replace_keys_with_values(msg.message, key_value_map)
                        mobile = trans[0].retailer.mobile
                        scheduleAnyTask(
                            send_message,
                            (mobile, message),
                        )
                else:
                    trans.update(status=3, remark=remark, order_id=order_id)
                    __rslt["message"] = (
                        f"Transaction status updated to {status_txn}. Error: {remark}"
                    )
                __rslt["message"] = "Transaction status updated successfully"

            __rslt["ok"] = 1
            __rslt["message"] = "Data processed successfully"
            # __rslt["data"] = {
            #     "amount": amount,
            #     "client_txn_id": client_txn_id,
            #     "createdAt": createdAt,
            #     "customer_email": customer_email,
            #     "customer_mobile": customer_mobile,
            #     "customer_name": customer_name,
            #     "customer_vpa": customer_vpa,
            #     "order_id": order_id,
            #     "p_info": p_info,
            #     "redirect_url": redirect_url,
            #     "remark": remark,
            #     "status": status_txn,
            #     "txnAt": txnAt,
            #     "udf1": udf1,
            #     "udf2": udf2,
            #     "udf3": udf3,
            #     "upi_txn_id": upi_txn_id,
            # }

        except Exception as ex:
            __rslt["error"] = str(ex)

        return Response(__rslt)


class RetailerTotalEarning(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, retailerID, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            rtr = Retailer.objects.get(id=retailerID)

            recharges = Recharge.objects.filter(retailer=rtr)

            if len(recharges) > 0:
                commission_amount = recharges.aggregate(
                    total_sum=Sum("commission_amount")
                )["total_sum"]
                __rslt["data"] = {"earning": commission_amount}
            else:
                __rslt["data"] = {"earning": 0}

            __rslt["ok"] = 1

        except Exception as ex:
            __rslt["error"] = ex.args

        return Response(__rslt)


def getUniqueID():

    # initializing size of string
    N = 7

    # using random.choices()
    # generating random strings
    return "".join(random.choices(string.ascii_uppercase + string.digits, k=N))


class PANCardVerificationAPI(APIView):
    authentication_classes = []
    permission_classes = []
    lock = threading.Lock()

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:

            # verifyPANCard('panID')
            # {'pan_number': 'DXKPP7384A', 'full_name': 'NEERAJ  PATHAK', 'category': 'individual'}

            with self.lock:  # Thread-level lock
                with transaction.atomic():  # Database-level atomicity
                    data = request.data
                    # Lock mechanism to prevent concurrent requests
                    rtr = Retailer.objects.select_for_update().get(id=data["retailer"])

                    if rtr.transaction_in_progress:
                        raise Exception(
                            "Another transaction is in progress. Please wait."
                        )

                    # Mark the transaction as in progress
                    rtr.transaction_in_progress = True
                    rtr.save()
                    __amt = 5
                    # Wallet and deduction logic
                    wlt = (
                        Wallet.objects.select_for_update()
                        .filter(
                            retailer__id=data["retailer"],
                            amount__gte=__amt,
                        )
                        .first()
                    )

                    if not wlt:
                        raise Exception("Low Wallet Balance!")

                    if not rtr.distributor:
                        raise Exception("You don't have distributor!")

                    # Deduct amount from wallet instantly
                    deducted_amount = float(5)
                    wlt.amount = float(wlt.amount) - deducted_amount
                    wlt.save()

                    try:

                        trans = Transaction.objects.create(
                            source=3,
                            retailer_id=int(data["retailer"]),
                            amount=5,
                            transaction_type=2,
                            status=2,
                        )

                        # Perform the transaction logic

                        pan_res = verifyPANCard(data["panID"])
                        sts = 2  # Pending
                        if (
                            pan_res
                            and "data" in pan_res
                            and "pan_number" in pan_res["data"]
                        ):
                            sts = 1
                        else:
                            sts = 3

                        trans.order_id = getUniqueID()
                        trans.tnx_id = getUniqueID()
                        trans.date = datetime.datetime.today()
                        trans.status = sts
                        trans.save()

                        if sts == 1:
                            RetailerPANInfo.objects.create(
                                retailer=rtr,
                                pan_number=pan_res["data"]["pan_number"],
                                full_name=pan_res["data"]["full_name"],
                                category=pan_res["data"]["category"],
                            )
                            rtr.name = pan_res["data"]["full_name"]
                            rtr.is_pan = True
                            if rtr.is_aadhar:
                                rtr.is_kyc = True
                            rtr.save()
                            rch_amount = 5
                            trans.deduction_amount = rch_amount
                            trans.commission_amount = 0
                            trans.cumulative_amount = getCumulativeAmount(
                                rtr, 0, rch_amount, trans.id
                            )
                            trans.save()
                            try:
                                wlt.amount = float(wlt.amount) + deducted_amount
                                wlt.amount = float(wlt.amount) - float(rch_amount)
                                wlt.save()
                            except Exception as ex:
                                raise Exception(f"Failed to save wallet: {str(ex)}")

                            __rslt["ok"] = 1
                        else:
                            __rslt["ok"] = 0
                            __rslt["error"] = "Transaction Failed Check API"

                    except Exception as ex:
                        # Rollback the deducted amount in case of failure
                        wlt.amount = float(wlt.amount) + deducted_amount
                        wlt.save()
                        raise ex  # Re-raise the exception after rollback

                    finally:
                        # Ensure the transaction flag is cleared in all cases
                        rtr.transaction_in_progress = False
                        rtr.save()

        except Exception as ex:
            __rslt["error"] = str(ex)
            # Handle exception and log errors

        return Response(__rslt)


class AadharSendOTPAPI(APIView):
    authentication_classes = []
    permission_classes = []
    lock = threading.Lock()

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:

            # verifyPANCard('panID')
            # {'pan_number': 'DXKPP7384A', 'full_name': 'NEERAJ  PATHAK', 'category': 'individual'}

            with self.lock:  # Thread-level lock
                with transaction.atomic():  # Database-level atomicity
                    data = request.data
                    # Lock mechanism to prevent concurrent requests
                    rtr = Retailer.objects.select_for_update().get(id=data["retailer"])

                    if rtr.transaction_in_progress:
                        raise Exception(
                            "Another transaction is in progress. Please wait."
                        )

                    # Mark the transaction as in progress
                    rtr.transaction_in_progress = True
                    rtr.save()
                    __amt = 5
                    # Wallet and deduction logic
                    wlt = (
                        Wallet.objects.select_for_update()
                        .filter(
                            retailer__id=data["retailer"],
                            amount__gte=__amt,
                        )
                        .first()
                    )

                    if not wlt:
                        raise Exception("Low Wallet Balance!")

                    if not rtr.distributor:
                        raise Exception("You don't have distributor!")

                    # Deduct amount from wallet instantly
                    deducted_amount = float(5)
                    wlt.amount = float(wlt.amount) - deducted_amount
                    wlt.save()

                    try:

                        trans = Transaction.objects.create(
                            source=3,
                            retailer_id=int(data["retailer"]),
                            amount=5,
                            transaction_type=2,
                            status=2,
                        )

                        # Perform the transaction logic

                        aadhar_res = sendAadharOTP(data["aadharID"])
                        sts = 2  # Pending
                        if (
                            aadhar_res
                            and "data" in aadhar_res
                            and "otp_sent" in aadhar_res["data"]
                        ):
                            sts = 1
                        else:
                            sts = 3

                        if not aadhar_res["data"]["otp_sent"]:
                            sts = 2

                        trans.order_id = getUniqueID()
                        trans.tnx_id = getUniqueID()
                        trans.date = datetime.datetime.today()
                        trans.status = sts
                        trans.save()

                        if sts == 1:

                            rch_amount = 5
                            trans.deduction_amount = rch_amount
                            trans.commission_amount = 0
                            trans.cumulative_amount = getCumulativeAmount(
                                rtr, 0, rch_amount, trans.id
                            )
                            trans.save()
                            try:
                                wlt.amount = float(wlt.amount) + deducted_amount
                                wlt.amount = float(wlt.amount) - float(rch_amount)
                                wlt.save()
                            except Exception as ex:
                                raise Exception(f"Failed to save wallet: {str(ex)}")

                            __rslt["ok"] = 1
                            __rslt["data"] = aadhar_res
                        else:
                            __rslt["ok"] = 0
                            __rslt["error"] = "Transaction Failed Check API"
                            raise Exception(f"Transaction Failed Check API: {str(ex)}")

                    except Exception as ex:
                        # Rollback the deducted amount in case of failure
                        wlt.amount = float(wlt.amount) + deducted_amount
                        wlt.save()
                        raise ex  # Re-raise the exception after rollback

                    finally:
                        # Ensure the transaction flag is cleared in all cases
                        rtr.transaction_in_progress = False
                        rtr.save()

        except Exception as ex:
            __rslt["error"] = str(ex)
            # Handle exception and log errors

        return Response(__rslt)


class VerifyAadharAPI(APIView):
    authentication_classes = []
    permission_classes = []
    lock = threading.Lock()

    def post(self, request, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:

            with self.lock:  # Thread-level lock
                with transaction.atomic():  # Database-level atomicity
                    data = request.data
                    # Lock mechanism to prevent concurrent requests
                    rtr = Retailer.objects.select_for_update().get(id=data["retailer"])

                    if rtr.transaction_in_progress:
                        raise Exception(
                            "Another transaction is in progress. Please wait."
                        )

                    # Mark the transaction as in progress
                    rtr.transaction_in_progress = True
                    rtr.save()

                    if not rtr.distributor:
                        raise Exception("You don't have distributor!")

                    try:

                        aadhar_res = verifyAadharOTP(data["request_id"], data["otp"])
                        sts = 2  # Pending
                        if (
                            aadhar_res
                            and "data" in aadhar_res
                            and "full_name" in aadhar_res["data"]
                        ):
                            sts = 1
                        else:
                            sts = 3

                        if sts == 1:
                            __tempData = aadhar_res["data"]
                            aadhar = RetailerAadhaarData.objects.create(
                                retailer=rtr,
                                full_name=__tempData["full_name"],
                                aadhaar_number=__tempData["aadhaar_number"],
                                gender=__tempData["gender"],
                                country=__tempData["address"]["country"],
                                state=__tempData["address"]["state"],
                                dist=__tempData["address"]["dist"],
                                subdist=__tempData["address"]["subdist"],
                                po=__tempData["address"]["po"],
                                loc=__tempData["address"]["loc"],
                                vtc=__tempData["address"]["vtc"],
                                street=__tempData["address"]["street"],
                                house=__tempData["address"]["house"],
                                landmark=__tempData["address"]["landmark"],
                                zip=__tempData["zip"],
                                care_of=__tempData["care_of"],
                                share_code=__tempData["share_code"],
                                status=__tempData["status"],
                            )
                            try:
                                aadhar.dob = __tempData["dob"]
                                aadhar.save()
                            except Exception as ex:
                                print(ex)

                            rtr.is_aadhar = True
                            if rtr.is_pan:
                                rtr.is_kyc = True
                            rtr.save()

                            __rslt["ok"] = 1
                        else:
                            __rslt["ok"] = 0
                            raise Exception(f"Transaction Failed Check API: {str(ex)}")

                    except Exception as ex:
                        raise ex  # Re-raise the exception after rollback

                    finally:
                        # Ensure the transaction flag is cleared in all cases
                        rtr.transaction_in_progress = False
                        rtr.save()

        except Exception as ex:
            __rslt["error"] = str(ex)
            # Handle exception and log errors

        return Response(__rslt)


class RetailerKycStatus(APIView):
    authentication_classes = []
    permission_classes = []
    lock = threading.Lock()

    def get(self, request, id, format=None):
        __rslt = {"ok": 0, "message": "", "error": "", "data": None}
        try:
            rtr = Retailer.objects.get(id=id)
            __rslt["data"] = {
                "is_kyc": rtr.is_kyc,
                "is_aadhar": rtr.is_aadhar,
                "is_pan": rtr.is_pan,
                "is_kyc_activated": rtr.is_kyc_activated,
            }
            __rslt["ok"] = 1
        except Exception as ex:
            __rslt["error"] = str(ex)
            # Handle exception and log errors

        return Response(__rslt)
