import { Response } from "express";
import clientDB from "../models/client.model";
import log from "../config/log";
import CONSTANTS from "../config/constants";
import propertyDB from "../models/property.model";
import CustomRequest from "../types/requestType";
//import propertiesTypes from "../schemas/property.schema";
import staffDB from "../models/staff.model";
import expenseDB from "../models/expense.model";
import landlordDB from "../models/landlord.model";
import landlordAccountDB from "../models/landlordAccount.model";
//import exp from "constants";
import propertyLeaseDB from "../models/propertyLease.model";
import { isUserPartner } from "../utils/isUserPartner";
// import axios from "axios";
// import crypto from "crypto";
// import moment from "moment";
// import getDueDescription from "../utils/getDueDescription";
import easeBuzzPaymentLink from "../utils/easeBuzz"
import landlordTransactionDB from "../models/landlordTransaction.model";
import propertiesTypes from "../schemas/property.schema";
import vendorDB from "../models/vendor.model";
import { isPrivilegedStaff } from "../utils/isPrivilegedStaff";
import clientLandlordDB from "../models/clientLandlord.model";
import moment from "moment";
import recurringExpenseDB from "../models/recurringExpense.model";
import otpDB from "../models/otp.model";
import sendSMS from "../utils/sendSMS";
import { sendWhatsappNewLandlord, sendWhatsappOtp } from "../utils/sendWhatsappWithConfig";
import jwt from "jsonwebtoken";
import landlordDocumentDB from "../models/landlordDocuments.model";
import getDocumentTitle from "../utils/getDocumentTitle";
import landlordBankAccountsDB from "../models/landlordBankAccounts.model";
import payoutBeneficiaryDB from "../models/payoutBeneficiary.model";
import cashfreePayout from "../utils/cashfreePayout";
import clientConfigDB from "../models/clientConfig.model";
import { getWalletBalanceAndLimits } from "../utils/walletHelper";

const landlords: any = {};

landlords.Add = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Add";

  try {
    const { name, email, mobile } = req.body;

    log.info(
      `[${C}], [${F}], Name [${name}], [${email}], [${mobile}]`
    );

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );
    }

    const isClientExists = await clientDB.getByMobile({
      mobile: mobile,
    });
    if (isClientExists) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Client Exists With The Same Mobile, Cannot Make Landlord`
      );

      return res.status(400).json({
        msg: "Cannot add client as a landlord",
        isSuccess: false,
      });
    }

    const isStaffExists = await staffDB.getByMobile({
      mobile: mobile,
    });
    if (isStaffExists) {
      log.info(
        `[${C}], [${F}], Mobile [${mobile}], Staff Exists With The Same Mobile, Cannot Make Landlord`
      );

      return res.status(400).json({
        msg: "Cannot add staff as a landlord",
        isSuccess: false,
      });
    }

    const isExists = await landlordDB.getByMobile({
      mobile,
    });

    let landlordId: number | null = null;

    if (!isExists) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${isExists?.id}], Landlord Not Exists, Creating Landlord Entry`
      );
      landlordId = await landlordDB.create({
        name: name,
        mobile: mobile,
        email: email,
      });
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${isExists?.id}], Landlord Already Exsits Updating Name`
      );
      landlordId = isExists?.id;
      await landlordDB.edit({
        id: landlordId,
        name: name,
        mobile: isExists?.mobile || mobile,
      });
    }

    // let landlordVendorRecord = await vendorDB.getByMobileAndClientId({mobile: mobile, clientId});

    // if (!landlordVendorRecord) {
    //   log.info(
    //     `[${C}], [${F}], Client Id [${clientId}], Landlord Name [${name}], Landlord Mobile [${mobile}], No Vendor Record Found, Creating New Vendor`
    //   );

    //   await vendorDB.create({
    //     mobile: mobile,
    //     name: name,
    //     clientId,
    //     type: CONSTANTS.VENDOR_TYPES.LANDLORD,
    //   });

    //   landlordVendorRecord = await vendorDB.getByMobile({mobile: mobile});
    // }

    const isAttachedWithClient = await clientLandlordDB.getByClientIdAndLandlordId({
      clientId,
      landlordId,
    });

    if (isAttachedWithClient) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Already Attached With ClientId`
      );

      return res.status(400).json({
        msg: "Landlord already added",
        isSuccess: false,
      });
    }

    await clientLandlordDB.create({
      clientId,
      landlordId,
    });

    await sendWhatsappNewLandlord(mobile, name, clientId);

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Added Successfully`
    );

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

landlords.EditX = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Edit";

  try {
    const { landlordId, name, email, mobile } = req.body;

    log.info(
      `[${C}], [${F}], Name [${name}], [${email}], [${mobile}]`
    );

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );
    }

    const landlord = await landlordDB.getById({
      id: landlordId,
    });
    if (!landlord) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], No Landlord Found`
      );

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

    let oldMobile = landlord?.mobile;

    let newLandlordId = landlordId;

    if (mobile != landlord?.mobile) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Mobile Inputted [${mobile}], Mobile In DB [${landlord?.mobile}], Mobile Differs, Checking DB For Entry With Entered Mobile`
      );

      const isExists = await landlordDB.getByMobile({
        mobile,
      });

      if (isExists) {
        newLandlordId = isExists?.id;

        const isAttachedWithClient = await clientLandlordDB.getByClientIdAndLandlordId({
          clientId,
          landlordId,
        });

        if (isAttachedWithClient) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Already Attached With ClientId`
          );
        } else {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Attaching Landlord With ClientId`
          );
          await clientLandlordDB.create({
            clientId,
            landlordId,
          });
        }
      } else {
        newLandlordId = await landlordDB.create({
          name: name,
          mobile: mobile,
          email: email,
        });

        await clientLandlordDB.create({
          clientId,
          landlordId: newLandlordId,
        });
      }

      await propertyLeaseDB.updateLandlordId({
        landlordId: landlordId,
        newLandlordId: newLandlordId,
      });
    }

    await landlordDB.editX({
      id: newLandlordId,
      name,
      mobile,
      email,
    });

    // let landlordVendorRecord = await vendorDB.getByMobileAndClientId({mobile: oldMobile, clientId});

    // if (!landlordVendorRecord) {
    //   log.info(
    //     `[${C}], [${F}], Client Id [${clientId}], Landlord Name [${name}], Landlord Mobile [${oldMobile}], No Vendor Record Found, Creating New Vendor`
    //   );

    //   await vendorDB.create({
    //     mobile: mobile,
    //     name: name,
    //     clientId,
    //     type: CONSTANTS.VENDOR_TYPES.LANDLORD,
    //   });

    //   landlordVendorRecord = await vendorDB.getByMobileAndClientId({mobile: mobile, clientId});
    // } else {
    //   log.info(
    //     `[${C}], [${F}], Client Id [${clientId}], Landlord Name [${name}], Landlord Mobile [${mobile}], Vendor Record Found, Updating Vendor Details`
    //   );

    //   await vendorDB.edit({
    //     id: landlordVendorRecord.id,
    //     mobile: mobile,
    //     name: name,
    //     clientId,
    //     type: CONSTANTS.VENDOR_TYPES.LANDLORD,
    //   });

    //   landlordVendorRecord = await vendorDB.getByMobileAndClientId({mobile: mobile, clientId});
    // }

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Updated Successfully`
    );

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

landlords.ListForClient = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ListForClient";

  try {
    const userType = req.userType;
    const { pageNum, s, startDate, endDate } = req.query;

    //StartDate and EndDate will be dates between 1-31
    // const limit = 10;

    let landlords = [];

    log.info(`[${C}], [${F}], User Type [${userType}], Page Num [${pageNum}], Search Val [${s}], Start Date [${startDate}], End Date [${endDate}]`);

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );

      if (s && s !== "" && s !== "undefined" && s !== "null") {
        landlords = await propertyLeaseDB.getByClientIdAndSearchVal({
          clientId,
          searchVal: s,
        });
      } else {
        landlords = await propertyLeaseDB.getByClientId({
          clientId,
        });
      }
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      // if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );

      if (s && s !== "" && s !== "undefined" && s !== "null") {
        landlords = await propertyLeaseDB.getByClientIdAndSearchVal({
          clientId,
          searchVal: s,
        });
      } else {
        landlords = await propertyLeaseDB.getByClientIdForStaff({
          clientId,
          staffId: staff.id,
        });
      }
    }
    let client = await clientDB.getById({ id: clientId });

    if (startDate && endDate && landlords && landlords.length > 0) {
      landlords = landlords.filter((lease: any) => {
        const rentDay = moment(lease.rentDate, "YYYY-MM-DD").date();
        return rentDay >= Number(startDate) && rentDay <= Number(endDate);
      });
    }

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlords List Sent Successfully`
    );

    return res.status(200).json({
      msg: "Landlords List Sent Successfully",
      landlords,
      canPayLandlord: client?.canPayLandlord,
      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,
    });
  }
};

landlords.ListForClientX = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ListForClientX";

  try {
    const userType = req.userType;
    const { pageNum, s } = req.query;
    // const limit = 10;

    let landlords: any = [];

    log.info(`[${C}], [${F}], User Type [${userType}], Page Num [${pageNum}], Search Val [${s}]`);

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      // if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );
    }

    let client = await clientDB.getById({ id: clientId });

    landlords = await landlordDB.getByClientIdX({
      clientId,
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlords List Sent Successfully`
    );

    return res.status(200).json({
      msg: "Landlords List Sent Successfully",
      landlords: landlords || [],
      canPayLandlord: client?.canPayLandlord,
      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,
    });
  }
};

landlords.GetExpiringAgreementsForWeb = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetExpiringAgreementsForWeb";

  try {
    const userType = req.userType;
    const { pageNum } = req.query;
    // const limit = 10;

    log.info(`[${C}], [${F}], User Type [${userType}], Page Num [${pageNum}]`);

    let landlords = [];
    let totalCount = { count: 0 };
    let curMonthExpiringCount = { count: 0 };
    let expiredCount = { count: 0 };
    let nextMonthExpiringCount = { count: 0 };

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );

      landlords = await propertyLeaseDB.getExpiringAgreements({
        clientId,
      });

      totalCount = landlords.length > 0 ? { count: landlords.length } : { count: 0 };
      curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringAgreementsCount({ clientId });
      expiredCount = await propertyLeaseDB.getExpiredAgreementsCount({ clientId });
      nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringAgreementsCount({ clientId });
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      //if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested....`
      );
      landlords = await propertyLeaseDB.getExpiringAgreementsForStaff({
        clientId,
        staffId: staff.id,
      });

      totalCount = landlords.length > 0 ? { count: landlords.length } : { count: 0 };
      curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringAgreementsCountForStaff({ clientId, staffId: staff.id });
      expiredCount = await propertyLeaseDB.getExpiredAgreementsCountForStaff({ clientId, staffId: staff.id });
      nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringAgreementsCountForStaff({ clientId, staffId: staff.id });
    }

    let client = await clientDB.getById({ id: clientId });

    const stats = {
      total: totalCount?.count || 0,
      curMonthExpiring: curMonthExpiringCount?.count || 0,
      expired: expiredCount?.count || 0,
      nextMonthExpiring: nextMonthExpiringCount?.count || 0,
    };

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlords List Sent Successfully`
    );
    if (landlords === false) {
      landlords = [];
    }

    return res.status(200).json({
      msg: "Landlords Agreement List Sent Successfully",
      canPayLandlord: client?.canPayLandlord,
      list: landlords,
      stats,
      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,
    });
  }
};

landlords.GetExpiringLockInPeriodForWeb = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetExpiringLockInPeriodForWeb";

  try {
    const userType = req.userType;

    log.info(`[${C}], [${F}], User Type [${userType}]`);

    let landlords = [];
    let totalCount = { count: 0 };
    let curMonthExpiringCount = { count: 0 };
    let expiredCount = { count: 0 };
    let nextMonthExpiringCount = { count: 0 };

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );

      landlords = await propertyLeaseDB.getExpiringLockInPeriod({
        clientId,
      });

      totalCount = landlords.length > 0 ? { count: landlords.length } : { count: 0 };
      curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringLockInPeriodCount({ clientId });
      expiredCount = await propertyLeaseDB.getExpiredLockInPeriodCount({ clientId });
      nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringLockInPeriodCount({ clientId });
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      //if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested....`
      );
      landlords = await propertyLeaseDB.getExpiringLockInPeriodForStaff({
        clientId,
        staffId: staff.id,
      });

      totalCount = landlords.length > 0 ? { count: landlords.length } : { count: 0 };
      curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringLockInPeriodCountForStaff({ clientId, staffId: staff.id });
      expiredCount = await propertyLeaseDB.getExpiredLockInPeriodCountForStaff({ clientId, staffId: staff.id });
      nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringLockInPeriodCountForStaff({ clientId, staffId: staff.id });
    }

    let client = await clientDB.getById({ id: clientId });

    const stats = {
      total: totalCount?.count || 0,
      curMonthExpiring: curMonthExpiringCount?.count || 0,
      expired: expiredCount?.count || 0,
      nextMonthExpiring: nextMonthExpiringCount?.count || 0,
    };

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlords List Sent Successfully`
    );
    if (landlords === false) {
      landlords = [];
    }

    return res.status(200).json({
      msg: "Landlords Agreement List Sent Successfully",
      canPayLandlord: client?.canPayLandlord,
      list: landlords,
      stats,
      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,
    });
  }
};

landlords.Edit = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Edit";

  try {
    const { landlordId, name, mobile, } = req.body;

    log.info(
      `[${C}], [${F}], Landlord Id [${landlordId}], Name [${name}], Mobile [${mobile}]`
    );
    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false
        });
      }
      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Non-admin Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested.....`
      );
    }

    let landlord = await landlordDB.getById({
      id: landlordId,
    });

    if (!landlord) {
      log.info(`[${C}], [${F}], Landlord Id [${landlordId}], No Landlord Found`);

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

    await landlordDB.edit({
      id: landlordId,
      name: name,
      mobile: mobile,
    });

    // Why Creating Vendor for landlord on via landlord edit.
    let vendorRecord = await vendorDB.getByMobileAndClientId({
      clientId: clientId,
      mobile: landlord.mobile,
    });

    if (!vendorRecord) {
      await vendorDB.create({
        mobile,
        name,
        clientId,
        type: CONSTANTS.VENDOR_TYPES.LANDLORD,
      });
    } else {
      await vendorDB.edit({
        id: vendorRecord.id,
        mobile,
        name,
        clientId,
        type: CONSTANTS.VENDOR_TYPES.LANDLORD,
      });
    }

    log.info(
      `[${C}], [${F}], Landlord Id [${landlordId}], Name [${name}], Mobile [${mobile}], Landlord Details Updated Successfully`
    );

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

landlords.ListRecords = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ListRecords";

  try {
    let { s, t, pageNum = 1 } = req.query;

    log.info(
      `[${C}], [${F}], Search Value [${s}], Search Type [${t}], Page Number [${pageNum}], Platform [${req.platform}]`
    );
    const userType = req.userType;
    const platform = req.platform;
    let limit = 10;

    let landlords: any = [];

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );

      if (s && s !== "") {
        if (platform !== CONSTANTS.TENANT_DEVICE_TYPE.WEB) {
          landlords = await landlordDB.getByClientIdBySearchApp({
            clientId,
            searchVal: s,
            pageNum,
            limit,
          });
        } else {
          landlords = await landlordDB.getByClientIdBySearchX({
            clientId,
            searchVal: s,
            searchType: t,
          });
        }
      } else {
        if (platform !== CONSTANTS.TENANT_DEVICE_TYPE.WEB) {
          landlords = await landlordDB.getByClientIdApp({
            clientId,
            pageNum,
            limit,
          });
        } else {
          landlords = await landlordDB.getByClientIdX({
            clientId,
          });
        }
      }
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      //if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Non-admin Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested.....`
      );

      const staffLinkedProps = await propertyDB.getPropsByStaffId({
        staffId: staff.id,
      });

      if (staffLinkedProps) {
        const propertiesIds = staffLinkedProps
          .map((prop: propertiesTypes) => prop.id)
          .join(",");

        if (s && s !== "") {
          if (platform !== CONSTANTS.TENANT_DEVICE_TYPE.WEB) {
            landlords = await landlordDB.getByClientIdBySearchForStaffApp({
              clientId,
              propertiesIds,
              searchVal: s,
              pageNum,
              limit,
            });
          } else {
            landlords = await landlordDB.getByClientIdBySearchForStaffX({
              clientId,
              propertiesIds,
              searchVal: s,
              searchType: t,
            });
          }
        } else {
          if (platform !== CONSTANTS.TENANT_DEVICE_TYPE.WEB) {
            landlords = await landlordDB.getByClientIdForStaffApp({
              clientId,
              propertiesIds,
              pageNum,
              limit,
            });
          } else {
            landlords = await landlordDB.getByClientIdForStaffX({
              clientId,
              propertiesIds,
            });
          }
        }
      }
    }

    if (landlords) {
      for (let landlord of landlords) {

        // const vendorRecord = await vendorDB.getByMobileAndClientId({
        //   mobile: landlord.mobile,
        //   clientId,
        // });
        const expenseAmt = await expenseDB.getTotlRentAndSecurityPaidToLandlord({
          clientId,
          paidTo: landlord.id,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        });

        landlord.lifetimePayment = expenseAmt;

        const properties = await propertyLeaseDB.getByClientIdAndLandlordId({
          clientId,
          landlordId: landlord.id,
        });

        landlord.propertiesCount = properties ? properties.length : 0;

        landlord.properties = landlord.properties || [];
        if (Array.isArray(properties) && properties.length > 0) {

          landlord.properties = await Promise.all(
            properties.map(async (item: any) => {
              const pendingDues = await expenseDB.getTotalUnPaidByPropIdAndFlatIdAndPaidTo({
                propId: item.propId,
                flatId: item.flatId,
                paidTo: landlord.id,
                paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
              });
              // const pendingDues = await expenseDB.getTotalUnPaidByPropIdAndPaidTo({
              //   propId: item.propId,
              //   paidTo: landlord.id,
              //   paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
              // });

              return {
                propId: item.propId,
                propName: item.propertyName,
                flatName: item.flatName,
                propAddress: item.propertyAddress,
                leaseRent: item.rent,
                leaseSecurity: item.security,
                startDate: item.startDate,
                endDate: item.endDate,
                rentDate: item.rentDate,
                incrementType: item.incrementType,
                incrementValue: item.incrementValue,
                incrementMonth: item.incrementMonth,
                pendingDues: pendingDues || 0,
              };
            })
          );
        }

        const docs = await landlordDocumentDB.getByClientIdAndLandlordId({ landlordId: landlord.id, clientId });
        if (docs && docs.length > 0) {
          for (let doc of docs) {
            const title = await getDocumentTitle(doc.type);
            doc.title = title;
          }
        }

        landlord.docs = docs || [];

        const bankDetails = await landlordBankAccountsDB.getByClientIdAndLandlordId({
          clientId,
          landlordId: landlord.id,
        });

        landlord.bankDetails = bankDetails || [];
      }
    }

    //log.info(`Landlords [${JSON.stringify(landlords)}]`);

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Search Value [${s}], Search Type [${t}], Landlord List Sent Successfully`
    );

    return res.status(200).json({
      msg: "Landlord list fetched successfully!",
      isSuccess: true,
      landlords,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

landlords.ExpenseListWeb = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ExpenseListWeb";

  try {
    const { vendorId, s, startDate, endDate } = req.query;
    // const limit = 10;

    log.info(`[${C}], [${F}], Vendor Id [${vendorId}], Search Val [${s}], Start Date [${startDate}], End Date [${endDate}]`);

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false
        });
      }
      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Non-admin Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested.....`
      );
    }

    let expenseList = [];

    if (s && s !== "" && s !== "undefined" && s !== "null") {
      expenseList = await expenseDB.getByPaidToAndSearchValWeb({
        clientId: clientId,
        paidTo: vendorId,
        paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
        searchVal: s,
      });
    } else if (startDate && endDate) {
      expenseList = await expenseDB.getByPaidToAndDateRange({
        clientId: clientId,
        paidTo: vendorId,
        paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
        startDate: startDate,
        endDate: endDate,
      });
    } else {
      expenseList = await expenseDB.getByPaidToWeb({
        clientId: clientId,
        paidTo: vendorId,
        paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
      });
    }


    let totalExpense = 0;
    if (expenseList && expenseList.length > 0) {
      expenseList.forEach((expense: any) => {
        totalExpense += expense.amount;
      });
    }

    log.info(`[${C}], [${F}], Client Id [${clientId}], Vendor Id [${vendorId}], Vendor Expenses List Sent Successfully`);

    return res.status(200).json({
      msg: "Vendor Expense list sent successfully",
      isSuccess: true,
      expenseList,
      totalExpense,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

landlords.Delete = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Delete";

  try {
    const { vendorId } = req.body;

    log.info(
      `[${C}], [${F}], Vendor Id [${vendorId}]`
    );
    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false
        });
      }
      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Non-admin Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Admin Requested.....`
      );
    }

    //Delete Vendor
    await landlordDB.updateStatus({
      id: vendorId,
      status: CONSTANTS.VENDOR_STATUS.DELETED,
    });

    log.info(
      `[${C}], [${F}], Vendor Id [${vendorId}], Vendor Deleted Successfully`
    );

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

landlords.InitiateLandlordPayment = async (req: CustomRequest, res: Response) => {
  const C = "LandLord Controller";
  const F = "InitiateLandlordPayment";
  try {
    const { landlordId, propId, amount, type = 1, paymentType, remarks = null, expenseId } = req.body;

    //paymentType - 0 Paying Fully, 1 Paying partially
    //type : 1 Paying Rent, 2 Paying Security 

    const email = 'kipinn.com@gmail.com';
    //let clientId = req.id;
    const userType = req.userType
    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`
        }, Landlord Id [${landlordId}], Prop Id [${propId}], Amount [${amount}], Payment Type [${paymentType}], Expense Type [${type}], Expense Id [${expenseId}], Remark [${remarks}], ${isPartner ? "Partner Requesting" : "Client Requesting"
        }....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }
      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Staff Role [${staff.role}], Not Allowed`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staff?.id}], Landlord Id [${landlordId}], Prop Id [${propId}], Amount [${amount}], Payment Type [${paymentType}], Expense Type [${type}], Expense Id [${expenseId}], Remark [${remarks}], Admin Requesting....`
      );
    }

    const landlord = await landlordDB.getById({
      id: landlordId,
    });
    if (!landlord) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const client = await clientDB.getById({
      id: clientId,
    });
    if (!client) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], No Client Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const property = await propertyDB.getById({
      id: propId,
    });
    if (!property) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], No Property Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }

    const landlordAccountDetail = await landlordAccountDB.getAccountDetailForPropId({
      clientId,
      landlordId,
      propId
    });
    if (!landlordAccountDetail) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], No Landlord account details Found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    } else if (landlordAccountDetail?.mId === null || landlordAccountDetail?.mid === "") {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], No Landlord MID found`
      );
      return res
        .status(400)
        .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
    }
    if (amount < 10) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], Amount cannot be less then 10`
      );
      return res.status(400).json({
        msg: `Amount entered is below the allowed limit`,
        isSuccess: true,
      });
    }
    let data = [];
    let gateway = Number(landlordAccountDetail?.gateway);
    if (gateway === CONSTANTS.PAYMENT_GATEWAY.EASEBUZZ) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], Gateway [${gateway}], Requesting easebuzz payment link`
      );
      data = await easeBuzzPaymentLink({
        C,
        F,
        landlordId,
        landLordName: landlord.name,
        landLordMobile: landlord.mobile,
        landlordMID: landlordAccountDetail?.mId,
        propName: property.name,
        propGID: property.gId,
        propId,
        type,
        clientId,
        clientName: client.name,
        clientMobile: client.mobile,
        email,
        amount,
        expenseId,
        remark: remarks.trim(),
      });
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], Amount [${amount}], Gateway [${gateway}], No link handling present for this gateway`
      );
      return res.status(400).json({
        msg: `Selected payment gateway is not allowed for this transaction`,
        //data: data,
        isSuccess: true,
      });
    }

    if (false === data) {
      log.info(`[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Landlord Id [${landlordId}], An error occured while creating link`);
      return res.status(500).json({
        msg: CONSTANTS.MSG.ERROR_MESSAGE,
        isSuccess: false,
      });
    }


    //log.info(`[${C}], [${F}], Status [${data?.status}], Payment Url [${data?.data?.payment_url}], Payment url shared`);
    //after succesfull hashing of hash
    return res.status(200).json({
      msg: `Payment url generated successfull`,
      link: data?.data?.payment_url,
      //data: data,
      isSuccess: true,
    });
    //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,
    });
  }
};

landlords.ManagePaymentDetails = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ManagePaymentDetails";
  try {
    const {
      landlordId,
      propId,
      paymentGateway,
      bankName,
      accountNumber,
      ifscCode,
      accountHolderName,
      merchantId,
      key = null
    } = req.body;


    let gateway = Number(paymentGateway);
    let accountNum = accountNumber;
    let ifsc = ifscCode;
    let holderName = accountHolderName;
    let mId = merchantId;

    let userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`
        }, Prop Id [${propId}], Landlord [${landlordId}], Gateway [${gateway}], Bank Name [${bankName}], Account Number [${accountNum}], IFSC Code [${ifsc}], Account Holder Name [${holderName}], MID [${mId}], Key [${key}], ${isPartner ? "Partner Requesting" : "Client Requesting"
        }....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }
      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Staff Role [${staff.role}], Not Allowed`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staff?.id}], Prop Id [${propId}], Landlord [${landlordId}], Gateway [${gateway}], Bank Name [${bankName}], Account Number [${accountNum}], IFSC Code [${ifsc}], Account Holder Name [${holderName}], MID [${mId}], Key [${key}], Admin Requesting....`
      );
    }

    let propertyLease = await propertyLeaseDB.getByClientIdAndPropId({
      clientId,
      propId,
    });

    if (!propertyLease) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Property Lease does not Exists`
      );

      return res.status(400).json({
        msg: "Property lease does not exists",
        isSuccess: false,
      });
    }

    let isEntryExists = await landlordAccountDB.isEntryExists({ clientId, landlordId, propId });
    if (isEntryExists) {
      await landlordAccountDB.update({
        id: isEntryExists.id,
        clientId,
        landlordId,
        propId,
        gateway,
        bankName,
        accountNum,
        ifsc,
        holderName,
        mId,
        key
      });
    } else {

      await landlordAccountDB.add({
        clientId,
        landlordId,
        propId,
        gateway,
        bankName,
        accountNum,
        ifsc,
        holderName,
        mId,
        key
      });
    }
    log.info(`[${C}], [${F}], ClientId [${clientId}], LandlordId [${landlordId}], PropId [${propId}], Gateway [${gateway}], BankName [${bankName}], AccountNum [${accountNum}], IFSC [${ifsc}], HolderName [${holderName}], MId [${mId}], Key [${key}], Landlord Account Added Successfully`);
    return res.status(200).json({
      msg: "Landlord Account Added Successfully",
      isSuccess: true,
    });
  } catch (error) {
    log.error(`
      [${C}], [${F}], Error [${error}]`);
    return res.status(500).json({
      msg: "Internal Server Error",
      isSuccess: false,
    });
  }
};

landlords.GetUnpaidRentsForClient = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetUnpaidRentsForClient";

  try {
    const { propId } = req.query;

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

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`}, ${isPartner ? "Partner Requesting...." : "Client Requesting...."
        }...`
      );
    } else {
      const staff = await staffDB.getById({
        id: req.id,
      });

      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }

      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );
    }
    let accountDetail = await landlordAccountDB.getAccountDetailByClientId({
      clientId,
      propId,
    });
    const unPaidLandlordExpenses = await expenseDB.getUnMarkedLandlordExpenseByPropId({
      clientId,
      propId,
    });
    let balance = 0;
    if (unPaidLandlordExpenses) {
      for (let expense of unPaidLandlordExpenses) {
        balance = Number(balance) + Number(expense.amount);

      }
    }
    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Unpaid Landlord Expenses Fetched Successfully`
    );

    return res.status(200).json({
      msg: "Unpaid landlord expenses fetched successfully.",
      mId: accountDetail?.mId ? accountDetail?.mId : "",
      balance,
      isSuccess: true,
      data: unPaidLandlordExpenses ? unPaidLandlordExpenses : [],
    });
  } catch (error) {
    log.error(`
      [${C}], [${F}], Error [${error}]`);
    return res.status(500).json({
      msg: "Internal Server Error",
      isSuccess: false,
    });
  }
};

landlords.GetPaymentsForWeb = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetPaymentsForWeb";

  try {
    const { propId, startDate, endDate, s, t } = req.query;
    const userType = req.userType;

    log.info(`[${C}], [${F}], Prop Id [${propId}], StartDate [${startDate}], End Date [${endDate}], Search Value [${s}], Search Type [${t}]`);

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    let paymentList: any = [];
    let summary: any = {};

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`}, ${isPartner ? "Partner Requesting" : "Client Requesting"
        }....`
      );

      if (propId && Number(propId) !== 0) {
        if (s && s !== undefined && s !== "") {
          paymentList = await expenseDB.getByPaidToForLandlordTransactionByPropIdAndSearchX({
            propId,
            searchVal: s,
            searchType: t,
          });
        } else {
          paymentList = await expenseDB.getByPaidToForLandlordTransactionByPropIdX({
            propId,
            startDate,
            endDate,
          });
        }

        summary = await expenseDB.getSummaryByPropIdAndDateRangeForLandlord({
          propId,
          startDate,
          endDate,
        });

        let totalSecurity = await expenseDB.getTotalByPropIdAndTypeForLandlord({
          propId,
          type: 43,
        });

        summary.lifetimeSecurity = totalSecurity
      } else {
        if (s && s !== undefined && s !== "") {
          paymentList = await expenseDB.getByPaidToForLandlordTransactionByClientIdAndSearchX({
            clientId,
            searchVal: s,
            searchType: t,
          });
        } else {
          paymentList = await expenseDB.getByPaidToForLandlordTransactionByClientIdX({
            clientId,
            startDate,
            endDate,
          });
        }

        summary = await expenseDB.getSummaryByClientIdAndDateRangeLandlord({
          clientId,
          startDate,
          endDate,
        });

        let totalSecurity = await expenseDB.getTotalByClientIdAndTypeForLandlord({
          clientId,
          type: 43,
        });

        summary.lifetimeSecurity = totalSecurity;
      }
    } else {
      const staff = await staffDB.getById({
        id: req.id,
      });

      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res
          .status(400)
          .json({ msg: CONSTANTS.MSG.INVALID_REQUEST, isSuccess: false });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      //if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) 
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );

      const staffLinkedProps = await propertyDB.getPropsByStaffId({
        staffId: staff.id,
      });

      if (staffLinkedProps) {
        const propertiesIds = staffLinkedProps
          .map((prop: propertiesTypes) => prop.id)
          .join(",");

        if (propId && Number(propId) !== 0) {
          if (s && s !== undefined && s !== "") {
            paymentList = await expenseDB.getByPaidToForLandlordTransactionByPropIdAndSearchX({
              propId,
              searchVal: s,
              searchType: t,
            });
          } else {
            paymentList = await expenseDB.getByPaidToForLandlordTransactionByPropIdX({
              propId,
              startDate,
              endDate,
            });
          }

          summary = await expenseDB.getSummaryByPropIdAndDateRangeForLandlord({
            propId,
            startDate,
            endDate,
          });

          let totalSecurity = await expenseDB.getTotalByPropIdAndTypeForLandlord({
            propId,
            type: 43,
          });

          summary.lifetimeSecurity = totalSecurity
        } else {
          if (s && s !== undefined && s !== "") {
            paymentList = await expenseDB.getByPaidToForLandlordTransactionByClientIdAndSearchForStaffX({
              clientId,
              propertiesIds: propertiesIds,
              searchVal: s,
              searchType: t,
            });
          } else {
            paymentList = await expenseDB.getByPaidToForLandlordTransactionByClientIdForStaffX({
              clientId,
              startDate,
              endDate,
              propertiesIds,
            });
          }

          summary = await expenseDB.getSummaryByClientIdAndDateRangeForStaffForLandlord({
            clientId,
            startDate,
            endDate,
            propertiesIds,
          });

          let totalSecurity = await expenseDB.getTotalByClientIdAndTypeForStaffForLandlord({
            clientId,
            type: 43,
            propertiesIds,
          });

          summary.lifetimeSecurity = totalSecurity;
        }
      }
    }

    if (paymentList) {
      for (let payment of paymentList) {
        if (payment?.paidToUserType === CONSTANTS.USER_TYPE.STAFF) {
          let staff = await staffDB.getById({ id: payment?.paidTo })
          payment.landlordName = staff?.name || 'NA';
          payment.landlordMobile = staff?.mobile || 'NA';
        }
      }
    }
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}]` : `Client Id [${clientId}]`}, Landlord payments sent successfully`
      );
    } else {
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}] Landlord payments sent successfully`
      );
    }

    return res.status(200).json({
      msg: "Landlord payments fetched successfully.",
      list: paymentList || [],
      summary: summary,
      isSuccess: true,
    });
  } catch (error) {
    log.error(`
      [${C}], [${F}], Error [${error}]`);
    return res.status(500).json({
      msg: "Internal Server Error",
      isSuccess: false,
    });
  }
};

landlords.GetUnPaidDuesByClientId = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetUnPaidDuesByClientId";

  try {
    const userType = req.userType;
    const limit = 10;

    let { s, t, startDate, endDate, type, locationId, pageNum } = req.query;

    log.info(
      `[${C}], [${F}], Search Value [${s}], Search Type [${t}], Start Date [${startDate}], End Date [${endDate}], Type [${type}], Location Id [${locationId}], Page Number [${pageNum}]`
    );

    if (type && typeof type === 'string') {
      type = type.split(',').map(v => v.trim()).filter(Boolean);
    }

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );

    let unPaidDues: any = [];
    let summary: any = {};

    let isStaffAllowed = false;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      const staff = await staffDB.getById({
        id: req.id,
      });
      isStaffAllowed = await isPrivilegedStaff(staff.role, 1);
    }

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner || isStaffAllowed) {
      log.info(
        `[${C}], [${F}], ${isPartner ? `Partner Id [${req.id}], Partner` : isStaffAllowed ? `Client Id [${clientId}], Staff Id [${req.id}], Staff` : `Client Id [${clientId}], Client`} Requesting....`
      );

      if (s && s !== undefined && s !== "") {
        if (t) {
          unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdAndSearch({
            clientId,
            searchVal: s,
            searchType: t,
          });
        } else {
          unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdAndSearchApp({
            clientId,
            searchVal: s,
            pageNum: Number(pageNum),
            limit: limit,
          });
        }
      } else if (pageNum && Number(pageNum)) {
        unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdForApp({
          clientId,
          startDate: startDate || null,
          endDate: endDate || null,
          typeFilter: type ? type : null,
          locationId: Number(locationId) ? Number(locationId) : null,
          pageNum: Number(pageNum),
          limit: limit,
        });
      } else {
        unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientId({
          clientId,
          startDate: startDate || null,
          endDate: endDate || null,
          typeFilter: type ? type : null,
          locationId: Number(locationId) ? Number(locationId) : null,
        });
      }

      summary = await expenseDB.getLandlordDuesSummaryByClientId({
        clientId,
        startDate: startDate ? startDate : moment().startOf("month").format("YYYY-MM-DD"),
        endDate: endDate ? endDate : moment().endOf("month").format("YYYY-MM-DD"),
      });
    } else {
      const staff = await staffDB.getById({
        id: req.id,
      });

      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }

      if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );

      const staffLinkedProps = await propertyDB.getPropsByStaffId({
        staffId: staff.id,
      });

      if (staffLinkedProps) {
        const propertiesIds = staffLinkedProps
          .map((prop: propertiesTypes) => prop.id)
          .join(",");


        if (s && s !== undefined && s !== "") {
          if (t) {
            unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdAndSearchForStaff({
              clientId,
              propertiesIds,
              searchVal: s,
              searchType: t,
            });            
          } else {
            unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdAndSearchForStaffApp({
              clientId,
              propertiesIds,
              searchVal: s,
              pageNum,
              limit,
            });
          }
        } else if (pageNum && Number(pageNum)) {
          unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdForStaffApp({
            clientId,
            propertiesIds,
            startDate: startDate || null,
            endDate: endDate || null,
            typeFilter: type ? type : null,
            locationId: Number(locationId) ? Number(locationId) : null,
            pageNum: Number(pageNum),
            limit: limit,
          });
        } else {
          unPaidDues = await expenseDB.getUnPaidLandlordDuesByClientIdForStaff({
            clientId,
            propertiesIds,
            startDate: startDate ? startDate : null,
            endDate: endDate ? endDate : null,
            typeFilter: type ? type : null,
            locationId: Number(locationId) ? Number(locationId) : null,
          });
        }

        summary = await expenseDB.getLandlordDuesSummaryByClientIdForStaff({
          clientId,
          propertiesIds,
          startDate: startDate ? startDate : moment().startOf("month").format("YYYY-MM-DD"),
          endDate: endDate ? endDate : moment().endOf("month").format("YYYY-MM-DD"),
        });
      }
    }

    const isPayoutEnabledConfig = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.IS_PAYOUT_ENABLED,
    });
    let isPayoutEnabled = 0;
    if (isPayoutEnabledConfig && Number(isPayoutEnabledConfig.value)) {
      isPayoutEnabled = Number(isPayoutEnabledConfig.value);
    }
    summary.balance = 0;
    if (isPayoutEnabled != 0) {
      let balance = await cashfreePayout.getWalletBalance(C, F, clientId);
      if (!balance.error) {
        summary.balance = Number(balance?.availableBalance);
      } else {
        summary.balance = 0;
      }
    }

    let payoutData = await getWalletBalanceAndLimits({
      clientId,
      userType: Number(userType),
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? Number(req.id) : null,
    });
    summary.payoutData = payoutData;
    summary.balance = payoutData?.walletBalance || summary.payoutBalance;

    let getAllLandlordPaid = await expenseDB.getLastPaymentDoneToLandlord({clientId});

    interface LastLandlordPayment {
      landlordId: number;
      paidDate: string | Date;
      paidAmount: number;
      bankRefNum: string | null;
    }
    const landlordPaymentMap = new Map<number, LastLandlordPayment>(
      getAllLandlordPaid.map((item: LastLandlordPayment) => [item.landlordId, item])
    );


    if (unPaidDues && unPaidDues.length > 0) {
      for (let due of unPaidDues) {
        let accountDetails : any  = false;
        if (due?.propId) {
          // accountDetails = await landlordAccountDB.isMidExists({
          //   clientId,
          //   landlordId: due.landlordId,
          //   propId: due.propId,
          // });
          accountDetails = await payoutBeneficiaryDB.getAllByUserIdAndUserType({
            userId: due.landlordId,
            userType: CONSTANTS.USER_TYPE.LANDLORD,
            clientId
          });
          if(accountDetails && accountDetails.length > 0) {
            accountDetails.forEach((accountDetail: any) => {
              accountDetail.isLastPaymentOnline =  !!accountDetail?.lastPaidAmount;
            });
          }
        }

        due.canPayOnline = accountDetails ? true : false;
        due.accounts = accountDetails || [];

        const lastPayment = landlordPaymentMap.get(due.landlordId);

        due.lastPaidDate = lastPayment?.paidDate || null;
        due.lastPaidAmount = lastPayment?.paidAmount || 0;
        //due.lastBankRefNum = lastPayment?.bankRefNum || null;
        due.isLastPaymentOnline =  !!lastPayment?.bankRefNum;
      }
    }

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Unpaid Landlord Dues Fetched Successfully`
    );

    return res.status(200).json({
      msg: "Unpaid landlord dues fetched successfully.",
      isSuccess: true,
      list: unPaidDues || [],
      summary: summary,
    })

  } catch (error) {
    log.error(`
      [${C}], [${F}], Error [${error}]`);
    return res.status(500).json({
      msg: "Internal Server Error",
      isSuccess: false,
    });
  }
};

landlords.Dashboard = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Dashboard";

  try {
    let { startDate, endDate } = req.query;
    const landlordId = req.id;

    if (!startDate) {
      startDate = moment().startOf("month").format("YYYY-MM-DD");
    }

    if (!endDate) {
      endDate = moment().endOf("month").format("YYYY-MM-DD");
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Start Date [${startDate}], End Date [${endDate}]`);

    const landlord = await landlordDB.getById({ id: landlordId });
    if (!landlord) {
      log.info(`[${C}], [${F}], Landlord Id [${landlordId}], No Landlord Found`);
      return res.status(400).json({
        msg: "No landlord account found",
        isSuccess: false,
      });
    }

    //const vendorRecord = await vendorDB.getByMobile({ mobile: landlord?.mobile });

    const propCount = await propertyLeaseDB.getCountByLandlordId({ landlordId });
    const tenantCount = await clientLandlordDB.getClientCountByLandlordId({ landlordId });

    let collection = await expenseDB.getTotalByPaidToAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      startDate,
      endDate,
    });

    // let collectionDueDate = await expenseDB.getTotalByPaidToAndDateRangeByDueDate({
    //   paidTo: landlordId,
    //   paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
    //   startDate,
    //   endDate,
    // });

    // if (vendorRecord) {
    //   const vendorCollection = await expenseDB.getTotalByPaidToAndDateRange({
    //     paidTo: vendorRecord.id,
    //     paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
    //     startDate,
    //     endDate,
    //   });

    //   collection += vendorCollection;
    // }

    let rentCollection = await expenseDB.getTotalByPaidToAndTypeAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 1, //Rent
      startDate,
      endDate,
    });

    let rentCollectionOnDueDate = await expenseDB.getTotalByPaidToAndTypeAndDateRangeDueDate({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 1, //Rent
      startDate,
      endDate,
    });

    // if (vendorRecord) {
    //   const vendorCollection = await expenseDB.getTotalByPaidToAndTypeAndDateRange({
    //     paidTo: vendorRecord.id,
    //     paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
    //     type: 1, //Rent
    //     startDate,
    //     endDate,
    //   });

    //   rentCollection += vendorCollection;
    // }

    let securityCollection = await expenseDB.getTotalByPaidToAndTypeAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 43, //Security
      startDate,
      endDate,
    });

    // if (vendorRecord) {
    //   const vendorCollection = await expenseDB.getTotalByPaidToAndTypeAndDateRange({
    //     paidTo: vendorRecord.id,
    //     paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
    //     type: 43, //Security
    //     startDate,
    //     endDate,
    //   });

    //   securityCollection += vendorCollection;
    // }


    let securityPending = await expenseDB.getTotalUnpaidByPaidToAndTypeAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 43, //Security
      startDate,
      endDate,
    });

    // if (vendorRecord) {
    //   let vendorPending = await expenseDB.getTotalUnpaidByPaidToAndTypeAndDateRange({
    //     paidTo: vendorRecord.id,
    //     paidToUserType: CONSTANTS.USER_TYPE.VENDOR,
    //     type: 43, //Security
    //     startDate,
    //     endDate,
    //   });

    //   //vendorPending = 0;
    //   securityPending += vendorPending;
    // }

    let otherPending = await expenseDB.getTotalUnpaidOtherDuesAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      startDate,
      endDate,
    });

    const totalPayableRent = await propertyLeaseDB.getTotalMonthlyRentByLandlordId({ landlordId });
    const totalPending = Number(totalPayableRent) + Number(securityPending) + Number(otherPending) - Number(rentCollectionOnDueDate);
    const rentPending = Number(totalPayableRent) - Number(rentCollectionOnDueDate);
    // log.info(
    //   `[${C}], [${F}], Landlord Id [${landlordId}], Calculated Total Payable Rent [${totalPayableRent}], Total Pending [${totalPending}], Rent Pending [${rentPending}], Security Pending [${securityPending}], Rent Collection [${rentCollection}] 1111111`
    // );

    const latestTransactions = await expenseDB.getByPaidToWithoutClientId({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      limit: 5,
      pageNum: 1,
    });

    //Handling for without start end done in model function
    const securityInHand = await expenseDB.getTotalByPaidToAndTypeAndDateRange({
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 43, //Security
    });

    const properties = await propertyDB.getByLandlordIdAndFilters({
      landlordId: landlord.id,
    });

    log.info(
      `[${C}], [${F}], Landlord Id [${landlordId}], Property Count [${propCount}], Tenant Count [${tenantCount}], Rent Collection [${rentCollection}], Security Collection [${securityCollection}], Total Pending [${totalPending}], Rent Pending [${rentPending}], Security Pending [${securityPending}], Dashboard Data Fetched Successfully`
    );

    return res.status(200).json({
      msg: "Dashboard data fetched successfully",
      isSuccess: true,
      landlord,
      propCount,
      tenantCount,
      collectionStats: {
        collection: Number(collection) || 0,
        rentCollection: Number(rentCollection) || 0,
        securityCollection: Number(securityCollection) || 0,
        securityInHand: securityInHand || 0,
      },
      dueStats: {
        totalPending: Number(totalPending) || 0,
        rentPending: Number(rentPending) || 0,
        securityPending: Number(securityPending) || 0,
      },
      latestTransactions: latestTransactions || [],
      properties: properties || [],
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

landlords.GetPropertyList = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetPropertyList";

  try {

    let { s, t, clientFilter } = req.query;

    if (clientFilter && typeof clientFilter === 'string') {
      clientFilter = clientFilter.split(',').map(v => v.trim()).filter(Boolean);
    }

    log.info(`[${C}], [${F}], Client Filter [${clientFilter}]`);

    const landlordId = req.id;

    const landlord = await landlordDB.getById({ id: landlordId });
    if (!landlord) {
      log.info(`[${C}], [${F}], Landlord Id [${landlordId}], No Landlord Found`);
      return res.status(400).json({
        msg: "No landlord account found",
        isSuccess: false,
      });
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Landlord Requesting....`);

    let properties = [];

    if (s && s !== undefined && s !== "") {
      properties = await propertyDB.getByLandlordIdAndSearch({
        landlordId,
        searchValue: s,
        searchType: t,
      });
    } else {
      properties = await propertyDB.getByLandlordIdAndFilters({ landlordId });
    }

    if (properties) {
      for (let property of properties) {
        const pendingDues = await expenseDB.getTotalUnPaidByPropIdAndPaidTo({
          propId: property.id,
          paidTo: landlord.id,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        });

        const totalCollection = await expenseDB.getTotalByPropIdAndPaidTo({
          propId: property.id,
          paidTo: landlord.id,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        });

        const totalSecurityCollection = await expenseDB.getTotalByPropIdAndPaidToAndType({
          propId: property.id,
          paidTo: landlord.id,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          type: 43,//security expense
        });

        property.pendingDues = pendingDues;
        property.totalCollection = totalCollection;
        property.totalSecurityCollection = totalSecurityCollection;

        const docs = await landlordDocumentDB.getByClientIdAndLandlordIdAndPropId({
          clientId: property.clientId,
          landlordId,
          propId: property.id,
        });
        if (docs && docs.length > 0) {
          for (let doc of docs) {
            const title = await getDocumentTitle(doc.type);
            doc.title = title;
          }
        }

        property.docs = docs || [];
      }
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Property List Fetched Successfully`);

    return res.status(200).json({
      msg: "Dashboard data fetched successfully",
      isSuccess: true,
      list: properties || [],
      total: properties?.length || 0,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

landlords.GetClientList = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetClientList";

  try {
    const { s, t } = req.query;
    const landlordId = req.id;

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Search Value [${s}], Search Type [${t}], Landlord Requesting....`);

    let clients = [];

    if (s && s !== undefined && s !== "") {
      clients = await clientLandlordDB.getClientsByLandlordIdAndSearch({
        landlordId,
        searchValue: s,
        searchType: t,
      });
    } else {
      clients = await clientLandlordDB.getClientsByLandlordId({ landlordId });
    }

    if (clients && clients.length > 0) {
      for (let client of clients) {
        const properties = await propertyDB.getByLandlordIdAndClientId({
          landlordId,
          clientId: client.clientId,
        });

        if (properties && properties.length > 0) {
          for (let property of properties) {
            const pendingDues = await expenseDB.getTotalUnPaidByPropIdAndPaidTo({
              propId: property.id,
              paidTo: landlordId,
              paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
            });

            property.pendingDues = pendingDues || 0;
          }
        }

        client.properties = properties || [];

        const pendingDues = await expenseDB.getTotalUnPaidByClientIdAndPaidTo({
          clientId: client.clientId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        });

        const totalCollection = await expenseDB.getTotalByClientIdAndPaidTo({
          clientId: client.clientId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        });

        log.info(`Client Id [${client.clientId}], Landlord Id [${landlordId}], total Collection [${totalCollection}]`);

        const totalSecurityCollection = await expenseDB.getTotalByClientIdAndPaidToAndType({
          clientId: client.clientId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          type: 43,//security expense
        });

        log.info(`Client Id [${client.clientId}], Landlord Id [${landlordId}], total Security [${totalSecurityCollection}]`);

        client.pendingDues = pendingDues;
        client.totalCollection = totalCollection;
        client.totalSecurityCollection = totalSecurityCollection;
      }
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Client List Fetched Successfully`);

    return res.status(200).json({
      msg: "Client list fetched successfully",
      isSuccess: true,
      list: clients || [],
      total: clients?.length || 0,
    });

  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

landlords.GetCollectionsByLandlordId = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetCollectionsByLandlordId";

  try {
    const { startDate, endDate, filter, propId } = req.query;
    const landlordId = req.id;

    let collections = [];
    let summary = {
      total: 0,
      rent: 0,
      security: 0,
      other: 0,
      lifetimeSecurity: 0,
    };

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Prop Id [${propId}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}]`);

    if (Number(propId) && Number(propId) !== 0) {
      if (filter && filter === 'R') {
        collections = await expenseDB.getByPaidToAndDateRangeAndTypeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 1, //Rent
        });
      } else if (filter && filter === 'S') {
        collections = await expenseDB.getByPaidToAndDateRangeAndTypeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 43, //Security
        });
      } else if (filter && filter === 'O') {
        collections = await expenseDB.getOtherExpenseByPaidToAndDateRangeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      } else {
        collections = await expenseDB.getByPaidToAndDateRangeForLandlordAndPropId({
          propId: propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      }
    } else {
      if (filter && filter === 'R') {
        collections = await expenseDB.getByPaidToAndDateRangeAndTypeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 1, //Rent
        });
      } else if (filter && filter === 'S') {
        collections = await expenseDB.getByPaidToAndDateRangeAndTypeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 43, //Security
        });
      } else if (filter && filter === 'O') {
        collections = await expenseDB.getOtherExpenseByPaidToAndDateRangeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      } else {
        collections = await expenseDB.getByPaidToAndDateRangeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      }
    }

    if (Number(propId) && Number(propId) !== 0) {
      summary = await expenseDB.getSummaryByLandlordIdAndDateRangeAndPropId({
        propId,
        paidTo: landlordId,
        paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        startDate,
        endDate,
      });
    } else {
      summary = await expenseDB.getSummaryByLandlordIdAndDateRange({
        paidTo: landlordId,
        paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        startDate,
        endDate,
      });
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Prop Id [${propId}], Start Date [${startDate}], End Date [${endDate}], Collections Fetched Successfully`);

    return res.status(200).json({
      msg: "Collection data fetched successfully",
      isSuccess: true,
      list: collections || [],
      summary: summary,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

landlords.GetDuesByLandlordId = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetDuesByLandlordId";

  try {
    const { startDate, endDate, filter, propId } = req.query;
    const landlordId = req.id;

    let dues = [];
    let summary = {
      startEndTotal: 0,
      rent: 0,
      security: 0,
      other: 0,
      lifetimeTotal: 0,
    };

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Prop Id [${propId}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}]`);

    if (Number(propId) && Number(propId) !== 0) {
      if (filter && filter === 'R') {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeAndTypeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 1, //Rent
        });
      } else if (filter && filter === 'S') {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeAndTypeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 43, //Security
        });
      } else if (filter && filter === 'O') {
        dues = await expenseDB.getUnPaidOtherExpenseByPaidToAndDateRangeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      } else {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeForLandlordAndPropId({
          propId,
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      }
    } else {
      if (filter && filter === 'R') {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeAndTypeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 1, //Rent
        });
      } else if (filter && filter === 'S') {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeAndTypeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
          type: 43, //Security
        });
      } else if (filter && filter === 'O') {
        dues = await expenseDB.getUnPaidOtherExpenseByPaidToAndDateRangeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      } else {
        dues = await expenseDB.getUnPaidByPaidToAndDateRangeForLandlord({
          paidTo: landlordId,
          paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
          limit: 10e9,
          pageNum: 1,
          startDate,
          endDate,
        });
      }
    }

    if (Number(propId) && Number(propId) !== 0) {
      summary = await expenseDB.getUnPaidSummaryByLandlordIdAndDateRangeAndPropId({
        propId,
        paidTo: landlordId,
        paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        startDate,
        endDate,
      });
    } else {
      summary = await expenseDB.getUnPaidSummaryByLandlordIdAndDateRange({
        paidTo: landlordId,
        paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
        startDate,
        endDate,
      });
    }

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Prop Id [${propId}], Start Date [${startDate}], End Date [${endDate}], Dues Fetched Successfully`);

    return res.status(200).json({
      msg: "Dues fetched successfully",
      isSuccess: true,
      list: dues || [],
      summary: summary,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

//Normal List
landlords.ListLeaseForLandlord = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "ListLeaseForLandlord";

  try {
    const { s, t, filter } = req.query;
    // const limit = 10;
    const landlordId = req.id;

    let leases = [];
    let summary = {
      total: 0,
      curMonth: 0,
      nextMonth: 0,
      expired: 0,
    };

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Filter [${filter}], Search Val [${s}], Search Type [${t}]`);

    if (s && s !== "" && s !== "undefined" && s !== "null") {
      leases = await propertyLeaseDB.getByLandlordIdAndSearch({
        landlordId,
        searchValue: s,
        searchType: t,
      });
    } else if (filter && filter === "LE") {
      //Lease Expiring
      leases = await propertyLeaseDB.getExpiringAgreementsByLandlordId({ landlordId });
      let totalCount = leases.length > 0 ? leases.length : 0;
      let curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringAgreementsCountForLandlord({ landlordId });
      let expiredCount = await propertyLeaseDB.getExpiredAgreementsCountForLandlord({ landlordId });
      let nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringAgreementsCountForLandlord({ landlordId });

      summary.total = totalCount ? totalCount : 0;
      summary.curMonth = curMonthExpiringCount ? curMonthExpiringCount : 0;
      summary.nextMonth = nextMonthExpiringCount ? nextMonthExpiringCount : 0;
      summary.expired = expiredCount ? expiredCount : 0;
    } else if (filter && filter === "LC") {
      //Lock In Completed
      leases = await propertyLeaseDB.getExpiringLockInPeriodForLandlordId({ landlordId });
      let totalCount = leases.length > 0 ? leases.length : 0;
      let curMonthExpiringCount = await propertyLeaseDB.getCurrentMonthExpiringLockInPeriodCountForlandlord({ landlordId });
      let expiredCount = await propertyLeaseDB.getExpiredLockInPeriodCountForlandlord({ landlordId });
      let nextMonthExpiringCount = await propertyLeaseDB.getNextMonthExpiringLockInPeriodCountForlandlord({ landlordId });

      summary.total = totalCount ? totalCount : 0;
      summary.curMonth = curMonthExpiringCount ? curMonthExpiringCount : 0;
      summary.nextMonth = nextMonthExpiringCount ? nextMonthExpiringCount : 0;
      summary.expired = expiredCount ? expiredCount : 0;
    } else {
      leases = await propertyLeaseDB.getByLandlordId({ landlordId });
    }

    log.info(
      `[${C}], [${F}], Landlord Id [${landlordId}], Filter [${filter}], Search Value [${s}], Search Type [${t}], Lease List Sent Successfully`
    );

    return res.status(200).json({
      msg: "Lease list sent successfully",
      isSuccess: true,
      leases: leases || [],
      summary: summary,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);
    return res.status(500).json({
      msg: CONSTANTS.MSG.ERROR_MESSAGE,
      isSuccess: false,
    });
  }
};

landlords.Summary = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "Summary";

  try {

    const { landlordId } = req.query;

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

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], No Staff Found`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false
        });
      }
      // if (staff.role !== CONSTANTS.STAFF_ROLES.ADMIN && staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE && staff.role !== CONSTANTS.STAFF_ROLES.FINANCE_ADMIN) {
      //   log.info(
      //     `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Non-admin Staff Not Authorized`
      //   );
      //   return res.status(400).json({
      //     msg: "Unauthorized Access",
      //     isSuccess: false,
      //   });
      // }
      log.info(`[${C}], [${F}], Staff Id [${req.id}], Staff Requested....`);
    }

    const landlord = await landlordDB.getById({ id: landlordId });
    if (!landlord) {
      log.info(`[${C}], [${F}], Landlord Id [${landlordId}], No Landlord Found`);
      return res.status(400).json({
        msg: "No landlord account found",
        isSuccess: false,
      });
    }

    const propCount = await propertyLeaseDB.getCountByLandlordId({ landlordId });
    //const tenantCount = await clientLandlordDB.getClientCountByLandlordId({ landlordId });

    let totalCollection = await expenseDB.getTotalByPaidTo({
      clientId,
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
    });

    let totalSecurity = await expenseDB.getPaidExpensesTotalByClientAndType({
      clientId,
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
      type: 43, //Security
    });

    let totalPending = await expenseDB.getUnpaidExpensesTotalByClientAndLandlord({
      clientId,
      paidTo: landlordId,
      paidToUserType: CONSTANTS.USER_TYPE.LANDLORD,
    });

    let transactions = await expenseDB.getByPaidToForLandlordTransactionByLandlordId({
      clientId,
      landlordId: landlord?.id,
    });

    let pendings = await expenseDB.getUnpaidExpensesByClientAndLandlord({
      clientId,
      paidTo: landlord?.id,
    });
    if (pendings && pendings.length > 0) {
      for (let pending of pendings) {
        let accountDetails = false;
        if (pending?.propId) {
          // accountDetails = await landlordAccountDB.isMidExists({
          //   clientId,
          //   landlordId: pending.landlordId,
          //   propId: pending.propId,
          // });
          accountDetails = await payoutBeneficiaryDB.getAllByUserIdAndUserType({
            userId: pending.landlordId,
            userType: CONSTANTS.USER_TYPE.LANDLORD,
            clientId
          });
        }

        pending.canPayOnline = accountDetails ? true : false;
        pending.accounts = accountDetails || [];
      }
    }

    const docs = await landlordDocumentDB.getByClientIdAndLandlordId({ landlordId: landlord.id, clientId });
    if (docs && docs.length > 0) {
      for (let doc of docs) {
        const title = await getDocumentTitle(doc.type);
        doc.title = title;
      }
    }

    landlord.docs = docs || [];

    if (transactions) {
      for (let transaction of transactions) {
        transaction.landlordName = landlord?.name || "";
        transaction.landlordMobile = landlord?.mobile || "";
      }
    }

    const properties = await propertyLeaseDB.getByClientIdAndLandlordId({
      clientId,
      landlordId: landlord.id,
    });

    const propertiesForDues = await propertyLeaseDB.getPropertiesByClientIdAndLandlordId({
      clientId,
      landlordId: landlord.id,
    });

    if (propertiesForDues && propertiesForDues.length > 0) {
      for (let property of propertiesForDues) {
        if (Array.isArray(property.flats) && property.flats.length === 1 && property.flats[0] === null) property.flats = [];
      }
    }

    const isPayoutEnabledConfig = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.IS_PAYOUT_ENABLED,
    });
    let isPayoutEnabled = 0;
    if (isPayoutEnabledConfig && Number(isPayoutEnabledConfig.value)) {
      isPayoutEnabled = Number(isPayoutEnabledConfig.value);
    }
    let walletBalance = 0;
    if (isPayoutEnabled != 0) {
      let balance = await cashfreePayout.getWalletBalance(C, F, clientId);
      if (!balance.error) {
        walletBalance = Number(balance?.availableBalance);
      } else {
        walletBalance = 0;
      }
    }

    let payoutData = await getWalletBalanceAndLimits({
      clientId,
      userType: Number(userType),
      staffId: userType === CONSTANTS.USER_TYPE.STAFF ? Number(req.id) : null,
    });
    walletBalance = payoutData?.walletBalance || walletBalance;

    log.info(
      `[${C}], [${F}], Landlord Id [${landlordId}], Property Count [${propCount}], Rent Collection [${totalCollection}], Security Collection [${totalSecurity}], Total Pending [${totalPending}], Landlord summary fetched successfully`
    );


    return res.status(200).json({
      msg: "Landlord summary fetched successfully",
      isSuccess: true,
      landlord,
      propCount,
      summary: {
        collection: Number(totalCollection) || 0,
        security: Number(totalSecurity) || 0,
        totalPending: Number(totalPending) || 0,
        balance: walletBalance,
        payoutData: payoutData,
      },
      //properties: properties || [],
      transactions: transactions || [],
      pendings: pendings || [],
      properties: properties || [],
      propertiesForDues: propertiesForDues || [],
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

landlords.EditDetail = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "EditDetail";

  try {
    const { landlordId, name, email, mobile, gender, bloodGroup, dob, address, nationality, alternateMobile, pan } = req.body;

    log.info(
      `[${C}], [${F}], Name [${name}], Email [${email}], Mobile [${mobile}], Gender [${gender}], DOB [${dob}], Blood Group [${bloodGroup}], Address [${address}], Nationality [${nationality}], Alternate Mobile [${alternateMobile}], Pan [${pan}]`
    );

    const userType = req.userType;

    let { isPartner, clientId } = await isUserPartner(
      Number(userType),
      Number(req.id)
    );
    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner) {
      log.info(
        `[${C}], [${F}], ${isPartner
          ? `Partner Id [${req.id}], Partner`
          : `Client Id [${clientId}], Client`
        }, Requesting....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff Id [${req.id}], No Staff Found`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      let isStaffAllowed = await isPrivilegedStaff(staff.role, 3);
      if (!isStaffAllowed) {
        log.info(
          `[${C}], [${F}], User Type [${userType}], User Id [${req.id}], Staff Not Authorized`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );
    }

    const landlord = await landlordDB.getById({
      id: landlordId,
    });
    if (!landlord) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], No Landlord Found`
      );

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

    let oldMobile = landlord?.mobile;

    let newLandlordId = landlordId;

    if (mobile != landlord?.mobile) {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Mobile Inputted [${mobile}], Mobile In DB [${landlord?.mobile}], Mobile Differs, Checking DB For Entry With Entered Mobile`
      );

      const isExists = await landlordDB.getByMobile({
        mobile,
      });

      if (isExists) {
        newLandlordId = isExists?.id;

        const isAttachedWithClient = await clientLandlordDB.getByClientIdAndLandlordId({
          clientId,
          landlordId,
        });

        if (isAttachedWithClient) {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Already Attached With ClientId`
          );
        } else {
          log.info(
            `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Attaching Landlord With ClientId`
          );
          await clientLandlordDB.create({
            clientId,
            landlordId,
          });
        }
      } else {
        newLandlordId = await landlordDB.create({
          name: name,
          mobile: mobile,
          email: email,
        });


        await clientLandlordDB.create({
          clientId,
          landlordId: newLandlordId,
        });
      }

      await propertyLeaseDB.updateLandlordId({
        landlordId: landlordId,
        newLandlordId: newLandlordId,
      });
    }

    await landlordDB.editDetails({
      id: newLandlordId,
      name,
      mobile,
      email,
      alternateMobile,
      gender,
      bloodGroup,
      dob,
      address,
      nationality
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Landlord Id [${landlordId}], Landlord Updated Successfully`
    );

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

landlords.GetPropertyStaffList = async (req: CustomRequest, res: Response) => {
  const C = "Landlord Controller";
  const F = "GetPropertyStaffList";

  try {

    let { s, t } = req.query;


    const landlordId = req.id;

    const landlord = await landlordDB.getById({ id: landlordId });
    if (!landlord) {
      log.info(`[${C}], [${F}], Landlord Id [${landlordId}], No Landlord Found`);
      return res.status(400).json({
        msg: "No landlord account found",
        isSuccess: false,
      });
    }
    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Landlord Requesting....`);

    // let properties = [];

    // if (s && s !== undefined && s !== "") {
    //   properties = await propertyDB.getByLandlordIdAndSearch({
    //     landlordId,
    //     searchValue: s,
    //     searchType: t,
    //   });
    // } else {
    //   properties = await propertyDB.getByLandlordIdAndFilters({ landlordId });
    // }

    // if (properties) {
    // }
    let staffs = [];
    staffs = await staffDB.getByPropertyId({ landlordId });

    log.info(`[${C}], [${F}], Landlord Id [${landlordId}], Staff List Fetched Successfully`);

    return res.status(200).json({
      msg: "Property staffs fetched successfully",
      isSuccess: true,
      list: staffs || [],
      total: staffs?.length || 0,
    });
  } catch (error: any) {
    log.info(`[${C}], [${F}], Error: ${error?.message || error}`);

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

export default landlords;
