import { Response } from "express";
import CONSTANTS from "../config/constants";
import log from "../config/log";
import staffDB from "../models/staff.model";
import CustomRequest from "../types/requestType";
import leadDB from "../models/lead.model";
import { stat } from "fs";
import { isUserPartner } from "../utils/isUserPartner";
import propertyDB from "../models/property.model";
import propertiesTypes from "../schemas/property.schema";
import clientDB from "../models/client.model";
import staffsTypes from "../schemas/staff.schema";
import { sendWhatsappStaffLeadAssigned } from "../utils/sendWhatsappWithConfig";
import settingsDB from "../models/settings.model";
import moment from "moment";
import bedDB from "../models/beds.model";
import { isPrivilegedStaff } from "../utils/isPrivilegedStaff";
import locationDB from "../models/location.model";
import { logLeadActivity } from "../utils/logLeadActivity";

const leads: any = {};

leads.Add = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "Add";
  try {
    let clientId = req.id;
    const userType = req.userType;
    let doneByName = "";
    const {
      name,
      propId,
      mobile,
      rentRange,
      roomType,
      gender,
      visitType,
      visitDateTime = null,
      remarks,
      source,
      status,
      staffs = null,
      email = null
    } = req.body;

    let assignStaff = false;

    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      const staff = await staffDB.getById({ id: staffId });
      doneByName = staff.name || "";
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Staff Role [${staff.role}], Prop Id [${propId}], Rent Range [${rentRange}], Room Type [${roomType}], Name [${name}], Mobile [${mobile}], Email [${email}], Gender [${gender}], Visit Type [${visitType}], Remarks [${remarks}], Source [${source}], Visit Date Time [${visitDateTime}], Staffs [${staffs}], Staff Requested...`
      );
      if (
        staff.role == CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role == CONSTANTS.STAFF_ROLES.PARTNER ||
        staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON ||
        staff.role === CONSTANTS.STAFF_ROLES.SALES_HEAD ||
        staff.role == CONSTANTS.STAFF_ROLES.WARDEN ||
        staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't add lead`
        );
        return res.status(400).json({
          msg: "Unauthorized Access",
          isSuccess: false,
        });
      }
      if (        
        staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON ||
        staff.role == CONSTANTS.STAFF_ROLES.WARDEN
      ) {
        assignStaff = true;
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Rent Range [${rentRange}], Room Type [${roomType}], Name [${name}], Mobile [${mobile}], Email [${email}], Gender [${gender}], Visit Type [${visitType}], Remarks [${remarks}], Source [${source}], Visit Date Time [${visitDateTime}], Staffs [${staffs}], Client Requested...`
      );
    }
    const alreadyExists = await leadDB.getByClientIdAndMobile({
      mobile,
      clientId,
    });
    if (alreadyExists) {
      log.info(
        `[${C}], [${F}], Lead with this number already exists, Mobile [${mobile}]`
      );
      return res.status(400).json({
        msg: `Lead with this number already exists.`,
        isSuccess: false,
      });
    }

    const client = await clientDB.getById({ id: clientId });
    if (!client) {
      log.info(`[${C}], [${F}], Client not found, Client Id [${clientId}]`);
      return res.status(400).json({
        msg: `Client not found`,
        isSuccess: false,
      });
    }
    if (userType === CONSTANTS.USER_TYPE.CLIENT) {
      doneByName = client.name || "";
    }

    const leadId = await leadDB.create({
      clientId,
      name,
      propId: Array.isArray(propId) ? null : propId,
      mobile,
      rentRange,
      roomType,
      gender,
      visitType,
      visitDateTime,
      remarks,
      source,
      status,
      email,
    });

    if (assignStaff) {
      const staff = await staffDB.getById({
        id: req.id
      })
      await leadDB.linkStaff({ 
        clientId, 
        staffId: staff.id, 
        leadId 
      });
    }

    if (remarks && remarks.trim() !== "") {
      await leadDB.recordNotes({
        clientId: clientId,
        leadId: leadId,
        notes: remarks,
        doneByUserType: userType,
        doneBy: req.id,
        doneByName: doneByName,
      });
    }

    if (Array.isArray(propId) && propId.length > 0) {
      for (let id of propId) {
        await leadDB.link({ clientId, propId: id, leadId });
      }
    }

    if (Array.isArray(staffs) && staffs.length > 0) {
      for (let staff of staffs) {
        await leadDB.linkStaff({ clientId, staffId: staff, leadId });
      }
    }

    let arg1 = null;
    if (visitDateTime) arg1 = visitDateTime;

    await logLeadActivity(
      Number(req.userType),
      Number(req.id),
      Number(req.parentClientId!),
      Number(req.platform),
      Number(leadId),
      Number(status),
      Number(status),
      arg1,
    );


    log.info(
      `[${C}], [${F}], Name [${name}], Mobile [${mobile}], Lead added successfully`
    );
    return res.status(200).json({
      msg: `Lead 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,
    });
  }
};

leads.AddFromWebsite = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "AddFromWebsite";
  try {
    let {
      name,
      propId,
      mobile,
      rentRange,
      gender=CONSTANTS.GENDER.MALE,
      remarks,
      email = null
    } = req.body;

    if (mobile == null || mobile === "" || String(mobile).trim() === "") {
      mobile = null;
    }

    log.info(`[${C}], [${F}], Property Id [${propId}], Name [${name}], Mobile [${mobile}], Email [${email}], Rent Range [${rentRange}], Gender [${gender}], Remarks [${remarks}]`);

    const property = await propertyDB.getById({
      id: propId,
    });
    if (!property) {
      log.info(`[${C}], [${F}], Property Id [${propId}], No Property Found With Id`);

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

    const alreadyExists = await leadDB.getByClientIdAndMobileAndPropId({
      mobile,
      clientId: property.clientId,
      propId: propId,
    });
    if (alreadyExists) {
      log.info(
        `[${C}], [${F}], Client Id [${property.clientId}], Property Id [${propId}], Mobile [${mobile}], Lead with this number already exists`
      );
      return res.status(200).json({
        msg: `Enquiry submitted successfully! Our team will contact you shortly`,
        isSuccess: true,
      });
    }

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

    const leadId = await leadDB.create({
      clientId: property.clientId,
      name,
      propId: propId,
      mobile,
      rentRange,
      roomType: 0,
      gender,
      visitType: null,
      visitDateTime: null,
      remarks: null,
      source: CONSTANTS.LEAD_SOURCE.WEBSITE,
      status: CONSTANTS.LEAD_STATUS.NEW,
      email,
    });

    if (remarks && remarks.trim() !== "") {
      await leadDB.recordNotes({
        clientId: property.clientId,
        leadId: leadId,
        notes: remarks,
        doneByUserType: CONSTANTS.USER_TYPE.TENANT,
        doneBy: null,
        doneByName: name,
      });
    }

    log.info(
      `[${C}], [${F}], Client Id [${property.clientId}], Property Id [${propId}], Name [${name}], Mobile [${mobile}], Rent Range [${rentRange}], Gender [${gender}], Lead added successfully`
    );
    return res.status(200).json({
      msg: `Enquiry submitted successfully! Our team will contact you shortly`,
      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,
    });
  }
};

leads.List = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "List";
  try {
    let clientId = req.id;
    const userType = req.userType;
    let { pageNum, filter, searchVal } = req.query;

    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Page Num [${pageNum}], Filter [${filter}], Search Val [${searchVal}], Staff Requesting....`
      );

      const staff = await staffDB.getById({ id: staffId });
      if (
        staff.role == CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role == CONSTANTS.STAFF_ROLES.WARDEN ||
        staff.role === CONSTANTS.STAFF_ROLES.PARTNER ||
        staff.role === CONSTANTS.STAFF_ROLES.SALES_HEAD ||
        staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't get lead list`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Page Num [${pageNum}], Filter [${filter}], Search Val [${searchVal}], Client Requesting....`
      );
    }
    let leads = [];
    let summary = [];
    const limit = 10;
    if (searchVal) {
      leads = await leadDB.getSearchResults({
        clientId,
        pageNum: Number(pageNum),
        limit,
        searchVal,
      });
    } else {
      leads = await leadDB.getList({
        clientId,
        pageNum: Number(pageNum),
        limit,
      });
    }
    summary = await leadDB.getSummaryByClientId({ clientId });
    log.info(`[${C}], [${F}], Lead list sent successfully`);
    return res.status(200).json({
      msg: `Lead list sent successfully`,
      data: leads || [],
      summary: summary || [],
      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,
    });
  }
};

leads.ListX = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "ListX";
  try {
    const userType = req.userType;
    let { 
      pageNum, 
      filter, 
      status, 
      filterVal, 
      searchVal, 
      propId, 
      startDate, 
      endDate,
      sourceFilters,
      staffFilters,
      propFilters,
    } = req.query;

    let staffAccounts = []; //for sales staff dashboard


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

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

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


    log.info(
      `[${C}], [${F}], User Type [${userType}], Page Num [${pageNum}], Filter [${filter}], Status [${status}], Filter Val [${filterVal}], Search Val [${searchVal}], Prop Ids [${propId}], Prop Filters [${propFilters}], Staff Filters [${staffFilters}], Source Filters [${sourceFilters}], Start Date [${startDate}], End Date [${endDate}]`
    );

    let statusVal = 0;

    switch(status) {
      case "N":
        statusVal = CONSTANTS.LEAD_STATUS.NEW;
        break;
      case "FU":
        statusVal = CONSTANTS.LEAD_STATUS.FOLLOW_UP;
        break;
      case "C":
        statusVal = CONSTANTS.LEAD_STATUS.CONVERTED;
        break;
      case "VD":
        statusVal = CONSTANTS.LEAD_STATUS.VISIT_DONE;
        break;
      case "VS":
        statusVal = CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED;
        break;
      case "CO":
        statusVal = CONSTANTS.LEAD_STATUS.CONTACTED;
        break;
      case "OH":
        statusVal = CONSTANTS.LEAD_STATUS.ONHOLD;
        break;
      case "I":
        statusVal = CONSTANTS.LEAD_STATUS.INTERESTED;
        break;
      case "NI":
        statusVal = CONSTANTS.LEAD_STATUS.NOT_INTERESTED;
        break;
      case "L":
        statusVal = CONSTANTS.LEAD_STATUS.LOST;
        break;
      case "SUA":
        statusVal = -1;
        break;
    }

    let leads = [];
    let summary = [];
    const limit = 10;
    let properties = [];
    let staffList = [];

    //For SalesPerson dashboard
    let bedSummary: any = {
      total: 0,
      vacant: 0,
      occupied: 0,
      movingOut: 0,
    };

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

    let staff = null;
    if(userType === CONSTANTS.USER_TYPE.STAFF && !isPartner) {
      staff = await staffDB.getById({
        id: req.id,
      });
    }

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner || (staff && staff.role === CONSTANTS.STAFF_ROLES.ADMIN || staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE)) {
      log.info(
        `[${C}], [${F}], ${
          isPartner
            ? `Partner Id [${req.id}], Partner`
            : userType === CONSTANTS.USER_TYPE.STAFF ? `Admin Id [${req.id}], Admin` 
            : `Client Id [${req.id}], Client`
        } Requesting....`
      );
      if (searchVal) {
        leads = await leadDB.getSearchResultsX({
          clientId,
          pageNum: Number(pageNum),
          limit,
          searchVal,
        });
      } else if (startDate && endDate) {
        if (status === "SUA")
        {
            leads = await leadDB.getByClientIdAndFiltersWithoutDate({
            clientId,
            propIds: propFilters,
            staffIds: staffFilters,
            sources: sourceFilters,
            status: statusVal,
            pageNum: Number(pageNum),
            limit: limit,
          });
        } else {
          leads = await leadDB.getByClientIdAndFilters({
            clientId,
            propIds: propFilters,
            staffIds: staffFilters,
            sources: sourceFilters,
            status: statusVal,
            startDate: startDate,
            endDate: endDate,
            pageNum: Number(pageNum),
            limit: limit,
          });
        }
      } else if (filter === "PR") {
        if (status === "N") {
          //New leads
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.NEW,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "FU") {
          //Follow Up lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "C") {
          //Converted lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.CONVERTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VD") {
          //Visit Done lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VS") {
          //Visit Scheduled lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "CO") {
          //Contacted lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.CONTACTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "OH") {
          //On hold lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.ONHOLD,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "I") {
          //Interest lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.INTERESTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "NI") {
          //Not Interest lead
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "L") {
          //Lost leads
          leads = await leadDB.getByPropIdAndClientIdAndStatus({
            clientId,
            propId: filterVal,
            status: CONSTANTS.LEAD_STATUS.LOST,
            pageNum: Number(pageNum),
            limit,
          });
        }  else if (status === "SUA") {
          //unassigned leads
          leads = await leadDB.getStaffUnassignedLeadsByPropId({
            clientId,
            propId: filterVal,
            pageNum: Number(pageNum),
            limit,
          });
        } else {
          leads = await leadDB.getByPropIdAndClientId({
            clientId,
            propId: filterVal,
            pageNum: Number(pageNum),
            limit,
          });
        }
      } else if (filter === "S") {
        if (status === "N") {
          //New leads
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.NEW,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "FU") {
          //Follow Up lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "C") {
          //Converted lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.CONVERTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VD") {
          //Visit Done lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VS") {
          //Visit Scheduled lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "CO") {
          //Contacted lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.CONTACTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "OH") {
          //On hold lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.ONHOLD,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "I") {
          //Interest lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.INTERESTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "NI") {
          //Not Interest lead
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "L") {
          //Lost leads
          leads = await leadDB.getByStaffIdAndClientIdAndStatus({
            clientId,
            staffs: filterVal,
            status: CONSTANTS.LEAD_STATUS.LOST,
            pageNum: Number(pageNum),
            limit,
          });
        } else {
          leads = await leadDB.getByStaffIdAndClientId({
            clientId,
            staffs: filterVal,
            pageNum: Number(pageNum),
            limit,
          });
        }
      } else if (status === "N") {
        //New leads
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.NEW,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "FU") {
        //Follow Up lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "C") {
        //Converted lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.CONVERTED,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "VD") {
        //Visit Done lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "VS") {
        //Visit Scheduled lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "CO") {
        //Contacted lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.CONTACTED,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "OH") {
        //On hold lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.ONHOLD,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "I") {
        //Interest lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.INTERESTED,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "NI") {
        //Not Interest lead
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "L") {
        //Lost leads
        leads = await leadDB.getByClientIdAndStatusApp({
          clientId,
          status: CONSTANTS.LEAD_STATUS.LOST,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (
        status === "P" &&
        propId !== "" &&
        propId !== " " &&
        propId !== "undefined"
      ) {
        //Prop filter
        leads = await leadDB.getByPropIdAndClientId({
          clientId,
          propId: propId,
          pageNum: Number(pageNum),
          limit,
        });
      } else if (status === "SUA") {
        //unassigned leads
        leads = await leadDB.getStaffUnassignedLeads({
          clientId: Number(clientId),
          pageNum: Number(pageNum),
          limit: limit,
        });
      } else {
        leads = await leadDB.getListX({
          clientId,
          pageNum: Number(pageNum),
          limit,
        });
      }
      if (startDate && endDate) {
        summary = await leadDB.getSummaryByClientIdAndFilters({
          clientId,
          sources: sourceFilters,
          propIds: propFilters,
          staffIds: staffFilters,
          startDate,
          endDate,
        });
      }
      else if (filter === "PR") {
        summary = await leadDB.getSummaryByClientIdAndPropFilter({ clientId, propIds: filterVal });
      } else if (filter === "S") {
        summary = await leadDB.getSummaryByClientIdAndStaffFilter({ clientId, staffs: filterVal }); 
      } else {
        summary = await leadDB.getSummaryByClientId({ clientId });
      }
      properties = await propertyDB.getPropIdsByClientId({
        clientId: clientId,
        status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
      });
      staffList = await staffDB.getActiveByClientId({
        clientId,
      });
      bedSummary = await bedDB.getCountsByClientId({
        clientId,
      });
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      
      staffAccounts = await staffDB.getStaffAccounts({
        mobile: staff.mobile,
      });

      // if (
      //   staff.role !== CONSTANTS.STAFF_ROLES.SALESPERSON &&
      //   staff.role !== CONSTANTS.STAFF_ROLES.WARDEN
      // ) {
      //   log.info(
      //     `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] staff can't access lead`
      //   );
      //   return res.status(400).json({
      //     msg: "Unauthorized request",
      //     isSuccess: false,
      //   });
      // }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Staff Requesting....`
      );

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

      properties = staffLinkedProps;

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

        if (searchVal) {
          leads = await leadDB.getSearchResultsForStaff({
            clientId,
            propertiesIds,
            pageNum: Number(pageNum),
            limit,
            searchVal,
            staffId: staff.id,
          });
        } else if (startDate && endDate) {
          leads = await leadDB.getByClientIdAndFiltersForStaff({
            clientId,
            staffId: staff.id,
            propIds: propFilters,
            staffIds: staffFilters,
            sources: sourceFilters,
            status: statusVal,
            startDate: startDate,
            endDate: endDate,
            pageNum: Number(pageNum),
            limit: limit,
          });
        } else if (filter === "PR") {
          if (status === "N") {
            //New leads
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.NEW,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "FU") {
            //Follow Up lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "C") {
            //Converted lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.CONVERTED,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "VD") {
            //Visit Done lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "VS") {
            //Visit Scheduled lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "CO") {
            //Contacted lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.CONTACTED,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "OH") {
            //On hold lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.ONHOLD,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "I") {
            //Interest lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.INTERESTED,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "NI") {
            //Not Interest lead
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else if (status === "L") {
            //Lost leads
            leads = await leadDB.getByPropIdAndClientIdAndStatusForStaff({
              clientId,
              propId: filterVal,
              status: CONSTANTS.LEAD_STATUS.LOST,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          } else {
            leads = await leadDB.getByPropIdAndClientIdForStaff({
              clientId,
              propId: filterVal,
              staffId: staff.id,
              pageNum: Number(pageNum),
              limit,
            });
          }
        } else if (filter === "S") {
          if (status === "N") {
            //New leads
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.NEW,
            });
          } else if (status === "FU") {
            //Follow Up lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
            });
          } else if (status === "C") {
            //Converted lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.CONVERTED,
            });
          } else if (status === "VD") {
            //Visit Done lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
            });
          } else if (status === "VS") {
            //Visit Scheduled lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
            });
          } else if (status === "CO") {
            //Contacted lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.CONTACTED,
            });
          } else if (status === "OH") {
            //On hold lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.ONHOLD,
            });
          } else if (status === "I") {
            //Interest lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.INTERESTED,
            });
          } else if (status === "NI") {
            //Not Interest lead
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
            });
          } else if (status === "L") {
            //Lost leads
            leads = await leadDB.getByStaffIdAndClientIdAndStatus({
              clientId,
              staffs: filterVal,
              status: CONSTANTS.LEAD_STATUS.LOST,
            });
          } else {
            leads = await leadDB.getByStaffIdAndClientId({
              clientId,
              staffs: filterVal,
            });
          }
        } else if (status === "N") {
          //New leads
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.NEW,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "FU") {
          //Follow Up lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "C") {
          //Converted lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.CONVERTED,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VD") {
          //Visit Done lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "VS") {
          //Visit Scheduled lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "CO") {
          //Contacted lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.CONTACTED,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "OH") {
          //On hold lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.ONHOLD,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "I") {
          //Interest lead
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.INTERESTED,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "NI") {
          //Not Interest
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.NOT_INTERESTED,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else if (status === "L") {
          //Lost
          leads = await leadDB.getByClientIdAndStatusForStaff({
            clientId,
            staffId: staff.id,
            status: CONSTANTS.LEAD_STATUS.LOST,
            propertiesIds: propertiesIds,
            pageNum: Number(pageNum),
            limit,
          });
        } else {
          leads = await leadDB.getListForStaff({
            clientId,
            // propertiesIds,
            staffId: staff.id,
            pageNum: Number(pageNum),
            limit,
          });
        }

        if (startDate && endDate) {
          summary = await leadDB.getSummaryByClientIdAndFiltersForStaff({
            clientId,
            staffId: staff.id,
            sources: sourceFilters,
            propIds: propFilters,
            staffIds: staffFilters,
            startDate,
            endDate,
          });
        } else if (filter === "PR") {
          summary = await leadDB.getSummaryByClientIdAndPropFilterForStaff({
            clientId,
            // propertiesIds,
            propIds: filterVal,
            staffId: staff.id,
          });
        } else if (filter === "S") {
          summary = await leadDB.getSummaryByClientIdAndStaffFilterForStaff({
            clientId,
            propertiesIds,
            staffs: filterVal,
            staffId: staff.id,
          });
        } else {
          summary = await leadDB.getSummaryByClientIdForStaff({
            clientId,
            staffId: staff.id, 
          });
        }
        bedSummary = await bedDB.getStatsForStaff({
          clientId,
          propertiesIds,
        });
      }
      staffList = await staffDB.getActiveByClientId({
        clientId,
      });
    }

    if (leads && leads.length > 0) {
      for (let lead of leads) {
        const leadProps = await leadDB.getLinkedProperties({
          clientId,
          leadId: lead.id,
        });
        lead.linkedProperties = leadProps || [];

        const leadStaffs = await leadDB.getLinkedStaffs({
          clientId,
          leadId: lead.id,
        });
        lead.linkedStaffs = leadStaffs || [];

        const leadNotes = await leadDB.getNotesByLeadId({
          leadId: lead.id,
          clientId,
        });
        lead.notes = leadNotes || [];
      }
    }
    const locationList = await locationDB.getByClientId({
      clientId,
    });
    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Page Num [${pageNum}], Filter [${filter}], Status [${status}], Filter Val [${filterVal}], Search Val [${searchVal}], Prop Ids [${propId}] Lead list sent successfully`
    );

    return res.status(200).json({
      msg: `Lead list sent successfully`,
      locationList: locationList || [],
      staffAccounts: staffAccounts || [],
      data: leads || [],
      summary: summary || [],
      propList: properties,
      staffs: staffList,
      bedSummary,
      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,
    });
  }
};

leads.UpdateProfile = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "UpdateProfile";
  try {
    const {
      name,
      propId,
      mobile,
      rentRange,
      roomType,
      gender,
      visitType,
      visitDateTime,
      remarks,
      source,
    } = req.body;
    const userType = req.userType;
    let clientId = req.id;
    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      const staff = await staffDB.getById({ id: staffId });
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Prop Id [${propId}], Rent Range [${rentRange}], Room Type [${roomType}], Name [${name}], Mobile [${mobile}], Gender [${gender}], Visit Type [${visitType}], Remarks [${remarks}], Source [${source}], Visit Date Time [${visitDateTime}] Staff Requested....`
      );
      if (
        staff.role === CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role === CONSTANTS.STAFF_ROLES.PARTNER ||
        staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE ||
        staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON ||
        staff.role === CONSTANTS.STAFF_ROLES.SALES_HEAD ||
        staff.role === CONSTANTS.STAFF_ROLES.WARDEN
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't update lead`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Prop Id [${propId}], Rent Range [${rentRange}], Room Type [${roomType}], Name [${name}], Mobile [${mobile}], Gender [${gender}], Visit Type [${visitType}], Remarks [${remarks}], Source [${source}], Visit Date Time [${visitDateTime}] Client Requested....`
      );
    }
    const lead = await leadDB.getByMobile({ mobile });
    if (!lead) {
      log.info(`[${C}], [${F}], Lead not found, Mobile [${mobile}]`);
      return res.status(400).json({
        msg: `Lead not found`,
        isSuccess: false,
      });
    }
    await leadDB.updateLead({
      name,
      propId,
      mobile,
      rentRange,
      roomType,
      gender,
      visitType,
      visitDateTime,
      remarks,
      source,
    });
    log.info(`[${C}], [${F}], Lead status updated successfully`);
    return res.status(200).json({
      msg: `Lead status 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,
    });
  }
};

leads.Remove = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "Remove";
  try {
    const { mobile } = req.body;
    const userType = req.userType;
    let clientId = req.id;
    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      const staff = await staffDB.getById({ id: staffId });
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Mobile [${mobile}], Staff requested to remove lead`
      );
      if (
        staff.role === CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role === CONSTANTS.STAFF_ROLES.PARTNER ||
        staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE ||
        staff.role === CONSTANTS.STAFF_ROLES.WARDEN ||
        staff.role === CONSTANTS.STAFF_ROLES.SALES_HEAD ||
        staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't remove lead`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Mobile [${mobile}], Client requested to remove lead`
      );
    }
    const lead = await leadDB.getByMobile({ mobile });
    if (!lead) {
      log.info(`[${C}], [${F}], Lead not found, Mobile [${mobile}]`);
      return res.status(400).json({
        msg: `Lead not found`,
        isSuccess: false,
      });
    }
    await leadDB.remove({ mobile });
    log.info(`[${C}], [${F}], Lead removed successfully`);
    return res.status(200).json({
      msg: `Lead removed 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,
    });
  }
};

leads.Edit = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "Edit";
  try {
    let clientId = req.id;
    const userType = req.userType;
    const { id, visitDateTime = null, remarks, status } = req.body;

    let doneByName = "";

    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      const staff = await staffDB.getById({ id: staffId });
      doneByName = staff.name || "";
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Staff Role [${staff.role}], Lead Id [${id}], Status [${status}], Visit Date Time [${visitDateTime}], Remarks [${remarks}], Staff Requested....`
      );
      if (
        staff.role === CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role === CONSTANTS.STAFF_ROLES.PARTNER ||
        staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON ||
        staff.role === CONSTANTS.STAFF_ROLES.SALES_HEAD ||
        staff.role === CONSTANTS.STAFF_ROLES.WARDEN ||
        staff.role === CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't edit lead`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Lead Id [${id}], Status [${status}], Visit Date Time [${visitDateTime}], Remarks [${remarks}], Client Requested....`
      );
    }

    const client = await clientDB.getById({ id: clientId });
    if (!client) {
      log.info(`[${C}], [${F}], Client not found, Client Id [${clientId}]`);
      return res.status(400).json({
        msg: `Client not found`,
        isSuccess: false,
      });
    }
    if (userType === CONSTANTS.USER_TYPE.CLIENT) {
      doneByName = client.name || "";
    }

    const lead = await leadDB.getById({ id });
    if (!lead) {
      log.info(`[${C}], [${F}], Client Id [${clientId}], Lead Id [${id}], No Lead Found With Id`);
      return res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
      });
    }

    const alreadyExists = await leadDB.getById({ id });
    if (!alreadyExists) {
      log.info(`[${C}], [${F}], Lead Id [${id}], Lead exists`);
      return res.status(400).json({
        msg: CONSTANTS.MSG.INVALID_REQUEST,
        isSuccess: false,
      });
    }

    const noteExist = await leadDB.isNoteExists({
      leadId: id,
      clientId,
      notes: remarks,
    });

    if (!noteExist) {
      await leadDB.recordNotes({
        clientId: clientId,
        leadId: id,
        notes: remarks,
        doneByUserType: userType,
        doneBy: req.id,
        doneByName: doneByName,
      });
    }

    await leadDB.editLead({
      id,
      visitDateTime,
      remarks,
      status,
    });

    if (status !== lead.status) {

      let arg1 = null;
      if (visitDateTime) arg1 = visitDateTime;

      await logLeadActivity(
        Number(req.userType),
        Number(req.id),
        Number(req.parentClientId!),
        Number(req.platform),
        Number(id), //leadId
        Number(status),
        Number(status),
        arg1,
      );
    }

    log.info(
      `[${C}], [${F}], Client [${clientId}], Lead Id [${id}], Lead updated successfully`
    );
    return res.status(200).json({
      msg: `Lead 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,
    });
  }
};

leads.ListForWeb = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "ListForWeb";
  try {
    let clientId = req.id;
    const userType = req.userType;
    let { startDate, endDate, filter, searchVal } = req.query;
    let pageNum = 1;
    if (userType == CONSTANTS.USER_TYPE.STAFF) {
      const staffId = req.id;
      log.info(
        `[${C}], [${F}], Staff Id [${staffId}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}], Search Val [${searchVal}], Staff Requesting....`
      );

      const staff = await staffDB.getById({ id: staffId });
      if (
        staff.role == CONSTANTS.STAFF_ROLES.ADMIN ||
        staff.role == CONSTANTS.STAFF_ROLES.WARDEN ||
        staff.role === CONSTANTS.STAFF_ROLES.PARTNER
      ) {
        clientId = staff.clientId;
      } else {
        log.info(
          `[${C}], [${F}], Staff Id [${staffId}], Non-Admin staff can't get lead list`
        );
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
    } else {
      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}], Search Val [${searchVal}], Client Requesting....`
      );
    }
    let leads = [];
    let summary = [];
    const limit = 10;
    if (searchVal) {
      // leads = await leadDB.getSearchResults({
      //   clientId,
      //   pageNum: Number(pageNum),
      //   limit,
      //   searchVal,
      // });
      leads = await leadDB.getSearchResultsX({
        clientId,
        pageNum: Number(pageNum),
        limit,
        searchVal,
      });
    } else if (filter === "N") {
      //New leads
      leads = await leadDB.getByClientIdAndStatus({
        clientId,
        status: CONSTANTS.LEAD_STATUS.NEW,
        startDate,
        endDate,
      });
    } else if (filter === "FU") {
      //Follow Up lead
      leads = await leadDB.getByClientIdAndStatus({
        clientId,
        status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
        startDate,
        endDate,
      });
    } else if (filter === "C") {
      //Converted lead
      leads = await leadDB.getByClientIdAndStatus({
        clientId,
        status: CONSTANTS.LEAD_STATUS.CONVERTED,
        startDate,
        endDate,
      });
    } else if (filter === "VD") {
      //Visit Done lead
      leads = await leadDB.getByClientIdAndStatus({
        clientId,
        status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
        startDate,
        endDate,
      });
    } else if (filter === "A") {
      //To reset filter
      leads = await leadDB.getListByDateRange({
        clientId,
        startDate,
        endDate,
      });
    } else {
      leads = await leadDB.getListByDateRange({
        clientId,
        startDate,
        endDate,
      });
    }
    summary = await leadDB.getSummaryByClientIdAndDate({
      clientId,
      startDate,
      endDate,
    });
    log.info(`[${C}], [${F}], Lead list sent successfully`);
    return res.status(200).json({
      msg: `Lead list sent successfully`,
      data: leads || [],
      summary: summary || [],
      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,
    });
  }
};

// leads.ListForWebX = async (req: CustomRequest, res: Response) => {
//   const C = "Lead Controller";
//   const F = "ListForWebX";
//   try {
//     const userType = req.userType;
//     let { startDate, endDate, filter, s, locationIds,} = req.query;
//     const searchVal = s ? String(s) : null;
//     let pageNum = 1;

//     let leads = [];
//     let summary = [];
//     const limit = 10;

//     log.info(
//       `[${C}], [${F}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}], Search Val [${searchVal}], Location Ids [${locationIds}]`
//     );

//     let locationFilters = null;

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

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

//     let isStaffAllowed = false;

//     if (userType === CONSTANTS.USER_TYPE.STAFF) {
//       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 
//         });
//       }
//       isStaffAllowed = await isPrivilegedStaff(staff.role, 1);
//     }

//     if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner || isStaffAllowed) {
//       log.info(
//         `[${C}], [${F}], ${
//           isStaffAllowed ? `Staff Id [${req.id}], Staff`
//             : isPartner
//               ? `Partner Id [${req.id}], Partner`
//               : `Client Id [${req.id}], Client`
//         } Requested....`
//       );
//       if (searchVal) {
//         //log.info(`[${C}], [${F}], Page ${pageNum} Getting search results for leads`);
//         // leads = await leadDB.getSearchResults({
//         //   clientId,
//         //   pageNum: Number(pageNum),
//         //   limit,
//         //   searchVal,
//         // });
//         leads = await leadDB.getSearchResultsX({
//           clientId,
//           pageNum: Number(pageNum),
//           limit,
//           searchVal,
//         });
//       } else if (filter === "N") {
//         //New leads
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.NEW,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "FU") {
//         //Follow Up lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "C") {
//         //Converted lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.CONVERTED,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "VD") {
//         //Visit Done lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "VS") {
//         //Visit Schedule lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "NA") {
//         //Not Answered lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.NOT_ANSWERED,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "OH") {
//         //On Hold lead
//         leads = await leadDB.getByClientIdAndStatusX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.ONHOLD,
//           startDate,
//           endDate,
//           locationFilters,
//         });
//       } else if (filter === "A") {
//         //To reset filter
//         leads = await leadDB.getListByDateRangeX({
//           clientId,
//           startDate,
//           endDate,
//         });
//       } else {
//         leads = await leadDB.getListByDateRangeX({
//           clientId,
//           startDate,
//           endDate,
//         });
//       }

//       summary = await leadDB.getSummaryByClientIdAndDate({
//         clientId,
//         startDate,
//         endDate,
//         locationFilters,
//       });
//     } else {
//       const staff = await staffDB.getById({ id: req.id });
//       if (!staff) {
//         log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
//         return res.status(400).json({
//           msg: CONSTANTS.MSG.INVALID_REQUEST,
//           isSuccess: false,
//         });
//       }
//       // if (
//       //   staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
//       //   staff.role !== CONSTANTS.STAFF_ROLES.SALESPERSON &&
//       //   staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE && 
//       //   staff.role !== CONSTANTS.STAFF_ROLES.WARDEN
//       // ) {
//       //   log.info(
//       //     `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] Non-Admin staff can't assign property to lead`
//       //   );
//       //   return res.status(400).json({
//       //     msg: "Unauthorized request",
//       //     isSuccess: false,
//       //   });
//       // }
//       log.info(
//         `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], ${
//           staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON
//             ? "SalesPerson"
//             : "Admin"
//         } Requested....`
//       );

//       if (searchVal) {
//         //log.info(`[${C}], [${F}], Page ${pageNum} Getting search results for leads`);
//         // leads = await leadDB.getSearchResults({
//         //   clientId,
//         //   pageNum: Number(pageNum),
//         //   limit,
//         //   searchVal,
//         // });
//         leads = await leadDB.getSearchResultsX({
//           clientId,
//           pageNum: Number(pageNum),
//           limit,
//           searchVal,
//         });
//       } else if (filter === "N") {
//         //New leads
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.NEW,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "FU") {
//         //Follow Up lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "C") {
//         //Converted lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.CONVERTED,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "VD") {
//         //Visit Done lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "VS") {
//         //Visit Schedule lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "NA") {
//         //Not Answered lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.NOT_ANSWERED,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "OH") {
//         //On Hold lead
//         leads = await leadDB.getByClientIdAndStatusForStaffX({
//           clientId,
//           status: CONSTANTS.LEAD_STATUS.ONHOLD,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else if (filter === "A") {
//         //To reset filter
//         leads = await leadDB.getListByDateRangeForStaff({
//           clientId,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       } else {
//         leads = await leadDB.getListByDateRangeForStaff({
//           clientId,
//           startDate,
//           endDate,
//           staffId: staff.id,
//         });
//       }

//       summary = await leadDB.getSummaryByClientIdAndDateForStaff({
//         clientId,
//         startDate,
//         endDate,
//         staffId: staff.id,
//         locationFilters,
//       });
//     }

//     // if (searchVal) {
//     //   //log.info(`[${C}], [${F}], Page ${pageNum} Getting search results for leads`);
//     //   // leads = await leadDB.getSearchResults({
//     //   //   clientId,
//     //   //   pageNum: Number(pageNum),
//     //   //   limit,
//     //   //   searchVal,
//     //   // });
//     //   leads = await leadDB.getSearchResultsX({
//     //     clientId,
//     //     pageNum: Number(pageNum),
//     //     limit,
//     //     searchVal,
//     //   });
//     // } else if (filter === "N") {
//     //   //New leads
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.NEW,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "FU") {
//     //   //Follow Up lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.FOLLOW_UP,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "C") {
//     //   //Converted lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.CONVERTED,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "VD") {
//     //   //Visit Done lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.VISIT_DONE,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "VS") {
//     //   //Visit Schedule lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "NA") {
//     //   //Not Answered lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.NOT_ANSWERED,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "OH") {
//     //   //On Hold lead
//     //   leads = await leadDB.getByClientIdAndStatusX({
//     //     clientId,
//     //     status: CONSTANTS.LEAD_STATUS.ONHOLD,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else if (filter === "A") {
//     //   //To reset filter
//     //   leads = await leadDB.getListByDateRangeX({
//     //     clientId,
//     //     startDate,
//     //     endDate,
//     //   });
//     // } else {
//     //   leads = await leadDB.getListByDateRangeX({
//     //     clientId,
//     //     startDate,
//     //     endDate,
//     //   });
//     // }

//     // summary = await leadDB.getSummaryByClientIdAndDate({
//     //   clientId,
//     //   startDate,
//     //   endDate,
//     // });

//     if (leads && leads.length > 0) {
//       for (let lead of leads) {
//         if(lead?.visitDateTime){
//           lead.visitDateTime = moment(lead.visitDateTime).format("YYYY-MM-DD HH:mm:ss");
//         }
//         const leadProps = await leadDB.getLinkedProperties({
//           clientId,
//           leadId: lead.id,
//         });
//         lead.linkedProperties = leadProps || [];

//         const leadStaffs = await leadDB.getLinkedStaffs({
//           clientId,
//           leadId: lead.id,
//         });
//         lead.linkedStaffs = leadStaffs || [];

//         const leadNotes = await leadDB.getNotesByLeadId({
//           leadId: lead.id,
//           clientId,
//         });
//         lead.notes = leadNotes || [];
//       }
//     }

//     const staffList = await staffDB.getActiveByClientId({
//       clientId,
//     });

//     log.info(`[${C}], [${F}], Lead list sent successfully`);
//     return res.status(200).json({
//       msg: `Lead list sent successfully`,
//       data: leads || [],
//       summary: summary || [],
//       staffList: staffList || [],
//       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,
//     });
//   }
// };

leads.ListForWebX = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "ListForWebX";
  try {
    const userType = req.userType;
    let { startDate, endDate, filter, s, locationFilters, sourceFilters, staffFilters, propFilters,} = req.query;
    const searchVal = s ? String(s) : null;
    let pageNum = 1;

    let leads = [];
    let summary = [];
    const limit = 10;

    let statusVal = 0;

    if (filter && String(filter).trim() !== "" && String(filter).toLowerCase().trim() !== "null" && String(filter).toLowerCase().trim() !== "undefined") {
      switch(filter) {
        case "N":
          statusVal = CONSTANTS.LEAD_STATUS.NEW;
          break;
        case "FU":
          statusVal = CONSTANTS.LEAD_STATUS.FOLLOW_UP;
          break;
        case "C":
          statusVal = CONSTANTS.LEAD_STATUS.CONVERTED;
          break;
        case "VD":
          statusVal = CONSTANTS.LEAD_STATUS.VISIT_DONE;
          break;
        case "VS":
          statusVal = CONSTANTS.LEAD_STATUS.VISIT_SCHEDULED;
          break;
        case "CO":
          statusVal = CONSTANTS.LEAD_STATUS.CONTACTED;
          break;
        case "OH":
          statusVal = CONSTANTS.LEAD_STATUS.ONHOLD;
          break;
        case "I":
          statusVal = CONSTANTS.LEAD_STATUS.INTERESTED;
          break;
        case "NI":
          statusVal = CONSTANTS.LEAD_STATUS.NOT_INTERESTED;
          break;
        case "L":
          statusVal = CONSTANTS.LEAD_STATUS.LOST;
          break;
        case "SUA":
          statusVal = -1;
          break;
      }
    }


    log.info(
      `[${C}], [${F}], Start Date [${startDate}], End Date [${endDate}], Filter [${filter}], Search Val [${searchVal}], Location Ids [${locationFilters}], Source Filters [${sourceFilters}], Staff Filters [${staffFilters}], Property Filters [${propFilters}]`
    );

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

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

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

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

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

    let isStaffAllowed = false;

    if (userType === CONSTANTS.USER_TYPE.STAFF) {
      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 
        });
      }
      isStaffAllowed = await isPrivilegedStaff(staff.role, 1);
    }

    if (userType === CONSTANTS.USER_TYPE.CLIENT || isPartner || isStaffAllowed) {
      log.info(
        `[${C}], [${F}], ${
          isStaffAllowed ? `Staff Id [${req.id}], Staff`
            : isPartner
              ? `Partner Id [${req.id}], Partner`
              : `Client Id [${req.id}], Client`
        } Requested....`
      );
      if (searchVal) {
        leads = await leadDB.getSearchResultsX({
          clientId,
          pageNum: Number(pageNum),
          limit,
          searchVal,
        });
      } else {
        leads = await leadDB.getByClientIdAndFilters({
          clientId,
          propIds: propFilters,
          staffIds: staffFilters,
          sources: sourceFilters,
          locations: locationFilters,
          status: statusVal,
          startDate: startDate,
          endDate: endDate,
          pageNum: 1,
          limit: null,
        });
      }

      summary = await leadDB.getSummaryByClientIdAndFilters({
        clientId,
        sources: sourceFilters,
        propIds: propFilters,
        staffIds: staffFilters,
        locations: locationFilters,
        startDate,
        endDate,
      });
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], ${
          staff.role === CONSTANTS.STAFF_ROLES.SALESPERSON
            ? "SalesPerson"
            : "Admin"
        } Requested....`
      );

      if (searchVal) {
        leads = await leadDB.getSearchResultsX({
          clientId,
          pageNum: Number(pageNum),
          limit,
          searchVal,
        });
      } else {
        leads = await leadDB.getByClientIdAndFiltersForStaff({
          clientId,
          staffId: staff.id,
          propIds: propFilters,
          locations: locationFilters,
          staffIds: staffFilters,
          sources: sourceFilters,
          status: statusVal,
          startDate: startDate,
          endDate: endDate,
          pageNum: 1,
          limit: null,
        });
      }

      summary = await leadDB.getSummaryByClientIdAndFiltersForStaff({
        clientId,
        staffId: staff.id,
        sources: sourceFilters,
        propIds: propFilters,
        locations: locationFilters,
        staffIds: staffFilters,
        startDate,
        endDate,
      });
    }

    if (leads && leads.length > 0) {
      for (let lead of leads) {
        if(lead?.visitDateTime){
          lead.visitDateTime = moment(lead.visitDateTime).format("YYYY-MM-DD HH:mm:ss");
        }
        const leadProps = await leadDB.getLinkedProperties({
          clientId,
          leadId: lead.id,
        });
        lead.linkedProperties = leadProps || [];

        const leadStaffs = await leadDB.getLinkedStaffs({
          clientId,
          leadId: lead.id,
        });
        lead.linkedStaffs = leadStaffs || [];

        const leadNotes = await leadDB.getNotesByLeadId({
          leadId: lead.id,
          clientId,
        });
        lead.notes = leadNotes || [];
      }
    }

    const staffList = await staffDB.getActiveByClientId({
      clientId,
    });

    log.info(`[${C}], [${F}], Lead list sent successfully`);
    return res.status(200).json({
      msg: `Lead list sent successfully`,
      data: leads || [],
      summary: summary || [],
      staffList: staffList || [],
      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,
    });
  }
};

leads.AssignProperty = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "AssignProperty";
  try {
    const { toggleValue, propId, leadId } = req.body;
    const userType = req.userType;

    log.info(
      `[${C}], [${F}], User Type [${userType}], Toggle Value [${toggleValue}], Prop Id [${propId}], Lead Id [${leadId}]`
    );

    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 [${req.id}], Client`
        } Requested....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALESPERSON &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALES_HEAD &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] Non-Admin staff can't assign property to lead`
        );
        return res.status(400).json({
          msg: "Unauthorized request",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin Requested....`
      );
    }

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

    if (toggleValue === CONSTANTS.TOGGLES.LINK) {
      const lead = await leadDB.getById({ id: leadId });
      if (!lead) {
        log.info(`[${C}], [${F}], Lead not found, Lead Id [${leadId}]`);
        return res.status(400).json({
          msg: `Lead not found`,
          isSuccess: false,
        });
      }
      const isAlreadyLinked = await leadDB.isAlreadyLinked({
        clientId,
        propId,
        leadId,
      });

      if (isAlreadyLinked) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Staff Id [${leadId}], Lead already linked`
        );
        return res
          .status(400)
          .json({ msg: "Lead already linked", isSuccess: false });
      }

      await leadDB.link({ clientId, propId, leadId });

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Staff Id [${leadId}], Lead linked Successfully`
      );
    } else {
      await leadDB.unlink({ clientId, propId, leadId });

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Property Id [${propId}],  Toggle Value [${toggleValue}], Property Id [${propId}], Staff Id [${leadId}], Lead unlinked Successfully`
      );
    }
    return res.status(200).json({
      msg: `Lead ${
        toggleValue === CONSTANTS.TOGGLES.LINK ? "linked" : "unlinked"
      } 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,
    });
  }
};

leads.AssignStaff = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "AssignStaff";
  try {
    const { toggleValue, staffId, leadId } = req.body;
    const userType = req.userType;

    log.info(
      `[${C}], [${F}], User Type [${userType}], Toggle Value [${toggleValue}], Staff Id [${staffId}], Lead Id [${leadId}]`
    );

    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 [${req.id}], Client`
        } Requested....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        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.SALES_HEAD &&
        staff.role !== CONSTANTS.STAFF_ROLES.SUPER_ADMIN
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] Non-Admin staff can't assign staff to lead`
        );
        return res.status(400).json({
          msg: "Unauthorized request",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin Requested....`
      );
    }

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

    const lead = await leadDB.getById({ id: leadId });
    if (!lead) {
      log.info(`[${C}], [${F}], Lead not found, Lead Id [${leadId}]`);
      return res.status(400).json({
        msg: `Lead not found`,
        isSuccess: false,
      });
    }

    if (toggleValue === CONSTANTS.TOGGLES.LINK) {
      const isAlreadyLinked = await leadDB.isStaffAlreadyLinked({
        clientId,
        staffId,
        leadId,
      });

      if (isAlreadyLinked) {
        log.info(
          `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}],  Toggle Value [${toggleValue}], Lead Id [${leadId}], Lead already linked`
        );
        return res
          .status(400)
          .json({ msg: "Lead already linked", isSuccess: false });
      }

      await leadDB.linkStaff({ clientId, staffId, leadId });

      const propSettings = await settingsDB.getByClientId({
        clientId: clientId,
      });

      let footerText = propSettings[0].footer || "The Kipinn Team";

      sendWhatsappStaffLeadAssigned(staff.mobile, lead.name, lead.mobile, footerText, Number(clientId));

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}],  Toggle Value [${toggleValue}], Lead Id [${leadId}], Lead linked Successfully`
      );
    } else {
      await leadDB.unlinkStaff({ clientId, staffId, leadId });

      log.info(
        `[${C}], [${F}], Client Id [${clientId}], Staff Id [${staffId}],  Toggle Value [${toggleValue}], Lead Id [${leadId}], Lead unlinked Successfully`
      );
    }

    if (toggleValue === CONSTANTS.TOGGLES.LINK) {
      await logLeadActivity(
        Number(req.userType),
        Number(req.id),
        Number(req.parentClientId!),
        Number(req.platform),
        Number(leadId),
        CONSTANTS.LEAD_ACTIVITY_TYPES.STAFF_ASSIGNED,
        Number(lead.status),
        staff.name, //arg1
      );
    }

    return res.status(200).json({
      msg: `Lead ${
        toggleValue === CONSTANTS.TOGGLES.LINK ? "linked" : "unlinked"
      } 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,
    });
  }
};

leads.LinkedProperties = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "LinkedProperties";
  try {
    const { leadId } = req.params;
    const userType = req.userType;

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

    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 [${req.id}], Client`
        } Requested....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALESPERSON &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALES_HEAD &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] Non-Admin staff can't get linked properties`
        );
        return res.status(400).json({
          msg: "Unauthorized request",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin Requested....`
      );
    }
    const lead = await leadDB.getById({ id: Number(leadId) });
    if (!lead) {
      log.info(`[${C}], [${F}], Lead Id [${leadId}], Lead not found`);
      return res.status(400).json({
        msg: `Lead not found`,
        isSuccess: false,
      });
    }

    let iterableProperties = null;

    const linkedProperties = await leadDB.getLinkedProperties({
      clientId,
      leadId: Number(leadId),
    });
    const allProperties = await propertyDB.getActivePropIdsByClientId({
      clientId,
      status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
    });

    iterableProperties = allProperties || [];


    const combinedPropList = iterableProperties.map(
      (property: propertiesTypes) => {
        let isExists = false;
        if (linkedProperties) {
          isExists = linkedProperties.find(
            (prop: propertiesTypes) => prop.id === property.id
          );
        }
        return {
          id: property.id,
          name: property.name,
          isLinked: isExists ? 1 : 0,
        };
      }
    );

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Lead Id [${leadId}], Linked Properties sent successfully`
    );

    return res.status(200).json({
      msg: `Linked Properties sent successfully`,
      data: combinedPropList,
      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,
    });
  }
};

leads.LinkedStaff = async (req: CustomRequest, res: Response) => {
  const C = "Lead Controller";
  const F = "LinkedStaffs";
  try {
    const { leadId } = req.params;
    const userType = req.userType;

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

    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 [${req.id}], Client`
        } Requested....`
      );
    } else {
      const staff = await staffDB.getById({ id: req.id });
      if (!staff) {
        log.info(`[${C}], [${F}], Staff not found, Id [${req.id}]`);
        return res.status(400).json({
          msg: CONSTANTS.MSG.INVALID_REQUEST,
          isSuccess: false,
        });
      }
      if (
        staff.role !== CONSTANTS.STAFF_ROLES.ADMIN &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALESPERSON &&
        staff.role !== CONSTANTS.STAFF_ROLES.SALES_HEAD &&
        staff.role !== CONSTANTS.STAFF_ROLES.WARDEN &&
        staff.role !== CONSTANTS.STAFF_ROLES.BACK_OFFICE
      ) {
        log.info(
          `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}] Non-Admin staff can't get linked properties`
        );
        return res.status(400).json({
          msg: "Unauthorized request",
          isSuccess: false,
        });
      }
      log.info(
        `[${C}], [${F}], Staff Id [${req.id}], Staff Role [${staff.role}], Admin Requested....`
      );
    }
    const lead = await leadDB.getById({ id: Number(leadId) });
    if (!lead) {
      log.info(`[${C}], [${F}], Lead Id [${leadId}], Lead not found`);
      return res.status(400).json({
        msg: `Lead not found`,
        isSuccess: false,
      });
    }

    let iterableStaffs = null;

    const linkedStaffs = await leadDB.getLinkedStaff({
      clientId,
      leadId: Number(leadId),
    });
    const allStaffs = await staffDB.getActiveByClientId({
      clientId,
    });

    iterableStaffs = allStaffs || [];

    // if (userType === CONSTANTS.USER_TYPE.STAFF && !isPartner) {
    //   const staffLinkedProps = await propertyDB.getPropsByStaffId({
    //     staffId: req.id,
    //   });

    //   iterableProperties = staffLinkedProps || [];
    // }

    const combinedStaffList = iterableStaffs.map((staff: staffsTypes) => {
      let isExists = false;
      if (linkedStaffs) {
        isExists = linkedStaffs.find((s: staffsTypes) => s.id === staff.id);
      }
      return {
        id: staff.id,
        name: staff.name,
        isLinked: isExists ? 1 : 0,
      };
    });

    log.info(
      `[${C}], [${F}], Client Id [${clientId}], Lead Id [${leadId}], Linked Properties sent successfully`
    );

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

export default leads;
