from appservices.common.util import *
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, SelectMultipleField,SelectField,FileField,IntegerField,BooleanField,FieldList,DateTimeLocalField,FormField
from wtforms.validators import DataRequired, ValidationError, Length,NumberRange, Optional,Regexp,InputRequired,AnyOf,URL, EqualTo

wallet_credits_debits = Blueprint("wallet_credits_debits",__name__)

ALPHANUMERIC_REGEX = r"^[a-zA-Z0-9\s@#$()+_\-/.]*$" ##  alphanumeric characters and special characters(letters and digits).

class WalletCreditDebitForm(FlaskForm):
    patternId = SelectField('', choices=[],validate_choice=False,validators=[DataRequired(message = "Pattern is required")])
    userId = SelectField('',choices=[], validate_choice=False,validators=[DataRequired(message = "User Name is required")])
    credittransferType = SelectField('', choices=[('Credit', 'Credit'), ('Debit', 'Debit'),('Debit', 'Debit')], validators=[Optional()])
    amount = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Settlement Amount must contains between 1 and 10 numeric characters"),Regexp(r'^\d+(\.\d+)*$', message="Settlement Amount contains only numeric characters")])
    comment = StringField('', validators=[DataRequired(),Length(min=1, max=100,message="Remark must be between 1 and 100 characters."),Regexp(ALPHANUMERIC_REGEX, message="Only alphanumeric and special characters @#$()+_-/.")])
    
    def validate_patternId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Pattern Id.")
            pattern_queryset = Patterns.objects(id=field.data,status__nin=[2]).first()
            if not pattern_queryset:
                raise ValidationError("Please select a Valid Pattern Id")
    
    def validate_merchantId(self, field):
        if field.data:
            if not ObjectId.is_valid(field.data): 
                raise ValidationError("Invalid Merchant Id.")
            merchant_queryset = Users.objects(id=field.data,status__nin=[2]).first()
            if not merchant_queryset:
                raise ValidationError("Please select a Valid Merchant Id")
            

class AdminBalanceUpdateForm(FlaskForm):
    transferType = SelectField("", choices=["Payout", "Payin"], validators=[DataRequired()])
    amount = StringField('',validators=[DataRequired(), Length(min=1, max=10,message="Amount must contains between 1 and 10 numeric characters"),Regexp(r'([0-9]+([.][0-9]*)?|[.][0-9])', message="Amount contains only numeric characters")])
    comment = StringField('', validators=[DataRequired(),Length(min=3, max=75, message="comment length can be between 3 to 75 "),
            Regexp(ALPHANUMERIC_REGEX, message="comment can contain only alphanumeric characters and @#$()+_\-\/.")])

def fetching_user_details(user_queryset):
    user_details = {}
    try:
        user_details = {
        "id":str(user_queryset.id),
        "fullName":user_queryset.fullName,
        "mobileNumber":user_queryset.phoneNumber,
        "emailId":user_queryset.email,
        "address":user_queryset.address
        }
    except Exception as e:
        app.logger.error(traceback.format_exc())
    return user_details
        
@wallet_credits_debits.route("/admin_balance_update", methods=["POST","GET"])
@adminid_access_token_required
@csrf_protect
def admin_balance_update():
    data_status={"responseStatus":0,"result":""}
    try:
        if not session.get("adminId"):
            return redirect("admin_login")
        adminId = session.get("adminId")
        
        csrf_token = request.form.get("csrf_token")
        print(csrf_token,"((((((((((((((csrf_token))))))))))))))")
        latitude = request.form.get("latitude", "")
        longitude = request.form.get("longitude", "")
        loginBrowser = request.headers.get("Sec-Ch-Ua")
        if loginBrowser:
            loginBrowseData = loginBrowser.split(";")
            browser = loginBrowseData[0]
        else:
            loginBrowseData = request.headers.get('User-Agent').split(";")
            browser = loginBrowseData[0]

        existing_record = ""
        client_ip=0
        # Extracting client IP address
        if request.headers.getlist("X-Forwarded-For"): 
            client_ip = request.headers.getlist("X-Forwarded-For")[0]
        else:
            client_ip = request.remote_addr

        actionDate=datetime.datetime.now()

        admin_querryset=SuperAdmin.objects(id=str(adminId)).first()
        if admin_querryset:
            adminName=admin_querryset.userName
        else:
            adminName="N/A"

        if request.method == "POST":
            amount = request.form.get("amount",0)
            transferType = request.form.get("transferType","")
            comment = request.form.get("comment","") 
            jsonData = request.form.to_dict(flat=True)          
            
            # if comment and not is_valid_alphanumeric(comment):
            #     flash("comment must contain only alphanumeric characters, spaces, and specific special characters: @#$()+_-/")
            #     return redirect(url_for("api_document_guide.api_document_guides_list"))
            
            # if amount and not is_valid_numeric(amount):
            #     flash("Amount must contain only numeric characters!")
            #     return redirect(url_for("api_document_guide.api_document_guides_list"))

            form = AdminBalanceUpdateForm()

            if form.validate_on_submit():

                if amount and transferType and comment:
                    try:
                        previousBalance = 0
                        currentBalance = 0
                        admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                        existing_record = admin_overall_balance_queryset.to_json()
                        message=admin_overall_balance_queryset.adminId.userName+" "+transferType+" Admin balance updated successfully!"
                        requestData=[admin_overall_balance_queryset]
                        updatedrequestData=[jsonData]
                        save_admin_log_table = save_admin_logs_data(adminId,None,None,"admin_balance_update","update",actionDate,client_ip,browser,message,requestData,updatedrequestData,latitude,longitude) 
                        if transferType == "Payin":
                            if admin_overall_balance_queryset:
                                updatePayinBalance = float(admin_overall_balance_queryset.payinBalance)+float(amount)

                                currentBalance = float(updatePayinBalance)
                                previousBalance = float(admin_overall_balance_queryset.payinBalance)

                                admin_overall_balance_queryset.update(
                                    payinBalance = updatePayinBalance,
                                    updatedOn = datetime.datetime.now()
                                    )

                            else:
                                currentBalance = float(amount)
                                previousBalance = 0

                                admin_overall_balance_table = AdminOverallBalances(
                                    adminId=adminId,
                                    payinBalance=amount,
                                    payoutBalance=0,
                                    createdOn = datetime.datetime.now(),
                                    status = 1
                                    ).save()

                        else:
                            ladmin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                            if ladmin_overall_balance_queryset:
                                updatePayoutBalance = float(ladmin_overall_balance_queryset.payoutBalance)+float(amount)

                                currentBalance = float(updatePayoutBalance)
                                previousBalance = float(ladmin_overall_balance_queryset.payoutBalance)

                                ladmin_overall_balance_queryset.update(
                                    payoutBalance = updatePayoutBalance,
                                    updatedOn = datetime.datetime.now()
                                    )
                            else:
                                currentBalance = float(amount)
                                previousBalance = 0

                                admin_overall_balance_table = AdminOverallBalances(
                                    adminId=adminId,
                                    payinBalance=0,
                                    payoutBalance=amount,
                                    createdOn = datetime.datetime.now(),
                                    status = 1
                                    ).save()

                        admin_log_balance_table = AdminLogBalances(
                            adminId=adminId,
                            transferType = transferType,
                            walletType = "Credit",
                            previousBalance = previousBalance,
                            currentBalance = currentBalance,
                            comment=comment,
                            amount=amount,
                            createdOn = datetime.datetime.now(),
                            status = 1
                            )
                        save_admin_log_table = admin_log_balance_table.save()
                        save_admin_log_table.update(userId=None)

                        try:
                            mail_subject = transferType+" balance credit to admin virtual wallet"
                            recipients_list = [admin_recieve_email]
                            template_name = "emails/admin_credit_debit.html"
                            trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                            mail_data = {
                            "amount":round(float(amount),2),
                            "transferType":transferType,
                            "trnsactionDate":trnsactionDate,
                            "adminName":adminName,
                            "comment":comment
                            }
                            send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                        except Exception as e:
                            pass

                        flash("Admin balance updated successfully!")

                        data_status['responseStatus']=1
                        return data_status
                    except Exception as e:
                        flash("Unable to update admin balance!!")
                        app.logger.error(traceback.format_exc())
                        data_status['responseStatus']=4
                        return data_status
                else:
                    data_status['responseStatus']=2
                    data_status['result']="Required fields are missing!!"
                    return data_status
            else:
                data_status['result']=form.errors
                return data_status
    except Exception as e:
        error = "Unable to update admin balance!!"
        flash(error)
        app.logger.error(traceback.format_exc())
        data_status['responseStatus']=4
        return data_status

#OTP Generate API
@wallet_credits_debits.route("/generate_credit_debit_wallet_otp",methods=["GET","POST"])
@adminid_access_token_required
@csrf.exempt
def generate_credit_debit_wallet_otp():
    credit_to_wallet=request.form.get('credit_to_wallet')
    data_status = {"responseStatus": 0, "result": "","otpCheckId":""}
    try:
        if not session.get("adminId"):
            data_status['result']="Invalid User."
            return data_status
        adminId = session.get("adminId")
        
        if adminId and credit_to_wallet:
            admin_queryset = SuperAdmin.objects(id=str(adminId),status=1).first()
            if admin_queryset:
                otp_record = VerifyNumbers.objects(verifyType="credit_debit",status=1).first()
                if otp_record:
                    phoneNumber = otp_record.mobileNumber
                else:
                    phoneNumber="9492844021"
                
                otpCode = str(random.randint(100000,999999))
               
                otpcheck_queryset=OtpChecks(
                    adminId=str(adminId),
                    phoneNumber=str(phoneNumber),
                    otpCode=otpCode,
                    attempts=0,
                    status=0,
                    createdOn=datetime.datetime.now(),
                    otpReason=credit_to_wallet
                    )
                otpcheck_queryset.save()
                otpCheckId=str(otpcheck_queryset.id)
                print(f" OTP Generated: {otpCode} | ID: {otpCheckId}")

                try:
                    smsmessage="Apex pay admin settlement verification code is "+str(otpCode)
                    send_sms(phoneNumber,smsmessage)
                except Exception as e:
                    pass 


                data_status["responseStatus"] = 1
                data_status["otpCheckId"] = otpCheckId
                data_status["result"]="Otp generated successfully"
                return data_status
            else:
                data_status["result"]="Invalid User."
                return data_status
        else:
            data_status["result"]="Invalid Request."
            return data_status 
    except Exception as e:
        app.logger.error(traceback.format_exc())
        data_status["result"]="Unable to generate OTP."
        return data_status

@wallet_credits_debits.route("/check_wallet_otp",methods=["POST"])
@adminid_access_token_required
@csrf.exempt
def check_wallet_otp():
    data_status = {"responseStatus": 0, "result": ""}
    otpCheckId = request.form.get("otpCheckId","")
    otpCode = request.form.get("otpCode","")
    print(otpCheckId,"otpCheckId")
    if otpCode and otpCheckId:
        try:
            if not session.get("adminId"):
                data_status['result']="Invalid User."
                return data_status
            adminId = session.get("adminId")
            print(adminId,"adminId")
            admin_queryset = SuperAdmin.objects(id=str(adminId)).first()
            if not admin_queryset:
                data_status["result"]="Invalid User!!"
                return data_status
            
            if otpCheckId!="":
                otpcheck_querryset=OtpChecks.objects(adminId=str(adminId),id=str(otpCheckId),status=0).first()
                if otpcheck_querryset:
                    attempts=otpcheck_querryset.attempts+1
                    if otpcheck_querryset.otpCode==otpCode:
                        otpcheck_querryset.update(status=1,attempts=attempts)
                        data_status["responseStatus"] = 1
                        data_status["result"] = "Otp validated."
                        return data_status
                    else:
                        otpcheck_querryset.update(attempts=attempts)
                        data_status["result"] = "Invalid Otp."
                        return data_status
                else:
                    data_status["result"] = "Invalid Otp."
                    return data_status
            else:
                data_status["result"] = "Invalid Otp."
                return data_status
        except Exception as e:
            app.logger.error(traceback.format_exc())
            data_status["result"]="Unable to user login!!"
            return data_status
    else:
        data_status["result"] = "Required fields are missing!!"
        return data_status

@wallet_credits_debits.route("/credit_to_wallet", methods=["POST","GET"])
@adminid_access_token_required
@csrf_protect
def credit_to_wallet():
    data_status={"responseStatus": 2, "result": ""}
    try:
        redirectTo = request.args.get("redirectTo","Credit")
        if redirectTo:
            redirectval = redirectTo
        else:
            redirectval = "Credit"

        if not session.get("adminId"):
            return redirect("admin_login")
        adminId = session.get("adminId")

        latitude = request.form.get("latitude", "")
        longitude = request.form.get("longitude", "")
        loginBrowser = request.headers.get("Sec-Ch-Ua")
        if loginBrowser:
            loginBrowseData = loginBrowser.split(";")
            browser = loginBrowseData[0]
        else:
            loginBrowseData = request.headers.get('User-Agent').split(";")
            browser = loginBrowseData[0]

        client_ip=0
        # Extracting client IP address
        if request.headers.getlist("X-Forwarded-For"): 
            client_ip = request.headers.getlist("X-Forwarded-For")[0]
        else:
            client_ip = request.remote_addr

        actionDate=datetime.datetime.now()

        csrf_token = request.form.get("csrf_token")
        print(csrf_token,"((((((((((((((csrf_token))))))))))))))")
        
        admin_querryset=SuperAdmin.objects(id=str(adminId),status=1).first()
        if admin_querryset:
            adminName=admin_querryset.userName
        else:
            adminName="N/A"

        form = WalletCreditDebitForm(request.form)
        if request.method == "GET":
            usersList = []
            patternsList = []
            
            totalPayInBalance=0
            totalPayoutAmount=0
            
            adminBalanceQueryset = AdminOverallBalances.objects(status=1).first()
            totalPayInBalance=float(adminBalanceQueryset.payinBalance)
            totalPayoutAmount =float(adminBalanceQueryset.payoutBalance)

            patterns_queryset = Patterns.objects(status__in=[0,1]).order_by("-id").all()
            for each_pattern in patterns_queryset:
                pattern_dict = fetching_pattern_details(each_pattern)
                patternsList.append(pattern_dict)

            # print("<<<<<<<<<<patternsList.append(pattern_dict)>>>>>>>>",patternsList)
            users_queryset = Users.objects(status__in=[1]).order_by("-id")
            for each_user in users_queryset:
                userDict = fetching_user_details(each_user)
                usersList.append(userDict)
            # print("<<<<<<<<<<patternsList.append(pattern_dict)>>>>>>>>",usersList)
            return render_template("super_admin_templates/wallet_credits_debits.html",
                usersList=usersList,
                patternsList=patternsList,
                redirectval=redirectval,
                totalPayInBalance=totalPayInBalance,
                totalPayoutAmount=totalPayoutAmount,
                )

        if request.method == "POST":
            
            if form.validate():
                userId = request.form.get("userId","")
                amount = request.form.get("amount",0)
                patternId = request.form.get("patternId","")
                transferType = request.form.get("transferType","") # "Payin" or "Payout" or "USDT" or "Commission"
                walletType = request.form.get("walletType","") # "Credit" or "Debit"
                comment = request.form.get("comment","")
                dotpLogid = request.form.get("dotpLogid","")
                cotpLogid = request.form.get("cotpLogid","")
                transactionUniqueId = random_digit_generate(16)
                orderId = random_digit_generate(16)
                print(request.form,"***********request.form**************")

                jsonData = request.form.to_dict(flat=True)
                requestData = [jsonData]
                updatedrequestData = [jsonData]
                
              
                print(userId,"(((((((((((((((userId)))))))))))))))")
                print(amount,"(((((((((((((((amount)))))))))))))))")
                print(patternId,"(((((((((((((((patternId)))))))))))))))")
                print(transferType,"(((((((((((((((transferType)))))))))))))))")
                print(comment,"(((((((((((((((comment)))))))))))))))")
                print(dotpLogid,"(((((((((((((((dotpLogid)))))))))))))))")
                print(cotpLogid,"(((((((((((((((cotpLogid)))))))))))))))")
                if userId and amount and patternId and transferType and comment and (dotpLogid or cotpLogid):
                    try:
                        admin_queryset = SuperAdmin.objects(id=adminId,status=1).first()
                        if admin_queryset:
                            message=admin_queryset.userName+" "+walletType+" Amount to merchant wallet successfully!"
                            save_admin_log_table = save_admin_logs_data(adminId,None,None,"credit_to_wallet","create",actionDate,client_ip,browser,message,requestData,updatedrequestData,latitude,longitude) 
                        otpCheckId=""
                        if cotpLogid:
                            otpCheckId=cotpLogid
                        if dotpLogid:
                            otpCheckId=dotpLogid

                        if otpCheckId=="":
                            flash("Invalid Request.")
                            data_status["responseStatus"] =1
                            return data_status
                        otpcheck_querryset=OtpChecks.objects(adminId=str(adminId),id=str(otpCheckId),status=1).first()
                        if not otpcheck_querryset:
                            flash("Invalid Request.")
                            data_status["responseStatus"] =4
                            return data_status
                        otpcheck_querryset.update(status=2)
                        admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                        if not admin_overall_balance_queryset:
                            admin_payinBalance=0
                            admin_payoutBalance=0
                        else:
                            admin_payinBalance=float(admin_overall_balance_queryset.payinBalance)
                            admin_payoutBalance=float(admin_overall_balance_queryset.payoutBalance)

                        user_queryset = Users.objects(id=userId).first()
                        if not user_queryset:
                            flash("Server Connection Error.")
                            data_status["responseStatus"] =4
                            return data_status
                        else:
                            payInPaymentGatewayId=""
                            payOutPaymentGatewayId=""
                            previousPayinBalance=0
                            if transferType == "Payin":
                                if not user_queryset.patternId.defaultPayinPaymentGatewayId:
                                    flash("Payin Api Not Assigned.")
                                    data_status["responseStatus"] =4
                                    return data_status
                                payInPaymentGatewayId = str(user_queryset.patternId.defaultPayinPaymentGatewayId.id)
                                payin_balances_queryset = PayinBalances.objects(userId=userId,transactionAPIId=payInPaymentGatewayId).first()
                                if payin_balances_queryset:
                                    previousPayinBalance = float(payin_balances_queryset.currentBalance)
                                else:
                                    previousPayinBalance=0
                                print(previousPayinBalance,"***********previousPayinBalance**************")

                                if walletType == "Credit":
                                    if float(admin_payinBalance)<float(amount):
                                        flash("insufficient Admin Payin Balance.")
                                        data_status["responseStatus"] =4
                                        return data_status

                                    balanceResult=user_payin_balance_update(str(userId),float(amount),"Credit",str(payInPaymentGatewayId))
                                    if balanceResult.get('responseStatus')==0:
                                        flash("Unable to connect with server. Please Try again.")
                                        data_status["responseStatus"] =4
                                        return data_status
                                    # latest_user_queryset = Users.objects(id=str(userId)).modify(inc__walletBalance=float(amount),new=True)
                                    # updateAmount = latest_user_queryset.walletBalance
                                    # actuallBalance = float(updateAmount)-float(amount)

                                    wallet_credit_table = WalletTransactions(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        patternId = patternId,
                                        creditType = "Credit",
                                        userType = "admin",
                                        comment = comment,
                                        transactionId = transactionUniqueId,
                                        paymentGatewayId = str(payInPaymentGatewayId),
                                        paymentType = "wallet",
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=balanceResult.get('userPreviousBalance'),
                                        currentBalance=balanceResult.get('userCurrentBalance'),
                                        remarks = "",
                                        orderId = orderId,
                                        customerName = "admin",
                                        customerEmail = "admin@appservices.tech",
                                        customerPhonenumber = "",
                                        agent = "",
                                        location = "",
                                        platform = "",
                                        paymentLink = "",
                                        errorMessage = "",
                                        paymentChannel = "",
                                        bankRefId = "",
                                        cardmasked = "",
                                        customerVpa = "",
                                        commissionCharges = {},
                                        status = 1
                                        )
                                    save_table = wallet_credit_table.save()
                                    
                                    # latest_payin_balances_queryset = PayinBalances.objects(userId=userId,transactionAPIId=payInPaymentGatewayId).first()
                                    # if latest_payin_balances_queryset:
                                    #     payin_balance_queryset = PayinBalances.objects(userId=str(userId),transactionAPIId=str(payInPaymentGatewayId)).modify(inc__currentBalance=float(amount),new=True)
                                    #     payinCurrentBalance=payin_balance_queryset.currentBalance
                                    #     latest_previousPayinBalance=float(payinCurrentBalance)-float(amount)
                                    #     payin_balance_queryset.update(previousBalance=round(float(latest_previousPayinBalance),2),updatedOn=datetime.datetime.now())

                                    payinbalancelogs_queryset=PayinBalanceLogs(
                                        transactionAPIId=str(payInPaymentGatewayId),
                                        userId=str(userId),
                                        previousBalance=balanceResult.get('transactionPreviousBalance'),
                                        currentBalance=balanceResult.get('transactionCurrentBalance'),
                                        orderId=orderId,
                                        amount=round(float(amount),2),
                                        grandTotal=round(float(amount),2),
                                        transferType="Credit",
                                        userType="admin",
                                        transactionId=transactionUniqueId,
                                        createdOn=datetime.datetime.now(),
                                        status=1
                                        ).save()

                                    # else:
                                    #     payinsavetable=PayinBalances(
                                    #         userId = userId,
                                    #         transactionAPIId = payInPaymentGatewayId,
                                    #         previousBalance = 0,
                                    #         currentBalance = float(amount),
                                    #         createdOn = datetime.datetime.now(),
                                    #         status = 1
                                    #         ).save()

                                    #     payinbalancelogs_queryset=PayinBalanceLogs(
                                    #         transactionAPIId=str(payInPaymentGatewayId),
                                    #         userId=str(userId),
                                    #         previousBalance=0,
                                    #         currentBalance=round(float(amount),2),
                                    #         orderId=orderId,
                                    #         amount=round(float(amount),2),
                                    #         grandTotal=round(float(amount),2),
                                    #         transferType="Credit",
                                    #         userType="admin",
                                    #         transactionId=transactionUniqueId,
                                    #         createdOn=datetime.datetime.now(),
                                    #         status=1
                                    #         ).save()

                                    latest_admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                                    if latest_admin_overall_balance_queryset:
                                        updatePayinBalance = float(latest_admin_overall_balance_queryset.payinBalance)-float(amount)

                                        currentBalance = float(updatePayinBalance)
                                        previousBalance = float(latest_admin_overall_balance_queryset.payinBalance)

                                        latest_admin_overall_balance_queryset.update(
                                            payinBalance = updatePayinBalance,
                                            updatedOn = datetime.datetime.now()
                                            )
                                        admin_log_balance_table = AdminLogBalances(
                                            adminId=adminId,
                                            userId = userId,
                                            transferType = transferType,
                                            walletType = "Debit",
                                            previousBalance = previousBalance,
                                            currentBalance = currentBalance,
                                            comment=comment,
                                            amount=amount,
                                            createdOn = datetime.datetime.now(),
                                            status = 1
                                            ).save()
                                    
                                    
                                    try:
                                        mail_subject = "Payin balance credit to "+str(user_queryset.fullName)+" wallet From admin"
                                        recipients_list = [admin_recieve_email]
                                        template_name = "emails/wallet_credit_debit.html"
                                        trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                        mail_data = {
                                        "amount":round(float(amount),2),
                                        "transactionUniqueId":transactionUniqueId,
                                        "merchantName":str(user_queryset.fullName),
                                        "transferType":transferType,
                                        "walletType":walletType,
                                        "trnsactionDate":trnsactionDate,
                                        "adminName":adminName,
                                        "comment":comment,
                                        "orderId":orderId
                                        }
                                        send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                    except Exception as e:
                                        pass
                                    
                                    flash("Amount credited to Merchant Payin Wallet successfully!")
                                    data_status["responseStatus"]=1
                                    data_status["result"] = "Amount credited to Merchant Payin Wallet successfully!"
                                    return data_status
                                else:
                                    latest_user_queryset = Users.objects(id=str(userId)).first()
                                    if float(latest_user_queryset.walletBalance)<float(amount):
                                        flash("insufficient Merchant Payin Balance.")
                                        data_status["responseStatus"] =1
                                        return data_status

                                    payin_balances_queryset = PayinBalances.objects(userId=userId,transactionAPIId=payInPaymentGatewayId).first()
                                    if payin_balances_queryset:
                                        previousPayinBalance = float(payin_balances_queryset.currentBalance)
                                    else:
                                        previousPayinBalance=0
                                    if float(previousPayinBalance)<float(amount):
                                        flash("insufficient Merchant Payin Balance.")
                                        data_status["responseStatus"] =4
                                        return data_status

                                    if payin_balances_queryset:
                                        balanceResult=user_payin_balance_update(str(userId),float(amount),"Debit",str(payInPaymentGatewayId))
                                        if balanceResult.get('responseStatus')==0:
                                            flash("Unable to connect with server. Please Try again.")
                                            data_status["responseStatus"] =4
                                            return data_status

                                        # payin_balance_queryset = PayinBalances.objects(userId=str(userId),transactionAPIId=str(payInPaymentGatewayId),currentBalance__gte=float(amount)).modify(dec__currentBalance=float(amount),new=True)
                                        # if payin_balance_queryset==None:
                                        #     flash("insufficient Merchant Payin Balance.")
                                        #     return redirect(url_for("wallet_credits_debits.credit_to_wallet"))

                                        # latest_user_queryset = Users.objects(id=userId).first()
                                        # actuallBalance = latest_user_queryset.walletBalance
                                        # updateAmount = float(actuallBalance)-float(amount)
                                        # latest_user_queryset.update(walletBalance = updateAmount)
                                        # print(actuallBalance,"actuallBalance")

                                        # payinCurrentBalance=payin_balance_queryset.currentBalance
                                        # latest_previousPayinBalance=float(payinCurrentBalance)+float(amount)
                                        # payin_balance_queryset.update(previousBalance=round(float(latest_previousPayinBalance),2),updatedOn=datetime.datetime.now())

                                        # latest_user_queryset = Users.objects(id=str(userId),walletBalance__gte=float(amount)).modify(dec__walletBalance=float(amount),new=True)
                                        # if latest_user_queryset==None:
                                        #     flash("insufficient Merchant Payin Balance.")
                                        #     return redirect(url_for("wallet_credits_debits.credit_to_wallet"))

                                        # updateAmount = latest_user_queryset.walletBalance
                                        # actuallBalance = float(updateAmount)+float(amount)

                                        payinbalancelogs_queryset=PayinBalanceLogs(
                                            transactionAPIId=str(payInPaymentGatewayId),
                                            userId=str(userId),
                                            previousBalance=balanceResult.get('transactionPreviousBalance'),
                                            currentBalance=balanceResult.get('transactionCurrentBalance'),
                                            orderId=orderId,
                                            amount=round(float(amount),2),
                                            grandTotal=round(float(amount),2),
                                            transferType="Debit",
                                            userType="admin",
                                            transactionId=transactionUniqueId,
                                            createdOn=datetime.datetime.now(),
                                            status=1
                                            ).save()

                                    wallet_credit_table = WalletTransactions(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        patternId = patternId,
                                        creditType = "Debit",
                                        userType = "admin",
                                        comment = comment,
                                        paymentGatewayId = str(payInPaymentGatewayId),
                                        transactionId = transactionUniqueId,
                                        paymentType = "wallet",
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=balanceResult.get('userPreviousBalance'),
                                        currentBalance=balanceResult.get('userCurrentBalance'),
                                        remarks = "",
                                        orderId = orderId,
                                        customerName = "admin",
                                        customerEmail = "admin@appservices.tech",
                                        customerPhonenumber = "",
                                        agent = "",
                                        location = "",
                                        platform = "",
                                        paymentLink = "",
                                        errorMessage = "",
                                        paymentChannel = "",
                                        bankRefId = "",
                                        cardmasked = "",
                                        customerVpa = "",
                                        commissionCharges = {},
                                        status = 1
                                        )
                                    save_table = wallet_credit_table.save()
                                    currentBalance=0
                                    previousBalance=0
                                    latest_admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                                    if latest_admin_overall_balance_queryset:
                                        updatePayinBalance = float(latest_admin_overall_balance_queryset.payinBalance)+float(amount)
                                        currentBalance = float(updatePayinBalance)
                                        previousBalance = float(latest_admin_overall_balance_queryset.payinBalance)

                                        latest_admin_overall_balance_queryset.update(
                                            payinBalance = updatePayinBalance,
                                            updatedOn = datetime.datetime.now()
                                            )
                                    else:
                                        currentBalance=amount
                                        previousBalance=0
                                        admin_overall_balance_table = AdminOverallBalances(
                                            adminId=adminId,
                                            payinBalance=amount,
                                            payoutBalance=0,
                                            createdOn = datetime.datetime.now(),
                                            status = 1
                                            ).save()
                                    admin_log_balance_table = AdminLogBalances(
                                        adminId=adminId,
                                        userId = userId,
                                        transferType = transferType,
                                        walletType = "Credit",
                                        previousBalance = previousBalance,
                                        currentBalance = currentBalance,
                                        comment=comment,
                                        amount=amount,
                                        createdOn = datetime.datetime.now(),
                                        status = 1
                                        ).save()
                                    flash("Amount debited from Merchant Payin Wallet Successfully!")
                                    try:
                                        mail_subject = "Payin balance debit from "+str(user_queryset.fullName)+" wallet to admin wallet"
                                        recipients_list = [admin_recieve_email]
                                        template_name = "emails/wallet_credit_debit.html"
                                        trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                        mail_data = {
                                        "amount":round(float(amount),2),
                                        "transactionUniqueId":transactionUniqueId,
                                        "merchantName":str(user_queryset.fullName),
                                        "transferType":transferType,
                                        "walletType":walletType,
                                        "trnsactionDate":trnsactionDate,
                                        "adminName":adminName,
                                        "comment":comment,
                                        "orderId":orderId
                                        }
                                        send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                    except Exception as e:
                                        pass
                                    data_status["responseStatus"] =1
                                    return data_status
                            elif transferType == "Payout":
                                if not user_queryset.patternId.payoutPaymentGatewayId:
                                    flash("Payout Api Not Assigned.")
                                    data_status["responseStatus"] =4
                                    return data_status
                                    
                                payOutPaymentGatewayId = str(user_queryset.patternId.payoutPaymentGatewayId.id)
        
                                if walletType == "Credit":
                                    if float(admin_payoutBalance)<float(amount):
                                        flash("insufficient Admin Payout Balance.")
                                        data_status["responseStatus"] =4
                                        return data_status


                                    # latest_user_queryset = Users.objects(id=userId).first()
                                    # actuallBalance = latest_user_queryset.payoutBalance
                                    # updateAmount = float(actuallBalance)+float(amount)
                                    # latest_user_queryset.update(payoutBalance = updateAmount)
                                    balanceResult=user_payout_balance_update(str(userId),float(amount),"Credit",str(payOutPaymentGatewayId))
                                    if balanceResult.get('responseStatus')==0:
                                        flash("Unable to connect with server. Please Try again.")
                                        data_status["responseStatus"] =4
                                        return data_status

                                    # latest_user_queryset = Users.objects(id=str(userId)).modify(inc__payoutBalance=float(amount),new=True)
                                    # updateAmount = latest_user_queryset.payoutBalance
                                    # actuallBalance = float(updateAmount)-float(amount)

                                    print("before query set reacord creation")
                                    fund_transfer_table = FundTransfers(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        transactionAPIId = payOutPaymentGatewayId,
                                        transferType = "Credit",
                                        userType = "admin",
                                        narration = comment,
                                        transactionUniqueId = transactionUniqueId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=balanceResult.get('userPreviousBalance'),
                                        currentBalance=balanceResult.get('userCurrentBalance'),
                                        uniqueRequestNumber = "",
                                        beneficiaryName = "admin",
                                        beneficiaryMail = "admin@appservices.tech",
                                        beneficiaryPhone = "",
                                        accountIFSCCode = "",
                                        fundTransferType = "admin",
                                        accountType = "",
                                        accountNumber = "",
                                        paymentMode = "wallet",
                                        bankBranch = "",
                                        bankName = "",
                                        errorMessage = "",
                                        internalId = "",
                                        pgOrderId = "",
                                        apiType = "web",
                                        merchantReferenceNumber = orderId,
                                        commissionCharges = {},
                                        status = 1
                                        )
                                    save_table = fund_transfer_table.save()
                                    
                                    # latest_payout_balances_queryset = PayoutBalances.objects(userId=userId,transactionAPIId=payOutPaymentGatewayId).first()
                                    # if latest_payout_balances_queryset:
                                    #     updatepayout_balance_queryset = PayoutBalances.objects(userId=str(userId),transactionAPIId=str(payOutPaymentGatewayId)).modify(inc__currentBalance=float(amount),new=True)
                                    #     payoutCurrentBalance=updatepayout_balance_queryset.currentBalance
                                    #     latest_previousPayoutBalance=float(payoutCurrentBalance)-float(amount)
                                    #     updatepayout_balance_queryset.update(previousBalance=round(float(latest_previousPayoutBalance),2),updatedOn=datetime.datetime.now())
                                        
                                    payoutbalancelog_queryset=PayoutBalanceLogs(
                                        userId =str(userId),
                                        transactionAPIId =str(payOutPaymentGatewayId),
                                        previousBalance = round(float(balanceResult.get('transactionPreviousBalance')),2),
                                        currentBalance = round(float(balanceResult.get('transactionCurrentBalance')),2),
                                        amount=round(float(amount),2),
                                        grandTotal=round(float(amount),2),
                                        orderId=orderId,
                                        transferType = "Credit",
                                        userType = "admin",
                                        transactionId = transactionUniqueId,
                                        createdOn = datetime.datetime.now(),
                                        status = 1
                                        ).save()
                                    # else:
                                    #     payoutsavetable=PayoutBalances(
                                    #         userId = userId,
                                    #         transactionAPIId = payOutPaymentGatewayId,
                                    #         previousBalance = 0,
                                    #         currentBalance = float(amount),
                                    #         createdOn = datetime.datetime.now(),
                                    #         status = 1
                                    #         ).save()

                                    #     payoutbalancelog_queryset=PayoutBalanceLogs(
                                    #         userId =str(userId),
                                    #         transactionAPIId =str(payOutPaymentGatewayId),
                                    #         previousBalance = 0,
                                    #         currentBalance = round(float(amount),2),
                                    #         amount=round(float(amount),2),
                                    #         grandTotal=round(float(amount),2),
                                    #         orderId=orderId,
                                    #         transferType = "Credit",
                                    #         userType = "admin",
                                    #         transactionId = transactionUniqueId,
                                    #         createdOn = datetime.datetime.now(),
                                    #         status = 1
                                    #         ).save()


                                    latest_admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                                    if latest_admin_overall_balance_queryset:
                                        updatePayoutBalance = float(latest_admin_overall_balance_queryset.payoutBalance)-float(amount)

                                        currentBalance = float(updatePayoutBalance)
                                        previousBalance = float(latest_admin_overall_balance_queryset.payoutBalance)

                                        latest_admin_overall_balance_queryset.update(
                                            payoutBalance = updatePayoutBalance,
                                            updatedOn = datetime.datetime.now()
                                            )
                                        admin_log_balance_table = AdminLogBalances(
                                            adminId=adminId,
                                            userId = userId,
                                            transferType = transferType,
                                            walletType = "Debit",
                                            previousBalance = previousBalance,
                                            currentBalance = currentBalance,
                                            comment=comment,
                                            amount=amount,
                                            createdOn = datetime.datetime.now(),
                                            status = 1
                                            ).save()
                                    flash("Amount credited to merchant payout wallet successfully!")
                                    try:
                                        mail_subject = "Payout balance Credit to "+str(user_queryset.fullName)+" wallet from admin wallet"
                                        recipients_list = [admin_recieve_email]
                                        template_name = "emails/wallet_credit_debit.html"
                                        trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                        mail_data = {
                                        "amount":round(float(amount),2),
                                        "transactionUniqueId":transactionUniqueId,
                                        "merchantName":str(user_queryset.fullName),
                                        "transferType":transferType,
                                        "walletType":walletType,
                                        "trnsactionDate":trnsactionDate,
                                        "adminName":adminName,
                                        "comment":comment,
                                        "orderId":orderId
                                        }
                                        send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                    except Exception as e:
                                        pass

                                    data_status["responseStatus"] =1
                                    return data_status
                                else:

                                    # latest_payout_balances_queryset = PayoutBalances.objects(userId=userId,transactionAPIId=payOutPaymentGatewayId).first()
                                    # if latest_payout_balances_queryset:
                                    #     latest_previousPayoutBalance = float(latest_payout_balances_queryset.currentBalance)
                                    # else:
                                    #     latest_previousPayoutBalance=0

                                    # if float(latest_previousPayoutBalance)<float(amount):
                                    #     flash("insufficient Merchant Payout Balance.")
                                    #     return redirect(url_for("wallet_credits_debits.credit_to_wallet"))

                                    # if latest_payout_balances_queryset:
                                    #     balanceResult=user_payout_balance_update(str(userId),float(amount),"Debit",str(payOutPaymentGatewayId))
                                    #     if balanceResult.get('responseStatus')==0:
                                    #         flash("insufficient Merchant Payout Balance.")
                                    #         return redirect(url_for("wallet_credits_debits.credit_to_wallet"))

                                        # updatepayout_balance_queryset = PayoutBalances.objects(userId=str(userId),transactionAPIId=str(payOutPaymentGatewayId),currentBalance__gte=float(amount)).modify(dec__currentBalance=float(amount),new=True)
                                        # if updatepayout_balance_queryset==None:
                                        #     flash("insufficient Merchant Payout Balance.")
                                        #     return redirect(url_for("wallet_credits_debits.credit_to_wallet"))

                                        # payoutCurrentBalance=updatepayout_balance_queryset.currentBalance
                                        # latest_previousPayoutBalance=float(payoutCurrentBalance)+float(amount)
                                        # updatepayout_balance_queryset.update(previousBalance=round(float(latest_previousPayoutBalance),2),updatedOn=datetime.datetime.now())

                                    latest_user_queryset = Users.objects(id=str(userId),payoutBalance__gte=float(amount)).modify(dec__payoutBalance=float(amount),new=True)
                                    if latest_user_queryset==None:
                                        flash("insufficient Merchant Payout Balance.")
                                        data_status["responseStatus"] =4
                                        return data_status

                                    updateAmount = latest_user_queryset.payoutBalance
                                    actuallBalance = float(updateAmount)+float(amount)

                                        # latest_user_queryset = Users.objects(id=userId).first()
                                        # actuallBalance = latest_user_queryset.payoutBalance
                                        # updateAmount = float(actuallBalance)-float(amount)
                                        # latest_user_queryset.update(payoutBalance = updateAmount)

                                        # payoutbalancelog_queryset=PayoutBalanceLogs(
                                        #     userId =str(userId),
                                        #     transactionAPIId =str(payOutPaymentGatewayId),
                                        #     previousBalance = round(float(balanceResult.get('transactionPreviousBalance')),2),
                                        #     currentBalance = round(float(balanceResult.get('transactionCurrentBalance')),2),
                                        #     amount=round(float(amount),2),
                                        #     grandTotal=round(float(amount),2),
                                        #     orderId=orderId,
                                        #     transferType = "Debit",
                                        #     userType = "admin",
                                        #     transactionId = transactionUniqueId,
                                        #     createdOn = datetime.datetime.now(),
                                        #     status = 1
                                        #     ).save()
                                    

                                    fund_transfer_table = FundTransfers(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        transactionAPIId = payOutPaymentGatewayId,
                                        transferType = "Debit",
                                        userType = "admin",
                                        narration = comment,
                                        transactionUniqueId = transactionUniqueId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=float(actuallBalance),
                                        currentBalance=float(updateAmount),
                                        uniqueRequestNumber = "",
                                        beneficiaryName = "admin",
                                        beneficiaryMail = "admin@appservices.tech",
                                        beneficiaryPhone = "",
                                        accountIFSCCode = "",
                                        fundTransferType = "admin",
                                        accountType = "",
                                        accountNumber = "",
                                        paymentMode = "wallet",
                                        bankBranch = "",
                                        bankName = "",
                                        errorMessage = "",
                                        internalId = "",
                                        pgOrderId = "",
                                        apiType = "web",
                                        merchantReferenceNumber = orderId,
                                        commissionCharges = {},
                                        status = 1
                                        )
                                    save_table = fund_transfer_table.save()
                                    currentBalance=0
                                    previousBalance=0
                                    latest_admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
                                    if latest_admin_overall_balance_queryset:
                                        updatePayoutBalance = float(latest_admin_overall_balance_queryset.payoutBalance)+float(amount)
                                        currentBalance = float(updatePayoutBalance)
                                        previousBalance = float(latest_admin_overall_balance_queryset.payoutBalance)

                                        latest_admin_overall_balance_queryset.update(
                                            payoutBalance = updatePayoutBalance,
                                            updatedOn = datetime.datetime.now()
                                            )
                                    else:
                                        currentBalance=amount
                                        previousBalance=0
                                        admin_overall_balance_table = AdminOverallBalances(
                                            adminId=adminId,
                                            payoutBalance=amount,
                                            payinBalance=0,
                                            createdOn = datetime.datetime.now(),
                                            status = 1
                                            ).save()
                                    admin_log_balance_table = AdminLogBalances(
                                        adminId=adminId,
                                        userId = userId,
                                        transferType = transferType,
                                        walletType = "Credit",
                                        previousBalance = previousBalance,
                                        currentBalance = currentBalance,
                                        comment=comment,
                                        amount=amount,
                                        createdOn = datetime.datetime.now(),
                                        status = 1
                                        ).save()

                                flash("Amount debited from merchant payout wallet successfully!")
                                try:
                                    mail_subject = "Payout balance debit from "+str(user_queryset.fullName)+" wallet to admin wallet"
                                    recipients_list = [admin_recieve_email]
                                    template_name = "emails/wallet_credit_debit.html"
                                    trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                    mail_data = {
                                    "amount":round(float(amount),2),
                                    "transactionUniqueId":transactionUniqueId,
                                    "merchantName":str(user_queryset.fullName),
                                    "transferType":transferType,
                                    "walletType":walletType,
                                    "trnsactionDate":trnsactionDate,
                                    "adminName":adminName,
                                    "comment":comment,
                                    "orderId":orderId
                                    }
                                    send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                except Exception as e:
                                    pass
                                data_status["responseStatus"] = 1
                                return data_status
                            elif transferType == "Usdt":
                                if walletType == "Credit":
                                    new_user_queryset = Users.objects(id=userId).first()
                                    updateAmount=0
                                    actuallBalance=0
                                    if new_user_queryset.usdtBalance:
                                        latest_user_queryset = Users.objects(id=str(userId)).modify(inc__usdtBalance=float(amount),new=True)
                                        updateAmount = latest_user_queryset.usdtBalance
                                        actuallBalance = float(updateAmount)-float(amount)
                                    else:
                                        new_user_queryset.update(usdtBalance=float(amount))
                                        actuallBalance=0
                                        updateAmount=float(amount)

                                    UsdtTransactions_qry = UsdtTransactions(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        transferType = "Credit",
                                        userType = "admin",
                                        narration = comment,
                                        transactionUniqueId = transactionUniqueId,
                                        orderId = orderId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=actuallBalance,
                                        currentBalance=updateAmount,
                                        status = 1
                                        )
                                    save_table = UsdtTransactions_qry.save()
                                    
                                    flash("Amount credited to merchant usdt wallet successfully!")
                                    try:
                                        mail_subject = "Usdt balance Credit to "+str(user_queryset.fullName)+" wallet"
                                        recipients_list = [admin_recieve_email]
                                        template_name = "emails/wallet_credit_debit.html"
                                        trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                        mail_data = {
                                        "amount":round(float(amount),2),
                                        "transactionUniqueId":transactionUniqueId,
                                        "merchantName":str(user_queryset.fullName),
                                        "transferType":transferType,
                                        "walletType":walletType,
                                        "trnsactionDate":trnsactionDate,
                                        "adminName":adminName,
                                        "comment":comment,
                                        "orderId":orderId
                                        }
                                        send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                    except Exception as e:
                                        pass

                                    data_status["responseStatus"] = 1
                                    return data_status
                                else:
                                    latest_user_queryset = Users.objects(id=userId).first()
                                    actuallBalance1 = latest_user_queryset.usdtBalance
                                    if float(actuallBalance1)<float(amount):
                                        flash("insufficient Merchant Usdt Balance.")
                                        data_status["responseStatus"] = 4
                                        return data_status
                                    
                                    latest_user_queryset = Users.objects(id=str(userId),usdtBalance__gte=float(amount)).modify(dec__usdtBalance=float(amount),new=True)
                                    if latest_user_queryset==None:
                                        flash("insufficient Merchant Usdt Balance.")
                                        data_status["responseStatus"] = 4
                                        return data_status
                                    updateAmount = latest_user_queryset.usdtBalance
                                    actuallBalance = float(updateAmount)+float(amount)

                                    updateAmount = float(actuallBalance)-float(amount)
                                    latest_user_queryset.update(usdtBalance = updateAmount)
                                    UsdtTransactions_qry = UsdtTransactions(
                                        createdBy=adminId,
                                        userId = userId,
                                        amount = amount,
                                        grandTotal = amount,
                                        transferType = "Debit",
                                        userType = "admin",
                                        narration = comment,
                                        transactionUniqueId = transactionUniqueId,
                                        orderId = orderId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=actuallBalance,
                                        currentBalance=updateAmount,
                                        status = 1
                                        )
                                    save_table = UsdtTransactions_qry.save()

                                flash("Amount debited from merchant usdt wallet successfully!")
                                try:
                                    mail_subject = "Usdt balance debit from "+str(user_queryset.fullName)+" wallet"
                                    recipients_list = [admin_recieve_email]
                                    template_name = "emails/wallet_credit_debit.html"
                                    trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                    mail_data = {
                                    "amount":round(float(amount),2),
                                    "transactionUniqueId":transactionUniqueId,
                                    "merchantName":str(user_queryset.fullName),
                                    "transferType":transferType,
                                    "walletType":walletType,
                                    "trnsactionDate":trnsactionDate,
                                    "adminName":adminName,
                                    "comment":comment,
                                    "orderId":orderId
                                    }
                                    send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                except Exception as e:
                                    pass
                                data_status["responseStatus"] = 1
                                return data_status
                            elif transferType == "Commission":
                                if walletType == "Credit":
                                    new_user_queryset = Users.objects(id=userId).first()
                                    updateAmount=0
                                    actuallBalance=0
                                    if new_user_queryset.commissionBalance:
                                        latest_user_queryset = Users.objects(id=str(userId)).modify(inc__commissionBalance=float(amount),new=True)
                                        updateAmount = latest_user_queryset.commissionBalance
                                        actuallBalance = float(updateAmount)-float(amount)
                                    else:
                                        new_user_queryset.update(commissionBalance=float(amount))
                                        actuallBalance=0
                                        updateAmount=float(amount)

                                    user_commission_table = UserCommissions(
                                        adminId=adminId,
                                        userId = userId,
                                        totalAmount = amount,
                                        transferType = "Credit",
                                        comment = comment,
                                        transactionId = transactionUniqueId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=actuallBalance,
                                        currentBalance=updateAmount,
                                        status = 1
                                        )
                                    save_table = user_commission_table.save()
                                    
                                    flash("Amount credited to merchant commission wallet successfully!")
                                    try:
                                        mail_subject = "Commission balance Credit to "+str(user_queryset.fullName)+" wallet"
                                        recipients_list = [admin_recieve_email]
                                        template_name = "emails/wallet_credit_debit.html"
                                        trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                        mail_data = {
                                        "amount":round(float(amount),2),
                                        "transactionUniqueId":transactionUniqueId,
                                        "merchantName":str(user_queryset.fullName),
                                        "transferType":transferType,
                                        "walletType":walletType,
                                        "trnsactionDate":trnsactionDate,
                                        "adminName":adminName,
                                        "comment":comment,
                                        "orderId":""
                                        }
                                        send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                    except Exception as e:
                                        pass

                                    data_status["responseStatus"] = 1
                                    return data_status
                                else:
                                    latest_user_queryset = Users.objects(id=userId).first()
                                    actuallBalance1 = latest_user_queryset.commissionBalance
                                    if float(actuallBalance1)<float(amount):
                                        flash("insufficient Merchant Commission Balance.")
                                        data_status["responseStatus"] = 4
                                        return data_status
                                    
                                    latest_user_queryset = Users.objects(id=str(userId),commissionBalance__gte=float(amount)).modify(dec__commissionBalance=float(amount),new=True)
                                    if latest_user_queryset==None:
                                        flash("insufficient Merchant Commission Balance.")
                                        data_status["responseStatus"] = 4
                                        return data_status
                                    updateAmount = latest_user_queryset.commissionBalance
                                    actuallBalance = float(updateAmount)+float(amount)

                                    updateAmount = float(actuallBalance)-float(amount)
                                    latest_user_queryset.update(commissionBalance = updateAmount)
                                    user_commission_table = UserCommissions(
                                        adminId=adminId,
                                        userId = userId,
                                        totalAmount = amount,
                                        transferType = "Debit",
                                        comment = comment,
                                        transactionId = transactionUniqueId,
                                        createdOn = datetime.datetime.now(),
                                        previousBalance=actuallBalance,
                                        currentBalance=updateAmount,
                                        status = 1
                                        )
                                    save_table = user_commission_table.save()

                                flash("Amount debited from merchant commission wallet successfully!")
                                try:
                                    mail_subject = "Commission balance debit from "+str(user_queryset.fullName)+" wallet"
                                    recipients_list = [admin_recieve_email]
                                    template_name = "emails/wallet_credit_debit.html"
                                    trnsactionDate = datetime.datetime.now().astimezone(ist_timezone).strftime("%d-%m-%Y %I:%M %p")
                                    mail_data = {
                                    "amount":round(float(amount),2),
                                    "transactionUniqueId":transactionUniqueId,
                                    "merchantName":str(user_queryset.fullName),
                                    "transferType":transferType,
                                    "walletType":walletType,
                                    "trnsactionDate":trnsactionDate,
                                    "adminName":adminName,
                                    "comment":comment,
                                    "orderId":""
                                    }
                                    send_asynchronous_email(mail_subject, recipients_list, template_name, mail_data)
                                except Exception as e:
                                    pass
                                data_status["responseStatus"] = 1
                                return data_status
                    except Exception as e:
                        flash("Unable to credit amount!!")
                        app.logger.error(traceback.format_exc())
                        data_status["responseStatus"] = 4
                        return data_status
                        # return render_template("super_admin_templates/wallet_credits_debits.html")
                else:
                    flash("Required fields are missing!!")
                    data_status["responseStatus"] = 4
                    return data_status
                    # return render_template("super_admin_templates/wallet_credits_debits.html")
            else:
                print("form",form.errors)
                data_status["result"] = form.errors
                data_status["responseStatus"] = 0
                return data_status
    except Exception as e:
        app.logger.error(traceback.format_exc())
        error = "Unable to credit amount!!"
        flash("Unable to credit.")
        data_status["responseStatus"] = 4
        return data_status

@wallet_credits_debits.route("/debit_from_wallet", methods=["POST","GET"])
@adminid_access_token_required
def debit_from_wallet():
    try:
        redirectTo = request.args.get("redirectTo","Debit")
        if redirectTo:
            redirectval = redirectTo
        else:
            redirectval = "Debit"

        if not session.get("adminId"):
            return redirect("admin_login")
        adminId = session.get("adminId")
        if request.method == "GET":
            usersList = []
            patternsList = []

            patterns_queryset = Patterns.objects(status__in=[0,1]).order_by("-id").all()
            for each_pattern in patterns_queryset:
                pattern_dict = fetching_pattern_details(each_pattern)
                patternsList.append(pattern_dict)

            users_queryset = Users.objects(status__in=[1]).order_by("-id")
            for each_user in users_queryset:
                userDict = fetching_user_details(each_user)
                usersList.append(userDict)

            return render_template("super_admin_templates/wallet_credits_debits.html",
                usersList=usersList,
                patternsList=patternsList,
                redirectval=redirectval,
                )

        if request.method == "POST":
            userId = request.form.get("userId","")
            amount = request.form.get("amount",0)
            patternId = request.form.get("patternId","")
            walletType = request.form.get("walletType","")
            comment = request.form.get("comment","")
            transactionUniqueId = "TXN"+random_digit_generate(16)

            if userId and amount and patternId and walletType and comment:
                try:
                    user_queryset = Users.objects(id=userId).first()
                    if user_queryset:
                        if walletType == "Wallet":
                            userBalance = float(user_queryset.walletBalance)
                            userUpdateBalance = float(user_queryset.walletBalance) - float(amount)
                            if userBalance >= float(amount):
                                wallet_debit_table = WalletTransactions(
                                    createdBy=adminId,
                                    userId = userId,
                                    amount = amount,
                                    patternId = patternId,
                                    creditType = "Debit",
                                    userType = "admin",
                                    comment = comment,
                                    transactionId = transactionUniqueId,
                                    paymentType = "wallet",
                                    previousBalance=userBalance,
                                    currentBalance=userUpdateBalance,
                                    createdOn = datetime.datetime.now(),
                                    status = 1,
                                    )
                                save_table = wallet_debit_table.save()
                                if save_table:
                                    user_queryset.update(walletBalance= userUpdateBalance)
                            else:
                                flash("Merchant balance is in-sufficient!!")
                                return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))
                        elif walletType == "Payout":
                            previousBalance = float(user_queryset.payoutBalance)
                            userUpdateBalance = float(user_queryset.payoutBalance) - float(amount)
                            if previousBalance >= float(amount):
                                payout_table = FundTransfers(
                                    userId=userId,
                                    amount=amount,
                                    transferType="Debit",
                                    userType = "admin",
                                    narration=comment,
                                    transactionUniqueId = transactionUniqueId,
                                    createdOn = datetime.datetime.now(),
                                    previousBalance=previousBalance,
                                    currentBalance=userUpdateBalance,
                                    status = 1
                                    )
                                save_payout_table = payout_table.save()
                                if save_payout_table:
                                    user_queryset.update(payoutBalance= userUpdateBalance)
                            else:
                                flash("Merchant balance is in-sufficient!!")
                                return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))

                        flash("Amount debited from wallet successfully!")
                        return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))
                        
                    else:
                        flash("Invaild user id!!")
                        return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))
                except Exception as e:
                    flash("Unable to debit amount!!")
                    app.logger.error(traceback.format_exc())
                    return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))
                    # return render_template("super_admin_templates/wallet_credits_debits.html")
            else:
                flash("Required fields are missing!!")
                return redirect(url_for("wallet_credits_debits.debit_from_wallet",redirectTo="Debit"))
                # return render_template("super_admin_templates/wallet_credits_debits.html")
    except Exception as e:
        app.logger.error(traceback.format_exc())
        error = "Unable to debit amount!!"
        return render_template("super_admin_templates/wallet_credits_debits.html",error=error)

############### Bank Holidays ################
@wallet_credits_debits.route("/add_bank_holiday",methods=["POST","GET"])
@adminid_access_token_required
def add_bank_holiday():
    try:
        if not session.get("adminId"):
            return redirect("admin_login")
        adminId = session.get("adminId")
        permissionsList = check_permissions(adminId,"bankHolidaysPermissions")
        if "add" in permissionsList:
            if request.method == "POST":
                occasion = request.form.get("occasion","")
                selectDate = request.form.get("selectDate","")

                if occasion and selectDate:
                    try:
                        bank_holidays_table = BankHolidays(
                            adminId=adminId,
                            occasion = occasion,
                            selectDate = selectDate,
                            createdOn = datetime.datetime.now(),
                            status = 1,
                            )
                        save_table = bank_holidays_table.save()

                        flash("Bank holiday saved successfully!")
                        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
                    except Exception as e:
                        flash("Unable to save bank holiday right details!!")
                        app.logger.error(traceback.format_exc())
                        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
                else:
                    flash("Required fields are missing!!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
        else:
            flash("Staff member does not have given create bank holiday permissions!!")
            return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
    except Exception as e:
        app.logger.error(traceback.format_exc())
        error = "Unable to save bank holiday details!!"
        return render_template("super_admin_templates/bank_holidays_list.html",error=error,redirectTo="Bankholiday")


@wallet_credits_debits.route("/update_bank_holiday",methods=["POST","GET"])
@adminid_access_token_required
def update_bank_holiday():
    if not session.get("adminId"):
        return redirect("admin_login")
    permissionsList = check_permissions(session.get("adminId"),"bankHolidaysPermissions")
    if "edit" in permissionsList:
        try:
            bankHolidayId = request.args.get("bankHolidayId","")
            if request.method == "POST":
                occasion = request.form.get("occasion","")
                selectDate = request.form.get("selectDate","")

                if occasion and selectDate:
                    bank_holiday_queryset = BankHolidays.objects(id=bankHolidayId,status__in=[0,1]).first()
                    if bank_holiday_queryset:
                        bank_holiday_queryset.update(
                            occasion = occasion,
                            selectDate = selectDate
                            )
                        flash("Bank holiday updated successfully!")
                        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
                    else:
                        flash("Invaild id!!")
                        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
                else:
                    flash("Required fields are missing!!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
        except Exception as e:
            app.logger.error(traceback.format_exc())
            error = "Unable to update bank holiday details!!"
            flash(error)
            return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
    else:
        flash("Staff member does not have given update bank holiday permissions!!")
        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))


def fetching_bank_holiday_details(bank_holiday_queryset):
    bank_holiday_dict = {}
    try:
        bank_holiday_dict={
        "id":str(bank_holiday_queryset.id),
        "occasion":bank_holiday_queryset.occasion
        }
        if bank_holiday_queryset.status==1:
            bank_holiday_dict["actionText"] = "Active"
        else:
            bank_holiday_dict["actionText"] = "Deactive"

        if bank_holiday_queryset.createdOn:
            bank_holiday_dict["createdOn"] = bank_holiday_queryset.createdOn.strftime("%m-%d-%Y")
        else:
            bank_holiday_dict["createdOn"] = ""

        if bank_holiday_queryset.selectDate:
            bank_holiday_dict["selectDate"] = bank_holiday_queryset.selectDate.strftime("%m-%d-%Y")
        else:
            bank_holiday_dict["selectDate"] = ""
    except Exception as e:
        app.logger.error(traceback.format_exc())
    return bank_holiday_dict

@wallet_credits_debits.route("/get_bank_holidays_list",methods=["POST","GET"])
@adminid_access_token_required
def get_bank_holidays_list():
    if not session.get("adminId"):
        return redirect("admin_login")
    bank_holidays_list = []
    
    adminId = session.get("adminId")
    permissionsList = check_permissions(session.get("adminId"),"bankHolidaysPermissions")
    if "view" in permissionsList:
        try:
            redirectTo = request.args.get("redirectTo","Bankholiday")
            if redirectTo:
                redirectval = redirectTo
            else:
                redirectval = "Bankholiday"
            search_element = request.form.get("search_element","")

            page = request.args.get(get_page_parameter(), type=int, default=1)
            page_start,page_end=fetch_limit_length_based_on_page_index(page,10)

            bank_holidays_queryset = BankHolidays.objects(status__in=[0,1]).order_by("-id")
            if search_element:
                bank_holidays_queryset = bank_holidays_queryset.filter(Q(occasion__icontains=search_element))
            length = bank_holidays_queryset.count()
            bank_holidays_queryset=bank_holidays_queryset[page_start:page_end]

            for each_bank_holiday in bank_holidays_queryset:
                bank_holiday_dict = fetching_bank_holiday_details(each_bank_holiday)
                bank_holidays_list.append(bank_holiday_dict)

            
            pagination = Pagination(
                page=page,
                total=length,
                record_occasion='Bankholidays',
                per_page=10,
                alignment="right"
                )
            return render_template("super_admin_templates/bank_holidays_list.html",
                bank_holidays_list=bank_holidays_list,
                redirectval=redirectval,
                pagination=pagination,
                search_element=search_element
                )
        except Exception as e:
            app.logger.error(traceback.format_exc())
            error = "Unable to fetch bank holidays details!!"
            return render_template("super_admin_templates/bank_holidays_list.html", 
                error=error,
                bank_holidays_list=bank_holidays_list,
                pagination=pagination,
                search_element=search_element
                )
    else:
        flash("Staff member does not have given view bank holidays permissions!!")
        return render_template("super_admin_templates/bank_holidays_list.html")

@wallet_credits_debits.route("/update_bank_holiday_status",methods=["POST","GET"])
@adminid_access_token_required
def update_bank_holiday_status():
    if not session.get("adminId"):
        return redirect("admin_login")
    permissionsList = check_permissions(session.get("adminId"),"bankHolidaysPermissions")
    if "edit" in permissionsList:
        bankHolidayId = request.args.get("bankHolidayId","")

        if bankHolidayId:
            try:
                bank_holiday_queryset = BankHolidays.objects(id=bankHolidayId,status__in=[0,1]).first()
                if bank_holiday_queryset:
                    if bank_holiday_queryset.status == 0:
                        bank_holiday_queryset.update(status=1)
                        flash("Bank holiday activated successfully!")
                    elif bank_holiday_queryset.status == 1:
                        bank_holiday_queryset.update(status=0)
                        flash("Bank holiday deactivated successfully!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
                else:
                    flash("Invaild id!!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
            except Exception as e:
                app.logger.error(traceback.format_exc())
                return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
        else:
            flash("Required field is missing!!")
            return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
    else:
        flash("Staff member does not have given update status bank holiday permissions!!")
        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))

@wallet_credits_debits.route("/delete_dispute",methods=["GET"])
@adminid_access_token_required
def delete_dispute():
    try:
        if not session.get("adminId"):
            return redirect("admin_login")
        permissionsList = check_permissions(session.get("adminId"),"bankHolidaysPermissions")
        if "delete" in permissionsList:
            if request.method == "GET":
                bankHolidayId = request.args.get("bankHolidayId","")
                bank_holiday_queryset = BankHolidays.objects(id=bankHolidayId,status__in=[0,1]).first()
                if bank_holiday_queryset:
                    bank_holiday_queryset.update(status=2)
                    flash("Bank holiday deleted successfully!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list"))
                else:
                    flash("Invaild id!!")
                    return redirect(url_for("wallet_credits_debits.get_bank_holidays_list"))
        else:
            flash("Staff member does not have given delete bank holiday permissions!!")
            return redirect(url_for("wallet_credits_debits.get_bank_holidays_list",redirectTo="Bankholiday"))
    except Exception as e:
        app.logger.error(traceback.format_exc())
        flash("Unable to delete bank holiday!!")
        return redirect(url_for("wallet_credits_debits.get_bank_holidays_list"))


@wallet_credits_debits.route("/pattern_based_merchants",methods=["POST"])
@adminid_access_token_required
@csrf.exempt
def pattern_based_merchants():
    data_status = {"responseStatus":0,"result":""}
    merchantsList = []
    try:
        patternId = request.form.get("patternId","")

        merchants_queryset = Users.objects(patternId=patternId).order_by("-id").all()
        for each_merchant in merchants_queryset:
            merchantDict = fetching_user_details(each_merchant)
            merchantsList.append(merchantDict)
        data_status["responseStatus"]=1
        data_status["result"]="Merchants data fetched successfully!"
        data_status["merchantsList"]=merchantsList
        return data_status
    except Exception as e:
        app.logger.error(traceback.format_exc())
        data_status["result"]="Unable to fetch merchants data!!"
        return data_status

@wallet_credits_debits.route("/get_admin_balances",methods=["POST"])
@adminid_access_token_required
def get_admin_balances():
    data_status = {"responseStatus":0,"result":""}
    merchantsList = []
    adminId=request.form.get('adminId')
    try:
        if adminId:
            admin_overall_balance_queryset = AdminOverallBalances.objects(status__in=[1]).first()
            if not admin_overall_balance_queryset:
                admin_payinBalance=0
                admin_payoutBalance=0
            else:
                admin_payinBalance=float(admin_overall_balance_queryset.payinBalance)
                admin_payoutBalance=float(admin_overall_balance_queryset.payoutBalance)
            data_status["responseStatus"]=1
            data_status["result"]="Merchants data fetched successfully!"
            data_status["admin_payinBalance"]="{:.2f}".format(float(admin_payinBalance))
            data_status["admin_payoutBalance"]="{:.2f}".format(float(admin_payoutBalance))
            return data_status
        else:
            data_status["result"]="invalid Admin"
            data_status["admin_payinBalance"]='0.00'
            data_status["admin_payoutBalance"]='0.00'
            return data_status
    except Exception as e:
        app.logger.error(traceback.format_exc())
        data_status["result"]="Unable to fetch merchants data!!"
        data_status["admin_payinBalance"]='0.00'
        data_status["admin_payoutBalance"]='0.00'
        return data_status


