import axios from "axios";
import fs from "fs";
import fsPromises from "fs/promises";
import { Response } from "express";
import CONSTANTS from "../config/constants";
import log from "../config/log";
import tenantDB from "../models/tenant.model";
import CustomRequest from "../types/requestType";
import eqaroTenantsDB from "../models/eqaroTenants.model";
import moment, { now } from "moment";
import eqaroCoApplicantsDB from "../models/eqaroCoApplicants.model";
import eqaroAPIs from "../utils/eqaroAPIs";
import {
  addAadhaarNumberToSignzy,
  uploadAadhaarToSignzy,
  uploadAadhaarToSignzyCoApplicant,
  verifyOTPFromSignzy,
} from "../utils/client/id_verification/signzy";
import {
  addAadhaarNumberToCashfree,
  addAadhaarNumberToCashfreeForCoApplicant,
  uploadAadhaarToCashfree,
  uploadAadhaarToCashfreeCoApplicant,
  verifyOTPFromCashfree,
  verifyOTPFromCashfreeForCoApplicant,
} from "../utils/client/id_verification/cashfree";
import serviceProviderDB from "../models/serviceProvider.model";
import occupancyDB from "../models/occupancy.model";
import documentDB from "../models/document.model";
import ipAddressDB from "../models/ipAddress.model";
import eqaroMainEligibilityCheck from "../utils/eqaroMainEligibilityCheck";
import { json } from "stream/consumers";
import otpDB from "../models/otp.model";
import sendSMS from "../utils/sendSMS";
import eqaroLandlordsDB from "../models/eqaroLandlords.model";
import clientDB from "../models/client.model";
import eqaroPropertiesDB from "../models/eqaroProperties.model";
import { completeEqaroPayment } from "../utils/completeEqaroPayment";
import { numberToBoolean } from "../utils/numberToBoolean";

const eqaro: any = {};

eqaro.TenantLogin = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "TenantLogin";

  try {
    let { mobile, profession, monthlyIncome } = req.body;
    const userType = req.userType;
    log.info(
      `[${C}], [${F}], Mobile [${mobile}], Occupaction [${profession}], Income [${monthlyIncome}], Type [${userType}]`
    );

    let response = null;
    let status = CONSTANTS.EQARO_TENANT_STATUS.REGISTERED;
    const tenant = await tenantDB.getByMobile({ mobile });
    if (!tenant) {
      log.info(`[${C}], [${F}], Mobile [${mobile}], Tenant not found`);
      return res.status(400).json({
        msg: "Tenant not found",
        isSuccess: false,
      });
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: tenant.id,
    });

    if (!occupancy) {
      log.info(`[${C}], [${F}], Mobile [${mobile}], Occupancy not found`);
      return res.status(400).json({
        msg: "Occupancy not found",
        isSuccess: false,
      });
    }

    const eqaroProperty = await eqaroPropertiesDB.getByPropId({
      propId: occupancy.propId,
    });

    if (!eqaroProperty) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Prop Id [${occupancy.propId}], Property not found in eqaro properties`
      );
      return res.status(400).json({
        msg: "Property not found",
        isSuccess: false,
      });
    }

    // const landlord = await clientDB.getById({
    //   id: occupancy.clientId,
    // });

    // if (!landlord) {
    //   log.info(
    //     `[${C}], [${F}], Mobile [${mobile}], Client Id [${occupancy.clientId}] Client not found`
    //   );
    //   return res.status(400).json({
    //     msg: "Client not found",
    //     isSuccess: false,
    //   });
    // }

    // const landlordMobile = landlord.mobile;

    let eqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenant.id,
    });

    if (!profession) {
      profession = eqaroTenant?.occupation;
    }

    if (!monthlyIncome) {
      monthlyIncome = eqaroTenant?.monthlyIncome;
    }

    const occupationType =
      profession === 1
        ? "Student"
        : profession === 2
        ? "Salaried"
        : "Self Employed";

    let eqaroLandlord = await eqaroLandlordsDB.getByClientId({
      clientId: occupancy.clientId,
    });

    if (!eqaroLandlord) {
      log.info(
        `[${C}], [${F}], Client Id [${occupancy.clientId}], Landlord not found`
      );
      return res.status(400).json({
        msg: "Landlord not found",
        isSuccess: false,
      });
    }
    const landlordMobile = eqaroLandlord.mobile.slice(-10);

    const eqaroTokenExpiresAt = moment(
      eqaroLandlord.tokenExpiresAt,
      "YYYY-MM-DD HH:mm:ss"
    );
    const now = moment();

    if (eqaroTokenExpiresAt.isBefore(now)) {
      log.info(
        `[${C}], [${F}], Landlord Mobile [${landlordMobile}], Landlord token expired, Loginng in landlord`
      );

      const landlordLoginBody = {
        phone: landlordMobile,
        key: "YecbTaNUJpAdFSuUX1HPtNwY3LgJyQRP", // to be shifted to env
      };

      response = await eqaroAPIs.getTokenApi(
        landlordMobile,
        "users/token/landlord/phone",
        landlordLoginBody
      );

      if (response && response.message !== "Not Found") {
        log.info(
          `[${C}], [${F}], Landlord Mobile [${landlordMobile}], landlord login successful`
        );

        await eqaroLandlordsDB.updateAccessTokens({
          mobile: `91${landlordMobile}`,
          accessToken: response.access.token,
          tokenExpiresAt: moment(response.access.expires).format(
            "YYYY-MM-DD HH:mm:ss"
          ),
        });

        log.info(
          `[${C}], [${F}], Landlord Mobile [${landlordMobile}], Landlord token updated successfully, checking if user is registered with eqaro`
        );

        eqaroLandlord = await eqaroLandlordsDB.getByMobile({
          mobile: `91${landlordMobile}`,
        });
      } else {
        log.info(
          `[${C}], [${F}], Landlord Mobile [${landlordMobile}], landlord login failed`
        );
        return res.status(400).json({
          msg: "Landlord login failed",
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Landlord Mobile [${landlordMobile}], Landlord token not expired, checking if user is registered with eqaro`
      );
    }

    const isUserRegisteredBody = {
      phone: `91${mobile}`,
    };

    response = await eqaroAPIs.isUserCheckpostApi(
      mobile,
      eqaroLandlord.accessToken,
      "users/userid",
      isUserRegisteredBody
    );

    if (response && response.data?.profileId) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Tenant found in eqaro database`
      );

      if (!eqaroTenant) {
        log.info(
          `[${C}], [${F}], Mobile [${mobile}], Tenant registered with eqaro, but not in Kipinn, registering tenant in Kipinn.`
        );

        const loginBody = {
          phone: `91${mobile}`,
        };

        const loginresponse = await eqaroAPIs.getTokenApi(
          mobile,
          "users/getUserByPhoneOrEmail",
          loginBody
        );
        if (loginresponse && loginresponse.message !== "Not Found") {
          await eqaroTenantsDB.create({
            tenantId: tenant.id,
            propId: occupancy?.propId || null,
            eqaroUserId: loginresponse?.user?.id || loginresponse?.user[0]?.id,
            eqaroProfileId:
              loginresponse?.user?.profileId ||
              loginresponse?.user[0]?.profileId,
            status: CONSTANTS.EQARO_TENANT_STATUS.REGISTERED,
            occupation: profession,
            mobile: mobile,
            monthlyIncome: monthlyIncome,
            accessToken: loginresponse.tokens.access.token,
            refreshToken: loginresponse.tokens.refresh.token,
            accessTokenExpires: moment(
              loginresponse.tokens.access.expires
            ).format("YYYY-MM-DD HH:mm:ss"),
            refreshTokenExpires: moment(
              loginresponse.tokens.refresh.expires
            ).format("YYYY-MM-DD HH:mm:ss"),
          });

          eqaroTenant = await eqaroTenantsDB.getByTenantId({
            tenantId: tenant.id,
          });
        } else {
          log.info(
            `[${C}], [${F}], Tenant Mobile [${mobile}], Failure to log into tenant in eqaro`
          );
          return res.status(400).json({
            msg: "Internal server error. Please try again later.",
            isSuccess: false,
          });
        }
      }

      const getTenantTokenBody = {
        tenantId: response?.data?.id || eqaroTenant.eqaroUserId,
      };

      response = await eqaroAPIs.postApi(
        mobile,
        eqaroLandlord.accessToken,
        "users/token/tenant",
        getTenantTokenBody
      );
      if (response && response.data?.access) {
        log.info(
          `[${C}], [${F}], Tenant Mobile [${mobile}], Tenant Token retrieved successfully`
        );

        await eqaroTenantsDB.updateTenantAccessToken({
          tenantId: tenant.id,
          accessToken: response.data.access.token,
          accessTokenExpires: moment(response.data.access.expires).format(
            "YYYY-MM-DD HH:mm:ss"
          ),
        });
      } else {
        log.info(
          `[${C}], [${F}], Tenant Mobile [${mobile}], Failure to get tenant token`
        );
        return res.status(400).json({
          msg: "Internal server error. Please try again later.",
          isSuccess: false,
        });
      }
    } else if (response && response.data.message === "Not Found") {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Tenant not registered with eqaro, Registering tenant`
      );
      if (eqaroTenant) {
        log.info(
          `[${C}], [${F}], Mobile [${mobile}], Tenant found in Kipinn DB, deleting tenant before registering`
        );

        await eqaroTenantsDB.deleteTenant({ tenantId: tenant.id });
      }

      const registerBody = {
        userType: "tenant",
        type: "Individual",
        referencePropertyId: eqaroProperty.propertyId,
        phone: `91${mobile}`,
      };

      // response = await eqaroAPIs.getTokenApi(
      //   mobile,
      //   "auth/register",
      //   registerBody
      // );

      response = await eqaroAPIs.registerTenantApi(
        mobile,
        "users/register/tenant",
        registerBody
      );

      if (response) {
        log.info(
          `[${C}], [${F}], Mobile [${mobile}] Tenant Registered Successfully`
        );

        // await eqaroTenantsDB.create({
        //   tenantId: tenant.id,
        //   eqaroUserId: response.user.id,
        //   eqaroProfileId: response.user.profileId,
        //   status: CONSTANTS.EQARO_TENANT_STATUS.REGISTERED,
        //   occupation: profession,
        //   mobile: mobile,
        //   monthlyIncome: monthlyIncome,
        //   accessToken: response.tokens.access.token,
        //   refreshToken: response.tokens.refresh.token,
        //   accessTokenExpires: moment(response.tokens.access.expires).format(
        //     "YYYY-MM-DD HH:mm:ss"
        //   ),
        //   refreshTokenExpires: moment(response.tokens.refresh.expires).format(
        //     "YYYY-MM-DD HH:mm:ss"
        //   ),
        // });

        await eqaroTenantsDB.create({
          tenantId: tenant.id,
          propId: occupancy?.propId || null,
          eqaroUserId: response.user.id,
          eqaroProfileId: response.user.profileId,
          status: CONSTANTS.EQARO_TENANT_STATUS.REGISTERED,
          occupation: profession,
          mobile: mobile,
          monthlyIncome: monthlyIncome,
          accessToken: response.access.token,
          refreshToken: response.access.token,
          accessTokenExpires: moment(response.access.expires).format(
            "YYYY-MM-DD HH:mm:ss"
          ),
          refreshTokenExpires: moment(response.access.expires).format(
            "YYYY-MM-DD HH:mm:ss"
          ),
        });

        const patchBody = {
          name: tenant.name,
          employmentDetails: {
            employment: occupationType,
            monthlyIncome: monthlyIncome,
          },
        };

        log.info(
          `[${C}], [${F}], Mobile [${mobile}], Occupation Type [${occupationType}] Going to update tenant record in eqaro`
        );
        response = await eqaroAPIs.patchApi(
          mobile,
          response.access.token,
          `users/${response.user.id}`,
          patchBody
        );

        if (!response) {
          log.info(
            `[${C}], [${F}], Mobile [${mobile}] Failure in updating tenant record in eqaro`
          );
          return res.status(400).json({
            msg: "Failure in updating tenant record",
            isSuccess: false,
          });
        } else {
          log.info(
            `[${C}], [${F}], Mobile [${mobile}] Tenant Details Updated Successfully`
          );
        }
      } else {
        log.info(
          `[${C}], [${F}], Mobile [${mobile}], Failure in registering tenant in eqaro`
        );
        return res.status(400).json({
          msg: "Server internal error. Please try later",
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Failure in checking whether tenant is registered or not in eqaro`
      );
      return res.status(400).json({
        msg: "Server internal error. Please try later",
        isSuccess: false,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${mobile}], Tenant token generated successfully`
    );

    const updatedEqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenant.id,
    });

    const tenantStatusBody = {
      phone: `91${mobile}`,
    };

    const statusResponse = await eqaroAPIs.postApi(
      mobile,
      updatedEqaroTenant.accessToken,
      "users/tenant/status",
      tenantStatusBody
    );

    log.info(
      `[${C}], [${F}], Mobile [${mobile}], Status [${status}], Eqaro Status [${statusResponse.data.status.toLowerCase()}] `
    );

    status =
      statusResponse.data.status.toLowerCase() === "none"
        ? CONSTANTS.EQARO_TENANT_STATUS.REGISTERED
        : statusResponse.data.status.toLowerCase() === "basiceligible"
        ? CONSTANTS.EQARO_TENANT_STATUS.BASIC_ELIGIBILITY_VERIFICATION_DONE
        : statusResponse.data.status.toLowerCase() === "eligible"
        ? CONSTANTS.EQARO_TENANT_STATUS.MAIN_ELIGIBILITY_VERIFICATION_DONE
        : statusResponse.data.status.toLowerCase() === "bond"
        ? CONSTANTS.EQARO_TENANT_STATUS.BOND_ISSUED
        : statusResponse.data.status.toLowerCase() === "incomplete"
        ? CONSTANTS.EQARO_TENANT_STATUS.REGISTERED
        : statusResponse.data.status.toLowerCase() === "ineligible"
        ? CONSTANTS.EQARO_TENANT_STATUS.INELIGIBLE
        : 0;

    let errorDetails = {
      msg: "",
      title: "",
    };
    if (statusResponse.data.status === "ineligible") {
      errorDetails = {
        msg: "We regret to inform you that you are currently not eligible for a Rental Bond. Please review the requirements or reach out to us for assistance.",
        title: "Eligibility Criteria Not Met",
      };
    }

    await eqaroTenantsDB.updateStatus({
      tenantId: tenant.id,
      status: status,
    });

    return res.status(200).json({
      msg: "Tenant has been logged-in successfully",
      errorDetails,
      isSuccess: true,
      // data: response.data,
      status: status,
      bondAmount: eqaroProperty.bondAmount,
      isStudent: Number(profession) === 1 ? true : false,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

eqaro.AddCoApplicant = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "AddCoApplicant";

  try {
    const { phone, profession, relation, monthlyIncome } = req.body;
    const id = req.id;

    log.info(
      `[${C}], [${F}], TenantId [${id}], Phone [${phone}], Occupation [${profession}], Relation [${relation}], Monthly Income [${monthlyIncome}]`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId: id });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${id}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    let status = eqaroTenant.status;

    const relationType =
      relation === CONSTANTS.EQARO_COAPPLICANT_RELATION.FATHER
        ? "Father"
        : relation === CONSTANTS.EQARO_COAPPLICANT_RELATION.MOTHER
        ? "Mother"
        : relation === CONSTANTS.EQARO_COAPPLICANT_RELATION.BROTHER
        ? "Brother"
        : "Sister";

    const occupationType =
      profession === 1
        ? "Student"
        : profession === 2
        ? "Salaried"
        : "Self Employed";

    const body = {
      phone: `91${phone}`,
      relation: relationType,
      employmentDetails: {
        employment: occupationType,
        monthlyIncome: monthlyIncome,
      },
    };

    const response = await eqaroAPIs.postApi(
      phone,
      eqaroTenant.accessToken,
      "users/register/applicant",
      body
    );

    if (response) {
      await eqaroCoApplicantsDB.create({
        tenantId: id,
        mobile: phone,
        occupation: profession,
        relation: relation,
        monthlyIncome: monthlyIncome,
      });

      await eqaroTenantsDB.updateCoApplicantId({
        tenantId: id,
        coApplicantId: response.data.user.id,
      });

      await eqaroTenantsDB.updateStatus({
        tenantId: id,
        status: CONSTANTS.EQARO_TENANT_STATUS.COAPPLICANT_REGISTERED,
      });

      status = CONSTANTS.EQARO_TENANT_STATUS.COAPPLICANT_REGISTERED;

      log.info(`[${C}], [${F}], Co-Applicant has been added successfully`);

      return res.status(200).json({
        msg: "Co-Applicant has been added successfully",
        isSuccess: true,
        status: status,
      });
    }

    log.info(`[${C}], [${F}], Failure in adding co-applicant`);

    return res.status(400).json({
      msg: "Failure in adding co-applicant",
      isSuccess: false,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.VerifyPan = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "VerifyPan";

  try {
    const { pan } = req.body;
    const id = req.id;
    const userType = req.userType;
    log.info(
      `[${C}], [${F}], Pan Number [${pan}], Type [${userType}], TenantId [${id}]`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId: id });
    if (!eqaroTenant) {
      log.info(`[${C}], [${F}], TenantId [${id}], Tenant not found`);
      return res.status(400).json({
        msg: "Tenant not found",
        isSuccess: false,
      });
    }

    let status = eqaroTenant.status;

    let isSuccess = true;
    let userId = eqaroTenant.eqaroUserId;
    if (
      Number(eqaroTenant.occupation) ===
      CONSTANTS.EQARO_OCCUPATION_TYPES.STUDENT
    ) {
      userId = eqaroTenant.coApplicantId;
      log.info(`[${C}], [${F}], Co Applicant Id [${userId}]`);
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], User Id [${userId}], Step 1 - Request Consent API`
    );
    const consentBody = {
      userId: userId,
      name: "Consent",
      text: "Consent text will be provided",
    };

    let response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "consent",
      consentBody
    );

    if (response) {
      log.info(`[${C}], [${F}], Tenant Id [${id}], Consent has given.`);
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Step 2 - PAN Card Validation API`
      );
      const panBody = {
        panNo: pan,
        userId: userId,
      };
      response = await eqaroAPIs.postApi(
        eqaroTenant.mobile,
        eqaroTenant.accessToken,
        "pan/validate",
        panBody
      );

      if (response && response.data.status === "Pan card valid") {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Name [${response.data.name}], Aaadhar [${response.data.aadhaar}], Pan has been verified successfully.`
        );
        status = CONSTANTS.EQARO_TENANT_STATUS.PAN_VERIFICATION_DONE;
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Step 3 - Upload PAN Doc API`
        );
        const docBody = {
          userId: userId,
          docs: [
            {
              docType: "pan",
              docId: pan,
            },
          ],
        };
        response = await eqaroAPIs.postApi(
          eqaroTenant.mobile,
          eqaroTenant.accessToken,
          "users/upload/docs",
          docBody
        );
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], isVerified [${response.data[0].isVerified}]`
        );
        if (response && response.data[0].isVerified) {
          log.info(
            `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Step 4 - Basic Eligibilty Check API`
          );

          const { isSuccess, response } = await eqaroAPIs.getApi(
            eqaroTenant.mobile,
            eqaroTenant.accessToken,
            `eligibility/basiccheck/${eqaroTenant.eqaroUserId}`
          );

          if (!isSuccess) {
            let errorMsg =
              "Tenant basic eligibility cannot be verified at this moment. Please try again later";
            let title = "Validation Failed";
            if (response.code === 422) {
              title = "PAN Validation Failed";
              errorMsg = response.message;
            } else if (response.code === 404) {
              title = "PAN Validation Failed";
              errorMsg = response.message;
            }
            log.info(
              `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Error [${errorMsg}]`
            );
            return res.status(400).json({
              title: title,
              msg: errorMsg,
              isSuccess: false,
            });
          } else {
            await eqaroTenantsDB.updateStatus({
              tenantId: id,
              status:
                CONSTANTS.EQARO_TENANT_STATUS
                  .BASIC_ELIGIBILITY_VERIFICATION_DONE,
            });

            status =
              CONSTANTS.EQARO_TENANT_STATUS.BASIC_ELIGIBILITY_VERIFICATION_DONE;

            log.info(
              `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Max Eligibilty [${response.data.maxEligibility}], Status [${response.data.status}], Basic eligibility check.`
            );

            if (response.data.status === "ineligible") {
              return res.status(400).json({
                title: "Max elibility check failed",
                msg: response.data.msg,
                isSuccess: false,
              });
            } else {
              await eqaroTenantsDB.updateStatus({
                tenantId: id,
                status:
                  CONSTANTS.EQARO_TENANT_STATUS
                    .BASIC_ELIGIBILITY_VERIFICATION_DONE,
              });

              status =
                CONSTANTS.EQARO_TENANT_STATUS
                  .BASIC_ELIGIBILITY_VERIFICATION_DONE;
              let data = {
                maxEligibility: response.data.maxEligibility,
                msg: response.data.msg,
              };

              return res.status(200).json({
                msg: "Tenant basic eligibility verified",
                isSuccess: true,
                data: data,
                status: status,
              });
            }
          }
        } else {
          log.info(
            `[${C}], [${F}], Tenant Id [${id}], Type [Upload Document], No response from eqaro API`
          );
          return res.status(400).json({
            msg: "Tenant document cannot be uploaded at this moment",
            isSuccess: false,
          });
        }
      } else {
        log.info(
          `[${C}], [${F}], Pan Number [${pan}], No response from eqaro API`
        );
        return res.status(400).json({
          msg:
            response?.data?.message ||
            "Tenant Pan cannot be verified at this moment",
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${id}], Type [Consent], Failure in consent request`
      );
      return res.status(400).json({
        msg: "Server internal error. Please try again later",
        isSuccess: false,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.TenantEmailConfirmation = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "TenantEmailConfirmation";

  try {
    const { email } = req.body;
    const id = req.id;
    log.info(
      `[${C}], [${F}], TenantId [${id}], Email [${email}], Tenant Email Confirmation Request`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId: id });
    if (!eqaroTenant) {
      log.info(`[${C}], [${F}], TenantId [${id}], Tenant not found`);
      return res.status(400).json({
        msg: "Tenant not found",
        isSuccess: false,
      });
    }

    let isPersonal = eqaroTenant.status >= CONSTANTS.EQARO_TENANT_STATUS.EMPLOYEMENT_VERIFICATION_DONE ? true : false;

    if (!isPersonal) {

      log.info(`[${C}], [${F}], TenantId [${id}], Email [${email}], Work Email, Calling Eqaro Patch API To Update Email`);
      
      let occupationType =
      eqaroTenant.occupation === 1
        ? "Student"
        : eqaroTenant.occupation === 2
        ? "Salaried"
        : "Self Employed";
      let monthlyIncome = eqaroTenant.monthlyIncome;

      if (eqaroTenant.occupation === 1) {
        
        log.info(`[${C}], [${F}], TenantId [${id}], Email [${email}], Occupation [${occupationType}], Is Co-Applicant [True], Calling Eqaro Patch API To Update Co Applicant Email`);

        const coApplicant = await eqaroCoApplicantsDB.getByTenantId({
          tenantId: eqaroTenant.tenantId,
        });
        monthlyIncome = coApplicant?.monthlyIncome || 0;
        occupationType =
          coApplicant?.occupation === 1
            ? "Student"
            : coApplicant?.occupation === 2
            ? "Salaried"
            : "Self Employed";
      }

      const patchBody = {
        employmentDetails: {
          workEmail: email,
          employment: occupationType,
          monthlyIncome: monthlyIncome,
        },
      };
      const userId = eqaroTenant.occupation === 1 ? eqaroTenant.coApplicantId : eqaroTenant.eqaroUserId;
      const response: any = await eqaroAPIs.patchApi(
          eqaroTenant.mobile,
          eqaroTenant.accessToken,
          `users/${userId}`,
          patchBody
      );

      if (!response) {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}] Failure in updating tenant email in eqaro`
        );
        return res.status(400).json({
          msg: "Failure in updating tenant email in Eqaro",
          isSuccess: false,
        });
      } else {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}] Tenant Details Updated Successfully`
        );
      }
    }

    const body = {
      email: email,
    };

    const response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "verify/generateotponmail",
      body
    );

    if (response && response.data.status === "pending") {
      log.info(
        `[${C}], [${F}], TenantId [${id}], Email [${email}], OTP sent successfully`
      );

      return res.status(200).json({
        msg: "OTP sent to the given email",
        isSuccess: true,
        status: eqaroTenant.status,
      });
    } else {
      log.info(
        `[${C}], [${F}], TenantId [${id}], Email [${email}], Error Message [${response.data.message}], Eqaro API Error`
      );
      return res.status(400).json({
        msg: "Tenant Work Confirmation couldn't process at this moment",
        isSuccess: false,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.TenantEmailOTPVerify = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "TenantEmailOTPVerify";

  try {
    const { otp, email } = req.body;
    const tenantId = req.id;
    log.info(
      `[${C}], [${F}], TenantId [${tenantId}], Email [${email}], OTP [${otp}], Tenant Email OTP Verify Request`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenantId,
    });

    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Tennat not found`
      );
      return res.status(400).json({
        msg: "Tennat not found",
        isSuccess: false,
      });
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: tenantId,
    });

    let isPersonal =
      eqaroTenant.status >=
      CONSTANTS.EQARO_TENANT_STATUS.EMPLOYEMENT_VERIFICATION_DONE
        ? true
        : false;

    let status = eqaroTenant.status;

    let body = null;

    if (true === isPersonal) {
      body = {
        email: email,
        code: otp,
        isWorkEmail: false,
      };
    } else {
      //For work email verification
      body = {
        email: email,
        code: otp,
        isWorkEmail: true,
      };
    }

    const response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "verify/verifyotponmail",
      body
    );

    if ("approved" === response?.data?.status) {
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Email [${email}], ${
          isPersonal ? "Personal Email Verified" : "Work Email Verified"
        }`
      );

      status = CONSTANTS.EQARO_TENANT_STATUS.EMPLOYEMENT_VERIFICATION_DONE;

      await eqaroTenantsDB.updateStatus({
        tenantId: tenantId,
        status: status,
      });

      const response = await eqaroMainEligibilityCheck(eqaroTenant);
      if (true === response.isSuccess) {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], isPersonal [${isPersonal}], Main Eligibility Approved`
        );

        if (true === isPersonal) {
          await eqaroTenantsDB.updateStatus({
            tenantId: tenantId,
            status: CONSTANTS.EQARO_TENANT_STATUS.EMAIL_VERIFICATION_DONE,
          });
          status = CONSTANTS.EQARO_TENANT_STATUS.EMAIL_VERIFICATION_DONE;
          const landlord = await eqaroLandlordsDB.getByClientId({
            clientId: occupancy.clientId,
          });

          const isPostpaid =
            landlord.bondPlan === CONSTANTS.EQARO_RENTAL_BOND_PLANS.POSTPAID
              ? true
              : false;

          const eqaroProperty = await eqaroPropertiesDB.getByPropId({
            propId: occupancy.propId,
          });

          if (isPostpaid) {
            const data = await completeEqaroPayment({
              tenantId: tenantId,
              bondAmount: eqaroProperty.bondAmount,
            });

            if (data && data.msg === "Bond Payment Successful") {
              return res.status(200).json({
                msg: "Bond Payment Successful",
                isSuccess: true,
                status: CONSTANTS.EQARO_TENANT_STATUS.PAYMENT_DONE,
              });
            } else if (
              data &&
              data.msg === "Bond Payment Failed, No response from Eqaro"
            ) {
              return res.status(500).json({
                msg: "Bond Payment Failed, No response from Eqaro",
                isSuccess: false,
              });
            } else if (
              data &&
              data.msg === "Bond already exist for this tenant"
            ) {
              return res.status(200).json({
                msg: "Bond already exist for this tenant",
                isSuccess: true,
                bondExist: true,
                status: status,
              });
            } else if (
              data &&
              data.msg ===
                "Bond payment initiation failed due to internal error"
            ) {
              return res.status(400).json({
                msg: "Bond payment initiation failed due to internal error",
                isSuccess: false,
                bondExist: false,
              });
            } else if (
              data &&
              data.msg ===
                "Bond Payment Initiation Failed, No response from Eqaro"
            ) {
              return res.status(500).json({
                msg: "Bond Payment Initiation Failed, No response from Eqaro",
                isSuccess: false,
                bondExist: false,
              });
            } else if (
              data &&
              data.msg ===
                "The Guarantee Value amount must be at least INR 7000"
            ) {
              return res.status(400).json({
                msg: "The Guarantee Value amount must be at least INR 7000",
                isSuccess: false,
                bondExist: false,
              });
            } else {
              return res.status(200).json({
                msg: "Personal email verified successfully, but failed to process bond payment please try again later",
                isSuccess: true,
                bondAmount: response.bondFee,
                status: status || eqaroTenant.status,
              });
            }
          } else {
            return res.status(200).json({
              msg: "Personal email verified successfully",
              isSuccess: true,
              bondAmount: response.bondFee,
              status: status || eqaroTenant.status,
            });
          }
        } else {
          return res.status(200).json({
            msg: "Work email verified successfully",
            isSuccess: true,
            bondAmount: response.bondFee,
            status: response.status || status || eqaroTenant.status,
          });
        }
      } else {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Failure in main eligibility check`
        );

        return res.status(400).json({
          msg: response.msg,
          isSuccess: false,
          bondAmount: 0,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}], Email [${email}], OTP verification failed`
      );

      return res.status(400).json({
        msg: `${
          isPersonal
            ? "Personal email verification failed"
            : "Work email verification failed"
        }`,
        isSuccess: false,
        bondAmount: 0,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.TenantWorkVerifyViaDoc = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "TenantWorkVerifyViaDoc";

  const file = req.file as Express.Multer.File;
  const removeTmpImages = async () => {
    try {
      await fsPromises.unlink(file.path);
    } catch (err) {}
  };

  try {
    const tenantId = req.id;
    const { docType } = req.body;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Doc Type [${docType}], Uploaded File [${JSON.stringify(
        file
      )}]`
    );

    if (!file) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Offer letter not uploaded correctly`
      );
      return res
        .status(400)
        .json({ msg: "Offer letter not uploaded correctly", isSuccess: false });
    }

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Files uploaded, Doc type [${docType}]`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenantId,
    });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], No Eqaro Tenant Found`
      );

      await fsPromises.unlink(file.path);

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

    let status = eqaroTenant.status;

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: eqaroTenant?.tenantId,
    });

    if (!occupancy) {
      log.info(`[${C}], [${F}], Tenant Id [${tenantId}], , No Occupancy Found`);

      await fsPromises.unlink(file.path);

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

    const folderName = `tenant_${occupancy.tenantId}`;
    const folderPath = `uploads/documents/client_${occupancy.clientId}/prop_${occupancy.propId}/room_${occupancy.roomId}_bed_${occupancy.bedId}/${folderName}`;
    const fileExtension = file.mimetype.split("/")[1];
    // const filename = `Offer_letter.${file.mimetype.split("/")[1]}`;
    const filename = `Offer_letter.${fileExtension}`;

    if (!fs.existsSync(folderPath)) {
      await fsPromises.mkdir(folderPath, { recursive: true });
    }

    const oldPath = `uploads/tmp/${file.filename}`;
    const newPath = `${folderPath}/${filename}`;
    const url = `${process.env.UPLOAD_PATH}/documents/client_${occupancy.clientId}/prop_${occupancy.propId}/room_${occupancy.roomId}_bed_${occupancy.bedId}/${folderName}/${filename}`;

    await fsPromises.copyFile(oldPath, newPath);

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Old Path [${oldPath}],New Path [${newPath}], Url [${url}] `
    );

    let userId = eqaroTenant.eqaroUserId;
    if (
      Number(eqaroTenant.occupation) ===
      CONSTANTS.EQARO_OCCUPATION_TYPES.STUDENT
    ) {
      userId = eqaroTenant.coApplicantId;
      log.info(`[${C}], [${F}], Co-Applicant Id [${userId}]`);
    }

    const body = {
      userId: userId,
      docs: [
        {
          docType: "offer_letter",
          isVerified: true,
          docUrl: url,
        },
      ],
    };

    const response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "users/upload/docs",
      body
    );

    if (response && !response.data.code) {
      await eqaroTenantsDB.updateStatus({
        tenantId: tenantId,
        status: CONSTANTS.EQARO_TENANT_STATUS.EMPLOYEMENT_VERIFICATION_DONE,
      });

      status = CONSTANTS.EQARO_TENANT_STATUS.EMPLOYEMENT_VERIFICATION_DONE;

      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Offer letter verified successfully`
      );

      const response = await eqaroMainEligibilityCheck(eqaroTenant);
      if (true === response.isSuccess) {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Main eligibility approved`
        );

        return res.status(200).json({
          msg: "Work email verified successfully",
          isSuccess: true,
          bondAmount: response.bondFee,
          status: response.status || eqaroTenant.status,
        });
      } else {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Failure in main eligibility check`
        );

        return res.status(400).json({
          msg: response.msg,
          isSuccess: false,
          bondAmount: 0,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Document upload API not available at this moment`
      );

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

eqaro.AadharOKYC = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "AadharOKYC";

  try {
    const { IdNumber, isCoApplicant } = req.body;
    const tenantId = req.id;

    const maskedIdNumber = "XXXXXXXX" + IdNumber.slice(-4);

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], ID Number [${maskedIdNumber}], isCoApplicant [${isCoApplicant}], Aadhar OKYC Request`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenantId,
    });

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], ID Number [${maskedIdNumber}], No Tenant Found`
      );
      return res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
        isDown: false,
      });
    }

    const occupancy = await occupancyDB.getByTenantId({
      tenantId,
    });

    const isExists = await documentDB.getIDByType({
      tenantId,
      clientId: occupancy?.clientId,
      type: CONSTANTS.DOCUMENT_TYPES.AADHAAR,
      moveOut: 0,
    });

    // if (isExists && isExists.status === CONSTANTS.DOCUMENT_STATUS.VERIFIED) {
    //   log.info(
    //     `[${C}], [${F}], Tenant Id [${tenantId}], ID Number [${maskedIdNumber}], ID Number Already Exists`
    //   );
    //   return res.status(400).json({
    //     msg: "ID Number Already Exists",
    //     isDown: false,
    //     isSuccess: false,
    //   });
    // }

    const provider = await serviceProviderDB.getActiveByType({
      type: CONSTANTS.SERVICE_PROVIDERS_TYPE.AADHAAR_NUMBER,
    });

    if (!provider) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], ID Number [${maskedIdNumber}], No service provider is active`
      );

      return res.status(400).json({
        msg: "Service is currently unavailable, please try again later.",
        isSuccess: false,
      });
    }

    let providerFunc: any = null;

    if (provider.name === CONSTANTS.SERVICE_PROVIDERS.SIGNZY) {
      providerFunc = addAadhaarNumberToSignzy;
    } else if (provider.name === CONSTANTS.SERVICE_PROVIDERS.CASHFREE) {
      if (isCoApplicant === true) {
        providerFunc = addAadhaarNumberToCashfreeForCoApplicant;
      } else {
        providerFunc = addAadhaarNumberToCashfree;
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], ID Number [${maskedIdNumber}], SP Name [${provider.name}] Invalid service provider`
      );

      return res.status(400).json({
        msg: "Service is currently unavailable, please try again later.",
        isSuccess: false,
      });
    }

    const { isSuccess, isServerError, msg, isDown, requestId, docId } =
      await providerFunc({
        tenantId: Number(tenantId),
        IdNumber,
        maskedIdNumber,
        isExists,
      });

    if (!isSuccess) {
      if (!isServerError) {
        return res.status(400).json({
          msg: msg,
          isSuccess: false,
          isDown,
        });
      } else {
        return res.status(500).json({
          msg: CONSTANTS.MSG.ERROR_MESSAGE,
          isSuccess: false,
          isDown,
        });
      }
    }

    return res.status(200).json({
      msg: "OTP sent to registered mobile number",
      requestId,
      docId,
      maskedIdNumber,
      isSuccess: true,
      status: eqaroTenant.status,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isDown: true,
      isSuccess: false,
    });
  }
};

eqaro.VerifyAadharNumber = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "VerifyAadharNumber";

  try {
    const { requestId, otp, docId, IdNumber, isCoApplicant } = req.body;
    const tenantId = req.id;
    let IP = req.headers["x-forwarded-for"] || req.socket.remoteAddress;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Aadhar Number [${IdNumber}]  Request Id [${requestId}], OTP [${otp}], isCoApplicant [${isCoApplicant}]`
    );

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}],  Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], No Tenant Found`
      );
      res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
        isDown: false,
      });
    }

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "No tenant found with given id",
        isSuccess: false,
      });
    }

    let status = eqaroTenant.status;

    let userId = eqaroTenant.eqaroUserId;
    if (true === isCoApplicant) {
      userId = eqaroTenant.coApplicantId;
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] Co Applicant Id [${userId}]`
      );
    }

    const hitCount = await ipAddressDB.getCountByHour({ ip: IP });

    if (hitCount > 3) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], Hit more than thrice in an hour`
      );

      return res.status(400).json({
        msg: "Service is currently unavailable. Please try to upload aadhaar photo or try agian later.",
        isSuccess: false,
      });
    }

    await ipAddressDB.add({
      userId: tenantId,
      userType: CONSTANTS.USER_TYPE.TENANT,
      ip: IP,
      target: CONSTANTS.IP_ADRESSES_TARGET.AADHAAR_OTP_VERIFICATION,
    });

    const provider = await serviceProviderDB.getActiveByType({
      type: CONSTANTS.SERVICE_PROVIDERS_TYPE.AADHAAR_NUMBER,
    });

    if (!provider) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], No service provider is active`
      );

      return res.status(400).json({
        msg: "Service is currently unavailable, please try again later.",
        isSuccess: false,
      });
    }

    let providerFunc: any = null;

    if (provider.name === CONSTANTS.SERVICE_PROVIDERS.SIGNZY)
      providerFunc = verifyOTPFromSignzy;
    else if (provider.name === CONSTANTS.SERVICE_PROVIDERS.CASHFREE) {
      if (isCoApplicant === true) {
        providerFunc = verifyOTPFromCashfreeForCoApplicant;
      } else {
        providerFunc = verifyOTPFromCashfree;
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], SP Name [${provider.name}] Invalid service provider`
      );

      return res.status(400).json({
        msg: "Service is currently unavailable, please try again later.",
        isSuccess: false,
      });
    }

    const { isServerError, isSuccess, msg, isDown, isTimeout, photo, result } =
      await providerFunc({
        tenantId: Number(tenantId),
        requestId,
        otp,
        docId,
      });

    if (!isSuccess) {
      if (!isServerError) {
        return res.status(400).json({
          msg: msg,
          isSuccess: false,
          isDown,
          isTimeout,
        });
      } else {
        return res.status(500).json({
          msg: CONSTANTS.MSG.ERROR_MESSAGE,
          isSuccess: false,
          isDown,
          isTimeout,
        });
      }
    }

    //Sukhbir - 20th Jan 2025 to make sure there should not be conflict with Eqaro Verification
    const { name, dob, gender, address, care_of, zip, photo_link } = result;

    let genderVal = 0;
    if (gender && gender.toLowerCase() === "m") {
      genderVal = CONSTANTS.GENDER.MALE;
    } else if (gender && gender.toLowerCase() === "f") {
      genderVal = CONSTANTS.GENDER.FEMALE;
    } else {
      genderVal = CONSTANTS.GENDER.OTHER;
    }

    // await tenantDB.updatePersonalInfo({
    //   name: name,
    //   fatherName: care_of?.slice(4) || "",
    //   dob: (dob && moment(dob, "DD-MM-YYYY").format("YYYY-MM-DD")) || null,
    //   gender: genderVal,
    //   address,
    //   id: tenantId,
    //   kycStatus: CONSTANTS.KYC_STATUS.SELFI_UPLOADED,
    // });

    if (isCoApplicant === false) {
      await tenantDB.updatePersonalInfo({
        name: name,
        fatherName: care_of?.slice(4) || "",
        dob: moment(dob, "DD-MM-YYYY").format("YYYY-MM-DD"),
        gender: genderVal,
        address: address,
        id: tenantId,
        kycStatus: CONSTANTS.KYC_STATUS.SELFI_UPLOADED,
      });

      await documentDB.updateStatus({
        id: docId,
        status: CONSTANTS.DOCUMENT_STATUS.VERIFIED,
      });
    } else {
      await eqaroCoApplicantsDB.updatePersonalInfo({
        name: name,
        dob: moment(dob, "DD-MM-YYYY").format("YYYY-MM-DD"),
        id: tenantId,
        email: result.email || null,
      });
    }

    // await documentDB.updateStatus({
    //   id: docId,
    //   status: CONSTANTS.DOCUMENT_STATUS.VERIFIED,
    // });
    /********************* End *********************/

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], Photo [${photo}], Result [${JSON.stringify(
        result
      )}]`
    );

    const body = {
      userId: userId,
      docs: [
        {
          docType: "adhaar",
          docId: IdNumber,
          isVerified: true,
          metadata: JSON.stringify(result),
        },
      ],
    };

    const response = await eqaroAPIs.postApi(
      tenant.mobile,
      eqaroTenant.accessToken,
      "users/upload/docs",
      body
    );

    if (response && !response.data.code) {
      if (
        Number(eqaroTenant.occupation) ===
        CONSTANTS.EQARO_OCCUPATION_TYPES.STUDENT
      ) {
        if (isCoApplicant === true) {
          await eqaroTenantsDB.updateStatus({
            tenantId: tenantId,
            status: CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE,
          });
          status = CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE;
        } else {
          await eqaroTenantsDB.updateStatus({
            tenantId: tenantId,
            status:
              CONSTANTS.EQARO_TENANT_STATUS.STUDENT_AADHAR_VERIFICATION_DONE,
          });
          status =
            CONSTANTS.EQARO_TENANT_STATUS.STUDENT_AADHAR_VERIFICATION_DONE;
        }
      } else {
        await eqaroTenantsDB.updateStatus({
          tenantId: tenantId,
          status: CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE,
        });
        status = CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE;
      }

      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Mobile [${tenant.mobile}], Aadhar verified successfully`
      );

      const updatedTenant = await tenantDB.getById({ id: tenantId });

      const coApplicant = await eqaroCoApplicantsDB.getByTenantId({
        tenantId: tenantId,
      });

      if (
        Number(eqaroTenant.occupation) ===
          CONSTANTS.EQARO_OCCUPATION_TYPES.SELF_EMPLOYED ||
        Number(coApplicant?.occupation) ===
          CONSTANTS.EQARO_OCCUPATION_TYPES.SELF_EMPLOYED
      ) {
        const response = await eqaroMainEligibilityCheck(eqaroTenant);
        if (true === response.isSuccess) {
          log.info(
            `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Main eligibility approved`
          );

          return res.status(200).json({
            msg: "Details fetched sucessfully",
            data: { image: photo || null },
            tenant: updatedTenant,
            isSuccess: true,
            bondAmount: response.bondFee, //hard coded for now
            status: response.status || eqaroTenant.status,
            isSelfEmployed: true,
          });
        } else {
          log.info(
            `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Failure in main eligibility check`
          );

          return res.status(400).json({
            msg: response.msg,
            isSuccess: false,
            bondAmount: 0,
          });
        }
      } else {
        // const updatedTenant = await tenantDB.getById({ id: tenantId });

        log.info(
          `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], Details fetched & sent sucessfully`
        );

        return res.status(200).json({
          msg: "Details fetched sucessfully",
          data: { image: photo || null },
          tenant: updatedTenant,
          isSuccess: true,
          status: status,
          isSelfEmployed: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Request Id [${requestId}], OTP [${otp}], Doc Id [${docId}], Document upload API not available at this moment `
      );

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

    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isDown: true,
      isSuccess: false,
    });
  }
};

eqaro.InitiateBondPayment = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "InitiateBondPayment";

  try {
    const { bondAmount } = req.body;
    const tenantId = req.id;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Bond Amount [${bondAmount}] Initiating Bond Payment`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    const occupancy = await occupancyDB.getByTenantId({ tenantId });
    if (!occupancy) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No occupancy found with given id`
      );
      return res.status(400).json({
        msg: "No occupancy found for given tenant",
        isSuccess: false,
      });
    }

    const eqaroProperty = await eqaroPropertiesDB.getByPropId({
      propId: occupancy.propId,
    });

    if (!eqaroProperty) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Prop Id [${occupancy.propId}], Property not found in eqaro properties`
      );
      return res.status(400).json({
        msg: "Property not found",
        isSuccess: false,
      });
    }

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Prop Id [${
        eqaroProperty.propId
      }],  Rent [${occupancy.rent}], Bond Amount [${
        occupancy.rent * eqaroProperty.bondAmountMul
      }], Property Id [${eqaroProperty.propertyId}]`
    );

    let effectiveBondAmount = occupancy.rent * eqaroProperty.bondAmountMul;
    const body = {
      tenantId: eqaroTenant.eqaroUserId,
      propertyId: eqaroProperty.propertyId,
      bondAmount: effectiveBondAmount,
      type: "buy_bond",
      bondEffectiveDate: moment().format("YYYY-MM-DD"),
    };

    const { isSuccess, response } = await eqaroAPIs.paymentPostApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "paymentGateway/initiate",
      body
    );
    if (isSuccess && response.data.eqaroOrderId) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Bond Effective Date [${occupancy.moveInDate}], Bond OrderId [${response.data.eqaroOrderId}] Bond Payment Initiation Successfull`
      );

      // let respAmount = Number(response.data.amount) / 100;
      // removing /100 as in our case customer wallet should be charged and amount will be in ruppes only
      let respAmount = Number(response.data.amount); 
      await eqaroTenantsDB.updateInitiateBondParams({
        tenantId: tenantId,
        bondFee: respAmount,
        bondEffectiveDate: moment().format("YYYY-MM-DD"),
        orderId: response.data.eqaroOrderId,
        bondAmount: effectiveBondAmount,
      });

      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Bond Fee [${response.data.amount}]`
      );

      return res.status(200).json({
        msg: "Bond Payment Initiation Successfull",
        isSuccess: true,
        bondExist: false,
        status: eqaroTenant.status,
        bondFee: respAmount,
      });
    } else if (response) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Bond Effective Date [${occupancy.moveInDate}], Bond payment initiation failed due to internal error`
      );
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Message [${response.message}]`
      );
      if (response.message === "Bond already exist for this tenant") {
        return res.status(200).json({
          msg: "Bond already exist for this tenant",
          isSuccess: true,
          bondExist: true,
          status: eqaroTenant.status,
        });
      } else {
        return res.status(400).json({
          msg: "Bond payment initiation failed due to internal error",
          isSuccess: false,
          bondExist: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Bond Effective Date [${occupancy.moveInDate}], Bond payment initiation failed, no response from Eqaro`
      );

      return res.status(500).json({
        msg: "Bond Payment Initiation Failed, No response from Eqaro",
        isSuccess: false,
        bondExist: false,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.CompleteBondPayment = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "CompleteBondPayment";

  try {
    const { paymentId, status } = req.body;
    const tenantId = req.id;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], Payment Id [${paymentId}], Payment status [${status}], Completing Bond Payment`
    );

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    let eqaroStatus = eqaroTenant.status;

    const body = {
      tenantId: eqaroTenant.eqaroUserId,
      bondEffectiveDate: moment(eqaroTenant.bondEffectiveDate).format(
        "YYYY-MM-DD"
      ),
      eqaroOrderId: eqaroTenant.orderId,
    };

    const { isSuccess, response } = await eqaroAPIs.paymentPostApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "payment/complete",
      body
    );
    if (isSuccess && response.data.message === "Payment Successful!!") {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Payment Id [${paymentId}], BondId [${response.data.bondId}], Payment status [${status}], Bond Fee [${eqaroTenant.bondFee}], Bond Payment Successful`
      );

      await eqaroTenantsDB.updateCompleteBondParams({
        tenantId: tenantId,
        bondId: response.data.bondId,
        bondExpiryDate: response.data.expiryDate,
      });

      await eqaroTenantsDB.updateStatus({
        tenantId: eqaroTenant.tenantId,
        status: CONSTANTS.EQARO_TENANT_STATUS.PAYMENT_DONE,
      });

      eqaroStatus = CONSTANTS.EQARO_TENANT_STATUS.PAYMENT_DONE;

      return res.status(200).json({
        msg: "Bond Payment Successful",
        isSuccess: true,
        status: eqaroStatus,
      });
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Bond Payment Failed, No response from Eqaro`
      );
      return res.status(500).json({
        msg: "Bond Payment Failed, No response from Eqaro",
        isSuccess: false,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.uploadAadhaar = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "uploadAadhar";

  const files = req.files as Express.Multer.File[];
  const removeTmpImages = async () => {
    for (const file of files) {
      try {
        await fsPromises.unlink(file.path);
      } catch (err) {}
    }
  };

  try {
    let { isCoApplicant } = req.body;
    const tenantId = req.id;

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], isCoApplicant [${isCoApplicant}]`
    );

    isCoApplicant = await numberToBoolean(isCoApplicant);

    log.info(
      `[${C}], [${F}], Tenant Id [${tenantId}], isCoApplicant After conversion [${isCoApplicant}]`
    );

    if (!files) {
      log.info(`[${C}], [${F}], Tenant Id [${tenantId}], No files uploaded`);
      return res
        .status(400)
        .json({ msg: "No files uploaded", isSuccess: false });
    }

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({
      tenantId: tenantId,
    });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], No Eqaro Tenant Found`
      );

      await removeTmpImages();

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

    let status = eqaroTenant.status;

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(`[${C}], [${F}], Tenant Id [${tenantId}], , No Tenant Found`);

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

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: tenant?.id,
    });

    if (!occupancy) {
      log.info(`[${C}], [${F}], Tenant Id [${tenantId}], , No Occupancy Found`);

      await removeTmpImages();

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

    const folderName = `tenant_${occupancy.tenantId}`;
    const folderPath = `uploads/documents/client_${occupancy.clientId}/prop_${occupancy.propId}/room_${occupancy.roomId}_bed_${occupancy.bedId}/${folderName}`;
    const urlBase = folderPath.replace(
      "uploads/",
      `${process.env.UPLOAD_PATH}/`
    );

    if (!fs.existsSync(folderPath)) {
      await fsPromises.mkdir(folderPath, { recursive: true });
    }

    const provider = await serviceProviderDB.getActiveByType({
      type: CONSTANTS.SERVICE_PROVIDERS_TYPE.AADHAAR_UPLOAD,
    });

    if (!provider) {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], , No service provider is active`
      );

      await removeTmpImages();

      return res.status(400).json({
        msg: "Service is currently unavailable, please try again later.",
        isSuccess: false,
      });
    }

    const oldFrontPath = `${process.env.UPLOAD_PATH}/tmp/${files[0].filename}`;
    let oldBackPath = "";
    if (files[1])
      oldBackPath = `${process.env.UPLOAD_PATH}/tmp/${files[1].filename}`;

    let DOB = null;
    let GENDER = 0;
    let ADDRESS = "";
    let NAME = "";
    let RESULT = null;

    if (provider.name === CONSTANTS.SERVICE_PROVIDERS.SIGNZY) {
      let response;
      if (isCoApplicant === true) {
        response = await uploadAadhaarToSignzyCoApplicant({
          tenantId: Number(tenantId),
          oldFrontPath: String(oldFrontPath),
          oldBackPath: String(oldBackPath),
          folderPath,
          urlBase,
          occupancy,
        });
      } else {
        response = await uploadAadhaarToSignzy({
          tenantId: Number(tenantId),
          oldFrontPath: String(oldFrontPath),
          oldBackPath: String(oldBackPath),
          folderPath,
          urlBase,
          occupancy,
        });
      }
      const {
        msg,
        isSuccess,
        isServerError,
        dob,
        genderVal,
        address,
        name,
        result,
      } = response;

      if (!isSuccess) {
        await removeTmpImages();

        if (!isServerError) {
          return res.status(400).json({
            msg: msg,
            isSuccess: false,
          });
        } else {
          return res.status(500).json({
            msg: CONSTANTS.MSG.ERROR_MESSAGE,
            isSuccess: false,
          });
        }
      }
      //Sukbir - Change Variable Name
      DOB = dob;
      GENDER = Number(genderVal) || 0;
      ADDRESS = address;
      NAME = name;
      RESULT = result;
    } else if (provider.name === CONSTANTS.SERVICE_PROVIDERS.CASHFREE) {
      let response;
      if (isCoApplicant === true) {
        response = await uploadAadhaarToCashfreeCoApplicant({
          tenantId: Number(tenantId),
          oldFrontPath: String(oldFrontPath),
          oldBackPath: String(oldBackPath),
          folderPath,
          urlBase,
          occupancy,
        });
      } else {
        response = await uploadAadhaarToCashfree({
          tenantId: Number(tenantId),
          oldFrontPath: String(oldFrontPath),
          oldBackPath: String(oldBackPath),
          folderPath,
          urlBase,
          occupancy,
        });
      }
      const {
        msg,
        isSuccess,
        isServerError,
        yob,
        genderVal,
        address,
        name,
        result,
      } = response;

      if (!isSuccess) {
        await removeTmpImages();

        if (!isServerError) {
          return res.status(400).json({
            msg: msg,
            isSuccess: false,
          });
        } else {
          return res.status(500).json({
            msg: CONSTANTS.MSG.ERROR_MESSAGE,
            isSuccess: false,
          });
        }
      }
      DOB = yob;
      GENDER = Number(genderVal) || 0;
      ADDRESS = address;
      NAME = name;
      RESULT = result;
    }
    if (isCoApplicant === false) {
      await tenantDB.updatePersonalInfo({
        name: NAME,
        fatherName: "",
        dob: moment(DOB, "DD-MM-YYYY").format("YYYY-MM-DD"),
        gender: GENDER,
        address: ADDRESS,
        id: tenantId,
        kycStatus: CONSTANTS.KYC_STATUS.SELFI_UPLOADED,
      });
    } else {
      await eqaroCoApplicantsDB.updatePersonalInfo({
        name: NAME,
        dob: moment(DOB, "DD-MM-YYYY").format("YYYY-MM-DD"),
        tenantId: tenantId,
        email: RESULT?.email || null,
      });
    }

    let userId = eqaroTenant.eqaroUserId;
    if (true === isCoApplicant) {
      userId = eqaroTenant.coApplicantId;
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] Co Applicant Id [${userId}]`
      );
    }

    const body = {
      userId: userId,
      docs: [
        {
          docType: "adhaar",
          docId: RESULT.uid,
          isVerified: true,
          metadata: JSON.stringify(RESULT),
        },
      ],
    };

    const response = await eqaroAPIs.postApi(
      tenant.mobile,
      eqaroTenant.accessToken,
      "users/upload/docs",
      body
    );

    if (response && !response.data.code) {
      if (
        Number(eqaroTenant.occupation) ===
        CONSTANTS.EQARO_OCCUPATION_TYPES.STUDENT
      ) {
        if (isCoApplicant === true) {
          await eqaroTenantsDB.updateStatus({
            tenantId: tenantId,
            status: CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE,
          });
          status = CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE;
        } else {
          await eqaroTenantsDB.updateStatus({
            tenantId: tenantId,
            status:
              CONSTANTS.EQARO_TENANT_STATUS.STUDENT_AADHAR_VERIFICATION_DONE,
          });
          status =
            CONSTANTS.EQARO_TENANT_STATUS.STUDENT_AADHAR_VERIFICATION_DONE;
        }
      } else {
        await eqaroTenantsDB.updateStatus({
          tenantId: tenantId,
          status: CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE,
        });
        status = CONSTANTS.EQARO_TENANT_STATUS.AADHAR_VERIFICATION_DONE;
      }

      const updatedTenant = await tenantDB.getById({ id: tenantId });

      const coApplicant = await eqaroCoApplicantsDB.getByTenantId({
        tenantId,
      });

      if (
        Number(eqaroTenant.occupation) ===
          CONSTANTS.EQARO_OCCUPATION_TYPES.SELF_EMPLOYED ||
        Number(coApplicant?.occupation) ===
          CONSTANTS.EQARO_OCCUPATION_TYPES.SELF_EMPLOYED
      ) {
        const response = await eqaroMainEligibilityCheck(eqaroTenant);
        if (true === response.isSuccess) {
          log.info(
            `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Main eligibility approved`
          );

          return res.status(200).json({
            msg: "Details fetched sucessfully",
            tenant: updatedTenant,
            isSuccess: true,
            bondAmount: response.bondFee,
            status: response.status || eqaroTenant.status,
            isSelfEmployed: true,
          });
        } else {
          log.info(
            `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Failure in main eligibility check`
          );

          return res.status(400).json({
            msg: response.msg,
            isSuccess: false,
            bondAmount: 0,
          });
        }
      } else {
        log.info(
          `[${C}], [${F}], Tenant Id [${tenantId}], Tenant Occupation [${eqaroTenant.occupation}] Aadhar uploaded sucessfully`
        );
        return res.status(200).json({
          msg: "Aahaar uploaded sucessfully",
          tenant: updatedTenant,
          isSuccess: true,
          status: status,
          isSelfEmployed: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Tenant Id [${tenantId}], Document upload API not available at this moment`
      );

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

    await removeTmpImages();

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

eqaro.GenerateBond = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "GenerateBond";

  try {
    const tenantId = req.id;
    let apiTryCount = 1;

    log.info(`[${C}], [${F}], Tenant Id [${tenantId}]`);

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    let status = eqaroTenant.status;

    const occupancy = await occupancyDB.getByTenantId({
      tenantId: eqaroTenant?.tenantId,
    });
    if (!occupancy) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No occupancy found with given id`
      );
      return res.status(400).json({
        msg: "No occupancy found with given id",
        isSuccess: false,
      });
    }

    const hitGenerateBond = async () => {
      const response = await eqaroAPIs.bondGetApi(
        eqaroTenant.mobile,
        eqaroTenant.accessToken,
        `generate/bond/pdf?bondId=${eqaroTenant.bondId}`
      );
      return response;
    };

    let response = await hitGenerateBond();
    while (!response || !response.data) {
      if (apiTryCount < 3) {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Try Count [${apiTryCount}] Failure in generating PDF, Retrying...`
        );

        apiTryCount++;
        response = await hitGenerateBond();
      } else {
        log.info(
          `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Try Count [${apiTryCount}] Failure in generating PDF, Please try again after sometime.`
        );
        return res.status(400).json({
          msg:
            response.msg ||
            "Server internal error. Please try again after sometime.",
          isSuccess: false,
        });
      }
    }

    const contentLength = response.headers["content-length"];
    if (parseInt(contentLength) > 0) {
      const folderName = `tenant_${occupancy.tenantId}`;
      const folderPath = `uploads/documents/client_${occupancy.clientId}/prop_${occupancy.propId}/room_${occupancy.roomId}_bed_${occupancy.bedId}/${folderName}`;
      const fileName = `${eqaroTenant?.tenantId}Bond.pdf`;
      const filePath = `${folderPath}/${fileName}`;

      if (!fs.existsSync(folderPath)) {
        fs.mkdirSync(folderPath, { recursive: true });
      }

      fs.writeFileSync(filePath, response.data);

      const url = `${process.env.UPLOAD_PATH}/documents/client_${occupancy.clientId}/prop_${occupancy.propId}/room_${occupancy.roomId}_bed_${occupancy.bedId}/${folderName}/${fileName}`;

      await eqaroTenantsDB.updateBondPdf({
        tenantId: tenantId,
        bondUrl: url,
      });

      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Bond PDF generated successfully`
      );

      await eqaroTenantsDB.updateStatus({
        tenantId: tenantId,
        status: CONSTANTS.EQARO_TENANT_STATUS.BOND_ISSUED,
      });

      status = CONSTANTS.EQARO_TENANT_STATUS.BOND_ISSUED;

      await documentDB.addDocWithStatus({
        tenantId,
        clientId: occupancy.clientId,
        propId: occupancy.propId,
        roomId: occupancy.roomId,
        type: CONSTANTS.DOCUMENT_TYPES.EQARO_BOND,
        value: url,
        status: CONSTANTS.DOCUMENT_STATUS.VERIFIED,
      });

      return res.status(200).json({
        msg: "Bond PDF generated successfully",
        isSuccess: true,
        url: url,
        status: status,
      });
    } else {
      log.info(
        `[${C}], [${F}], PDF data is empty for bond ID [${eqaroTenant.bondId}]`
      );
      return res.status(400).json({
        msg: "Generated PDF is empty",
        isSuccess: false,
      });
    }
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.GetTenantStatusByPhone = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "GetTenantStatusByPhone";

  try {
    const tenantId = req.id;

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    const body = {
      phone: eqaroTenant.mobile,
    };

    const response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "users/tenant/status",
      body
    );

    if (response && response.data) {
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Tenant status fetched successfully`
      );

      return res.status(200).json({
        msg: "Tenant status fetched successfully",
        data: response.data,
        isSuccess: true,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Failure in fetching tenant status.`
    );

    return res.status(400).json({
      msg: response.msg || "Server internal error. Please try again later.",
      isSuccess: false,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.GetTenantProfileByPhone = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "GetTenantProfileByPhone";

  try {
    const tenantId = req.id;

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    const body = {
      phone: eqaroTenant.mobile,
    };

    const response = await eqaroAPIs.postApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      "users/userid",
      body
    );

    if (response && !response.data.code) {
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Tenant profile fetched successfully`
      );
      return res.status(200).json({
        msg: "Tenant profile fetched successfully",
        data: response.data,
        isSuccess: true,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Failure in fetching tenant profile.`
    );

    return res.status(400).json({
      msg: response.msg || "Server internal error. Please try again later.",
      isSuccess: false,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.GetBondDetails = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "GetBondDetails";

  try {
    const tenantId = req.id;

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    const response = await eqaroAPIs.paymentGetApi(
      eqaroTenant.mobile,
      eqaroTenant.accessToken,
      `bond/tenant/${eqaroTenant.eqaroUserId}`
    );

    if (response && response.data) {
      log.info(
        `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Bond details fetched successfully`
      );
      return res.status(200).json({
        msg: "Bond details fetched successfully",
        data: response.data,
        isSuccess: true,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenantsDB.mobile}], Failure in fetching bond details.`
    );

    return res.status(400).json({
      msg: response.msg || "Server internal error. Please try again later.",
      isSuccess: false,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

eqaro.GetTenantDetails = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "GetTenantDetails";

  try {
    const tenantId = req.id;

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Fetching tenant details`
    );

    const tenantData = await eqaroTenantsDB.getTenantDetails({ tenantId });
    let coApplicantData = null;

    if (
      Number(eqaroTenant.occupation) ===
      CONSTANTS.EQARO_OCCUPATION_TYPES.STUDENT
    ) {
      coApplicantData = await eqaroTenantsDB.getCoApplicantDetails({
        tenantId,
      });
    }

    log.info(
      `[${C}], [${F}], Mobile [${eqaroTenant.mobile}], Tenant details fetched successfully`
    );

    return res.status(200).json({
      msg: "Tenant details fetched successfully",
      data: {
        tenantData,
        coApplicantData: coApplicantData || [],
      },
      status: eqaroTenant.status,
      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,
    });
  }
};

eqaro.SendOTPCoApplicantMobile = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "SendOTPCoApplicantMobile";

  try {
    const { phone } = req.body;
    const tenantId = req.id;

    log.info(
      `[${C}], [${F}], Mobile [${phone}], TenantId [${tenantId}], Sending otp to co-applicant mobile`
    );

    let mobile = phone;

    const eqaroTenant = await eqaroTenantsDB.getByTenantId({ tenantId });
    if (!eqaroTenant) {
      log.info(
        `[${C}], [${F}], TenantId [${tenantId}] No tenant found with given id`
      );
      return res.status(400).json({
        msg: "Invalid tenant id",
        isSuccess: false,
      });
    }

    let otp = Math.floor(Math.random() * (999999 - 100000) + 100000).toString();

    if (process.env.ENABLE_RANDOM_OTP === "false") {
      otp = "111111";
    }

    await otpDB.create({ mobile, otp });

    const msg = `${otp} ${CONSTANTS.MSG.OTP}`;

    let templateId = "1707172182376945542";

    const isSent = await sendSMS(mobile, msg, templateId);
    log.info(
      `[${C}], [${F}], Mobile [${mobile}], OTP [${otp}], ${
        isSent ? "OTP sent successfully" : "Failed to send OTP SMS"
      }`
    );

    if (!isSent) {
      return res.status(400).json({
        msg: "Failed to send OTP SMS, Try again.",
        isSuccess: false,
      });
    } else {
      return res.status(200).json({
        msg: "OTP has been sent successfully",
        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,
    });
  }
};

eqaro.VerifyCoApplicantMobile = async (req: CustomRequest, res: Response) => {
  const C = "Eqaro Controller";
  const F = "VerifyCoApplicantMobile";

  try {
    const { otp, phone } = req.body;
    const tenantId = req.id;
    log.info(
      `[${C}], [${F}], Mobile [${phone}], Tenant ID [${tenantId}], OTP [${otp}]`
    );

    let mobile = phone;

    const record = await otpDB.getByMobile({ mobile });

    if (!record) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], OTP [${otp}] No Record Found`
      );

      return res.status(400).json({
        msg: "Invalid mobile number",
        isSuccess: false,
        isValid: true,
      });
    }

    if (record?.otp !== otp) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], OTP [${otp}], DB OTP [${record?.otp}], Incorrect OTP`
      );

      return res.status(400).json({
        msg: "Please enter a correct OTP",
        isSuccess: false,
      });
    } else {
      log.info(`[${C}], [${F}], Mobile [${phone}], OTP [${otp}], OTP Matched`);

      await otpDB.updateStatus({
        otp,
        status: CONSTANTS.OTP_STATUS.VERIFIED,
        mobile,
      });

      return res.status(200).json({
        msg: "OTP verified successfully",
        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,
    });
  }
};

export default eqaro;
