import log from "../config/log";
import jsSHA from "jssha";
import CONSTANTS from "../config/constants";
import { Request, Response } from "express";
import axios from "axios";
import querystring from "querystring";
import crypto from "crypto";
import CustomRequest from "../types/requestType";
import tenantDB from "../models/tenant.model";
import duesDB from "../models/dues.model";
import getDueDescription from "../utils/getDueDescription";
import clientDB from "../models/client.model";
import occupancyDB from "../models/occupancy.model";
import propertyDB from "../models/property.model";
import moveOutDB from "../models/moveOut.model";
import moveOutDuesDB from "../models/moveOutDues.model";

const payu: any = {};
payu.generatehash = async (req: Request, res: Response) => {
  const C = "Payu Controller";
  const F = "generatehash";
  try {
    const { hash } = req.body;
    if (hash == "" || hash.length == 0) {
      log.info(`[${C}], [${F}], Hash Value [${hash}], No Hash Found`);
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }
    const HashBody = hash + process.env.PAYU_SALT;
    const HashObj = new jsSHA("SHA-512", "TEXT");
    HashObj.update(HashBody);
    const hashedPassword = HashObj.getHash("HEX");
    log.info(`[${C}], [${F}], Hash [${hash}] , Hash successfully shared`);
    //after succesfull hashing of hash
    return res.status(200).json({
      msg: `Request was successfull`,
      data: hashedPassword,
      isSuccess: true,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

payu.webPayment = async (req: CustomRequest, res: Response) => {
  const C = "Payu Controller";
  const F = "webPayment";
  try {
    const { email, dueId, ledgerReferenceId, charges=0, mode=2, gstAmount=0 } = req.body;
    const tenantId = req.id;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Tenant Requesting....`
    );

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Tenant Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const due = await duesDB.getById({ id: dueId });
    if (!due) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Due Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: tenantId,
    });
    if (!occupancy) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Occupancy Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const client = await clientDB.getById({
      id: occupancy.clientId,
    });
    if (!client) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const property = await propertyDB.getById({
      id: occupancy.propId,
    });
    if (!property) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Property Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const key = process.env.PAYU_KEY;
    const salt = process.env.PAYU_SALT;

    const surl = process.env.WEB_CHECKOUT_SUCCESS_URL;
    const furl = process.env.WEB_CHECKOUT_FAILURE_URL;
    const udf1 = `${client.name}(${property.name})`;
    const udf2 = client.mobile;
    const udf3 = `${property.gId}_${tenantId}`;
    const udf4 = dueId;
    const udf5 = `${ledgerReferenceId}_${charges}_${gstAmount}`;
    const txnId = Date.now() + udf4;
    const firstName = tenant.name;
    const phone = tenant.mobile;
    const amount = due.balance + Number(charges) + Number(gstAmount);
    const productInfo = due.title
      ? `Payment for ${due.title}`
      : `Payment for ${getDueDescription(due.type)}`;

    const paymentMode = mode === CONSTANTS.TRANSACTION_MODES.UPI ? "upi" : mode === CONSTANTS.TRANSACTION_MODES.NET_BANKING ? "netbanking" : "creditcard|debitcard";

    // const apiEndpoint = "https://test.payu.in/_payment";
    // const PAYU_API_URL = "https://secure.payu.in/_payment"; // Change for production
    const PAYU_API_URL = process.env.PAYU_WEB_CHECKOUT;

    //Step 1: Create Hash String
    const hashString = `${key}|${txnId}|${amount}|${productInfo}|${firstName}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
    const hash = crypto.createHash("sha512").update(hashString).digest("hex");

    log.info(
      `[${C}], [${F}], Client Id [${client.id}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Hash String [${hashString}], UDF1(Client Name) [${udf1}], UDF2(Client Mobile) [${udf2}], UDF3(propertyGid_tenantId) [${udf3}], UDF4(Due Id) [${udf4}], UDF5(LedgerReferenceId_Charges) [${udf5}], Transaction Id [${txnId}], First Name [${firstName}], Mobile [${phone}], Amount [${amount}], Product Info [${productInfo}],  Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Tenant Requesting....`
    );

    //Step 2: Send Redirect Form Data
    const payuFormData = {
      key: key,
      txnid: txnId,
      amount,
      productInfo,
      firstName,
      email,
      phone,
      surl: surl,
      furl: furl,
      hash,
      service_provider: "payu_paisa",
      //enforce_paymethod: "upi",
      enforce_paymethod: paymentMode,
      udf1,
      udf2,
      udf3,
      udf4,
      udf5,
    };

    // Generate HTML Form for Redirection
    let formHtml = `<form id="payuForm" action="${PAYU_API_URL}" method="POST">`;
    for (const [key, value] of Object.entries(payuFormData)) {
      formHtml += `<input type="hidden" name="${key}" value="${value}">`;
    }
    formHtml += `</form>`;

    return res.send(formHtml);
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

payu.webPaymentX = async (req: CustomRequest, res: Response) => {
  const C = "Payu Controller";
  const F = "webPaymentX";
  try {
    let { email = 'kipinn.com@gmail.com', amount, dueId, ledgerReferenceId, charges=0, mode=2, gstAmount=0, isBookingPayment=false } = req.body;
    // email = 'kipinn.com@gmail.com';
    if (!email || email.trim() === "") {
      email = 'kipinn.com@gmail.com';
    }
    const tenantId = req.id;
    const clientId = req.clientId;
    let transAmount = amount;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Is Evicted [${req.isEvicted}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Transaction Amount [${transAmount}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Is Booking Payment [${isBookingPayment}] Tenant Requesting....`
    );
    if(!req.clientId) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Is Booking Payment [${isBookingPayment}], No Client Id Found in Request`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Is Booking Payment [${isBookingPayment}], No Tenant Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    let dueIds = dueId.join(",");

    //let totalAmount = 0;
    let totalAmount = transAmount;
    let dueType= CONSTANTS.DUES_TYPES.RENT;
    if (dueId && dueId.length > 0) {
      for (let id of dueId) {
        let due = await duesDB.getById({ id });
        if (req.isEvicted) due = await moveOutDuesDB.getById({ id });
        if (!due) {
          log.info(
            `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], Mode [${mode}], No Due Found with this Id [${id}]`
          );
          return res
            .status(400)
            .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
        }
        dueType= due.type;
        //totalAmount += due.balance;
      }
    }
    
    const client = await clientDB.getById({
      id: clientId,
    });
    if (!client) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    // const occupancy = await occupancyDB.getByTenantId({
    //   tenantId: tenantId,
    // });
    //Pallav - Multi tenant senerio
    let occupancy = await occupancyDB.getByTenantIdAndClientId({
      tenantId: tenantId,
      clientId: clientId,
    });
    
    if (req.isEvicted) {
      occupancy = await moveOutDB.getByTenantIdAndClientId({
        tenantId: tenantId,
        clientId: clientId,
      });
    }

    if (!occupancy) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Transaction Amount [${totalAmount}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Is Booking Payment [${isBookingPayment}], No Occupancy Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    // const client = await clientDB.getById({
    //   id: occupancy.clientId,
    // });
    // if (!client) {
    //   log.info(
    //     `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Client Found`
    //   );
    //   return res
    //     .status(400)
    //     .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    // }

    const property = await propertyDB.getById({
      id: occupancy.propId,
    });
    if (!property) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Transaction Amount [${totalAmount}], Charges [${charges}], Mode [${mode}], Is Booking Payment [${isBookingPayment}], No Property Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const key = process.env.PAYU_KEY;
    const salt = process.env.PAYU_SALT;

    let surl = process.env.WEB_CHECKOUT_SUCCESS_URL;
    let furl = process.env.WEB_CHECKOUT_FAILURE_URL;
    if (client?.paymentLinkBaseUrl && client?.paymentLinkBaseUrl.trim() !== "") {
          surl = `${client?.paymentLinkBaseUrl.trim()}/payment-success`;
          furl = `${client?.paymentLinkBaseUrl.trim()}/payment-failed`;
    }
    const udf1 = `${client.name}(${property.name})`;
    const udf2 = client.mobile;
    const udf3 = `${property.gId}_${tenantId}_${req.isEvicted}`;
    const udf4 = dueIds;
    let udf5 = `${ledgerReferenceId[0]}_${charges}_${gstAmount}`;
    if (isBookingPayment) {
      udf5 = `${'BOOKINGLINK'}_${charges}_${gstAmount}`;
    }
    // const txnId = Date.now() + udf4;
    const txnId = Date.now() + tenant.id;
    const firstName = tenant.name;
    const phone = tenant.mobile;
    const amountPay = totalAmount + Number(charges) + Number(gstAmount);
    //const productInfo = `Payment for ${getDueDescription(dueType)}`;
    let productInfo = `Payment for `;
    if(true == isBookingPayment){
      productInfo += `Booking`;
    } else if(dueId && dueId.length == 1){
      productInfo += `${getDueDescription(dueType)}`;
    } else {
      productInfo += `pending dues`;
    }

    const paymentMode = mode === CONSTANTS.TRANSACTION_MODES.UPI ? "upi" : mode === CONSTANTS.TRANSACTION_MODES.NET_BANKING ? "netbanking" : "creditcard|debitcard";

    // const apiEndpoint = "https://test.payu.in/_payment";
    // const PAYU_API_URL = "https://secure.payu.in/_payment"; // Change for production
    const PAYU_API_URL = process.env.PAYU_WEB_CHECKOUT;

    //Step 1: Create Hash String
    const hashString = `${key}|${txnId}|${amountPay}|${productInfo}|${firstName}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
    const hash = crypto.createHash("sha512").update(hashString).digest("hex");

    log.info(
      `[${C}], [${F}], Client Id [${client.id}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Hash String [${hashString}], UDF1(Client Name) [${udf1}], UDF2(Client Mobile) [${udf2}], UDF3(propertyGid_tenantId) [${udf3}], UDF4(Due Id) [${udf4}], UDF5(LedgerReferenceId_Charges) [${udf5}], Transaction Id [${txnId}], First Name [${firstName}], Mobile [${phone}], Amount [${amountPay}], Product Info [${productInfo}],  Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Is Booking Payment [${isBookingPayment}], Tenant Requesting....`
    );

    //Step 2: Send Redirect Form Data
    const payuFormData = {
      key: key,
      txnid: txnId,
      amount: amountPay,
      productInfo,
      firstName,
      email,
      phone,
      surl: surl,
      furl: furl,
      hash,
      service_provider: "payu_paisa",
      //enforce_paymethod: "upi",
      enforce_paymethod: paymentMode,
      udf1,
      udf2,
      udf3,
      udf4,
      udf5,
    };

    // Generate HTML Form for Redirection
    let formHtml = `<form id="payuForm" action="${PAYU_API_URL}" method="POST">`;
    for (const [key, value] of Object.entries(payuFormData)) {
      formHtml += `<input type="hidden" name="${key}" value="${value}">`;
    }
    formHtml += `</form>`;

    return res.send(formHtml);
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

payu.AppPayment = async (req: CustomRequest, res: Response) => {
  const C = "Payu Controller";
  const F = "AppPayment";
  try {
    //let { email = 'kipinn.com@gmail.com', amount, dueId, ledgerReferenceId, charges=0, mode=2, gstAmount=0, isBookingPayment=false } = req.body;
    let { encryptedId, email = 'kipinn.com@gmail.com', amount, customerDetails, dueId, ledgerReferenceId='APP', charges = 0, mode = 2, gstAmount = 0, payingFor = CONSTANTS.PAYING_FOR.APP } = req.body;
    // email = 'kipinn.com@gmail.com';
    if (!email || email.trim() === "") {
      email = 'kipinn.com@gmail.com';
    }
    if(!Number(mode)) {
      if(mode === 'card') {
        mode = CONSTANTS.TRANSACTION_MODES.CARD;
      } else if(mode === 'netBanking') {
        mode = CONSTANTS.TRANSACTION_MODES.NET_BANKING;
      } else {
        mode = CONSTANTS.TRANSACTION_MODES.UPI;
      }
    }
    let isEvicted = false;
    let tenant = await occupancyDB.getByGIdX({ gId: encryptedId });
    if (!tenant) {
      log.info(
        `[${C}], [${F}], Encrypted Id [${encryptedId}], No GID Found In occupancy, Checking MoveOut Table`
      );

      tenant = await moveOutDB.getByGIdX({ gId: encryptedId });
      if (!tenant) {
        log.info(
         `[${C}], [${F}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Tenant Found`);

        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      isEvicted = true;
    }
    const tenantId = tenant?.tenantId;
    const clientId = tenant.clientId;
    let transAmount = amount;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Is Evicted [${isEvicted}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Transaction Amount [${transAmount}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Paying For [${payingFor}], Tenant Requesting....`
    );
    // if(!req.clientId) {
    //   log.info(
    //     `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Client Id Found in Request`
    //   );
    //   return res
    //     .status(400)
    //     .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    // }

    

    // let dueIds = dueId.join(",");
    let dueIdsArray = dueId.split(",");  // convert string → array
    let dueIds = dueIdsArray.join(",");  // ensure proper format
    //log.info(JSON.stringify(dueIds));
    //let totalAmount = 0;
    let totalAmount = transAmount;
    let dueType= CONSTANTS.DUES_TYPES.RENT;
    if (dueIdsArray && dueIdsArray.length > 0) {
      for (let id of dueIdsArray) {
        let due = await duesDB.getById({ id });
        if (isEvicted) due = await moveOutDuesDB.getById({ id });
        if (!due) {
          log.info(
            `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], Mode [${mode}], No Due Found with this Id [${id}]`
          );
          return res
            .status(400)
            .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
        }
        dueType= due.type;
        //totalAmount += due.balance;
      }
    }
    
    const client = await clientDB.getById({
      id: clientId,
    });
    if (!client) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    //Pallav - Multi tenant senerio
    let occupancy = await occupancyDB.getByTenantIdAndClientId({
      tenantId: tenantId,
      clientId: clientId,
    });
    
    if (isEvicted) {
      occupancy = await moveOutDB.getByTenantIdAndClientId({
        tenantId: tenantId,
        clientId: clientId,
      });
    }

    if (!occupancy) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Client Id [${clientId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Transaction Amount [${totalAmount}], Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], No Occupancy Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const property = await propertyDB.getById({
      id: occupancy.propId,
    });
    if (!property) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Transaction Amount [${totalAmount}], Charges [${charges}], Mode [${mode}], No Property Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }
    let tenantDetail = await tenantDB.getById({id: tenantId});

    const key = process.env.PAYU_KEY;
    const salt = process.env.PAYU_SALT;

    let surl = `${process.env.PAYU_APP_WEB_PAYMENT_BASE_URL}/status`;
    let furl = `${process.env.PAYU_APP_WEB_PAYMENT_BASE_URL}/status`;
    if (client?.paymentLinkBaseUrl && client?.paymentLinkBaseUrl.trim() !== "") {
          surl = `${client?.paymentLinkBaseUrl.trim()}/payment-success`;
          furl = `${client?.paymentLinkBaseUrl.trim()}/payment-failed`;
    }
    const udf1 = `${client.name}(${property.name})`;
    const udf2 = client.mobile;
    const udf3 = `${property.gId}_${tenantId}_${isEvicted}`;
    const udf4 = dueIds;
    let udf5 = `${ledgerReferenceId[0]}_${charges}_${gstAmount}`;
    if (Number(payingFor) === CONSTANTS.PAYING_FOR.WEB_LINK) {
      udf5 = `PAYVIALINK_${charges}_${gstAmount}`;
    } else if (Number(payingFor) === CONSTANTS.PAYING_FOR.WEB_BOOKING_LINK) {
      udf5 = `BOOKINGLINK_${charges}_${gstAmount}`;
    } else if (Number(payingFor) === CONSTANTS.PAYING_FOR.APP_WEB_LINK) {
      udf5 = `PAYVIAAPPLINK_${charges}_${gstAmount}`;
    }
    // const txnId = Date.now() + udf4;
    const txnId = Date.now() + tenantDetail.id;
    const firstName = `${tenantDetail.name}`;
    const phone = tenantDetail.mobile;
    const amountPay = Number(totalAmount) + Number(charges) + Number(gstAmount);
    //const productInfo = `Payment for ${getDueDescription(dueType)}`;
    let productInfo = `Payment for `;
    if(dueId && dueId.length == 1){
      productInfo += `${getDueDescription(dueType)}`;
    } else {
      productInfo += `pending dues`;
    }

    const paymentMode = mode === CONSTANTS.TRANSACTION_MODES.UPI ? "upi" : mode === CONSTANTS.TRANSACTION_MODES.NET_BANKING ? "netbanking" : "creditcard|debitcard";

    const PAYU_API_URL = process.env.PAYU_WEB_CHECKOUT;

    //Step 1: Create Hash String
    const hashString = `${key}|${txnId}|${amountPay}|${productInfo}|${firstName}|${email}|${udf1}|${udf2}|${udf3}|${udf4}|${udf5}||||||${salt}`;
    const hash = crypto.createHash("sha512").update(hashString).digest("hex");

    log.info(
      `[${C}], [${F}], Client Id [${client.id}], Tenant Id [${tenantId}], Email [${email}], Due Id [${dueId}], Ledger Reference Id [${ledgerReferenceId}], Hash String [${hashString}], UDF1(Client Name) [${udf1}], UDF2(Client Mobile) [${udf2}], UDF3(propertyGid_tenantId) [${udf3}], UDF4(Due Id) [${udf4}], UDF5(LedgerReferenceId_Charges) [${udf5}], Transaction Id [${txnId}], First Name [${firstName}], Mobile [${phone}], Amount [${amountPay}], Product Info [${productInfo}],  Charges [${charges}], GST Amount [${gstAmount}], Mode [${mode}], Tenant Requesting....`
    );

    //Step 2: Send Redirect Form Data
    const payuFormData = {
      key: key,
      txnid: txnId,
      amount: amountPay,
      productInfo,
      firstName,
      email,
      phone,
      surl: surl,
      furl: furl,
      hash,
      service_provider: "payu_paisa",
      //enforce_paymethod: "upi",
      enforce_paymethod: paymentMode,
      udf1,
      udf2,
      udf3,
      udf4,
      udf5,
    };

    // Generate HTML Form for Redirection
    let formHtml = `<form id="payuForm" action="${PAYU_API_URL}" method="POST">`;
    for (const [key, value] of Object.entries(payuFormData)) {
      formHtml += `<input type="hidden" name="${key}" value="${value}">`;
    }
    formHtml += `</form>`;

    return res.send(formHtml);
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

export default payu;
