import moment from "moment";
import CONSTANTS from "../../config/constants";
import bankDB from "../../models/bank.model";
import propertyDB from "../../models/property.model";
import clientsTypes from "../../schemas/client.schema";
import transactionDB from "../../models/transaction.model";
import duesDB from "../../models/dues.model";
import createIncomeStats from "./createIncomeStats";
import bedDB from "../../models/beds.model";
import notificationDB from "../../models/notification.model";
import requestDB from "../../models/request.model";
import staffsTypes from "../../schemas/staff.schema";
import complaintDB from "../../models/complaint.model";
import propertiesTypes from "../../schemas/property.schema";
import expense from "../../controllers/expense.controller";
import expenseDB from "../../models/expense.model";
import log from "../../config/log";
import occupancyDB from "../../models/occupancy.model";
import roomDB from "../../models/room.model";
import moveOutDB from "../../models/moveOut.model";
import occupancyReportDB from "../../models/occupancyReport.model";
import staffDB from "../../models/staff.model";
import leadDB from "../../models/lead.model";
import bookingsDB from "../../models/bookings.model";

export const clientDashboard = async (client: clientsTypes) => {
  const clientId = client.id;
  const properties = await propertyDB.getPropIdsByClientId({
    clientId,
    status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
  });
  const banks = await bankDB.getByClientId({ clientId });

  let stats = [
    {
      totalIncome: 0,
      totalDues: 0,
      month: moment().format("M"),
      year: moment().format("YYYY"),
    },
  ];

  let dueTenantCount = 0;
  let todaysCollection = 0;
  let todaysSecurityCollection = 0;
  let pendingComplaintsCount = 0;
  let currentMonthExpenses = 0;
  let beds = {
    total: 0,
    vacant: 0,
    occupied: 0,
    movingOut: 0,
  };

  let isPendingPropertyExists = false;

  if (properties) {
    pendingComplaintsCount = await complaintDB.getPendingComplaints({
      clientId,
    });

    todaysCollection = await transactionDB.getTodaysCollection({
      clientId,
    });

    todaysSecurityCollection = await transactionDB.getTodaysSecurityCollection({
      clientId,
    });

    // const transactionStats = await transactionDB.getTotalIncomeStats({
    //   clientId,
    //   status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    // });

    currentMonthExpenses = await expenseDB.getCurMonthExpense({
      clientId,
    });

    // const duesStats = await duesDB.getTotalDuesStats({
    //   clientId,
    // });

    const isOtherThanPending = properties.find(
      (prop: propertiesTypes) =>
        prop.status !== CONSTANTS.PROPERTY_STATUS.PENDING
    );

    // stats = await createIncomeStats(stats, transactionStats, duesStats);

    for (const prop of properties) {
      if (
        prop.status === CONSTANTS.PROPERTY_STATUS.PENDING &&
        !isOtherThanPending
      )
        isPendingPropertyExists = true;

      // if (
      //   prop.status === CONSTANTS.PROPERTY_STATUS.PENDING ||
      //   prop.status === CONSTANTS.PROPERTY_STATUS.INACTIVE ||
      //   prop.status === CONSTANTS.PROPERTY_STATUS.COMPLETED
      // )

      if (prop.status != CONSTANTS.PROPERTY_STATUS.ACTIVE) continue;

      const counts = await bedDB.getCountsByPropId({ propId: prop.id });
      beds.total += Number(counts.total) || 0;
      beds.vacant += Number(counts.vacant) || 0;
      beds.occupied += Number(counts.occupied) || 0;
      beds.movingOut += Number(counts.movingOut) || 0;
    }
  }

  const unreadNotifications = await notificationDB.getUnreadNotifications({
    userId: clientId,
    userType: CONSTANTS.USER_TYPE.CLIENT,
  });

  const pendingRequests = await requestDB.getPendingReqByClientId({
    clientId,
  });

  const summary = await occupancyDB.getOccupancyStatsForClient(clientId);

  // const occupancyData = await occupancyReportDB.getOccupancyReport({
  //   clientId,
  // });

  let curMonthOccupancy = ((beds.occupied / beds.total) * 100).toFixed(2) || 0;
  let prevMonthOccupancy = null;

  // if (occupancyData && occupancyData.length > 0) {
  //   const curMonth = occupancyData?.find((d: any) => d.month === Number(moment().month() + 1));
  //   const prevMonth = occupancyData?.find((d: any) => d.month === Number(moment().month()));

  //   curMonthOccupancy = ((beds.occupied / beds.total) * 100).toFixed(2) || 0;
  //   // const curMonthOccupancy = ((curMonth?.occupied / curMonth?.total) * 100).toFixed(2) || 0;
  //   prevMonthOccupancy = ((prevMonth?.occupied / prevMonth?.total) * 100).toFixed(2) || 0;
  // }

  const prevMonthOccupancyData = await occupancyReportDB.getOccupancyReportByYearMonth({
    clientId,
    year: moment().subtract(1, "month").format("YYYY"),
    month: moment().subtract(1, "month").format("MM"),
  });

  if (prevMonthOccupancyData) {    
    prevMonthOccupancy = ((prevMonthOccupancyData?.occupied / prevMonthOccupancyData?.total) * 100).toFixed(2) || 0;
  }

  summary.curMonthOccupancy = Number(curMonthOccupancy) || 0;
  summary.prevMonthOccupancy = Number(prevMonthOccupancy) || 0;

  const data = {
    //stats, // Sukhbir on 26th Jan 2025
    todaysCollection: todaysCollection || 0,
    todaysSecurityCollection: todaysSecurityCollection || 0,
    currentMonthExpenses,
    //dueTenantCount: Number(dueTenantCount) || 0,
    isPropertyExists: properties ? true : false,
    isPendingPropertyExists,
    pendingComplaintsCount: Number(pendingComplaintsCount) || 0,
    isBankExists: banks ? true : false,
    beds,
    summary: summary || 0,
    pendingRequests: Number(pendingRequests) || 0,
    unreadNotifications: Number(unreadNotifications) || 0,
    clientStatus: client.status,
  };

  return data;
};

// export const clientDashboardFilter = async (
//   client: clientsTypes,
//   month: any,
//   year: any
// ) => {
//   const clientId = client.id;
//   const properties = await propertyDB.getPropIdsByClientId({
//     clientId,
//     status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
//   });
//   const banks = await bankDB.getByClientId({ clientId });

//   let stats = [
//     {
//       totalIncome: 0,
//       totalDues: 0,
//       month: moment().format("M"),
//       year: moment().format("YYYY"),
//     },
//   ];

//   let dueTenantCount = 0;
//   let todaysCollection = 0;
//   let pendingComplaintsCount = 0;
//   let currentMonthExpenses = 0;
//   let beds = {
//     total: 0,
//     vacant: 0,
//     occupied: 0,
//   };

//   let isPendingPropertyExists = false;

//   if (properties) {
//     pendingComplaintsCount = await complaintDB.getPendingComplaints({
//       clientId,
//     });

//     todaysCollection = await transactionDB.getTodaysCollection({
//       clientId,
//     });

//     const transactionStats = await transactionDB.getTotalIncomeStats({
//       clientId,
//       status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
//     });

//     currentMonthExpenses = await expenseDB.getCurMonthExpense({
//       clientId,
//     });

//     const duesStats = await duesDB.getTotalDuesStats({
//       clientId,
//     });

//     const isOtherThanPending = properties.find(
//       (prop: propertiesTypes) =>
//         prop.status !== CONSTANTS.PROPERTY_STATUS.PENDING
//     );

//     stats = await createIncomeStats(stats, transactionStats, duesStats);

//     //const tenantCount = await duesDB.getTenantCount({ clientId });
//     //dueTenantCount = tenantCount.dueTenantCount;

//     for (const prop of properties) {
//       if (
//         prop.status === CONSTANTS.PROPERTY_STATUS.PENDING &&
//         !isOtherThanPending
//       )
//         isPendingPropertyExists = true;

//       if (
//         prop.status === CONSTANTS.PROPERTY_STATUS.PENDING ||
//         prop.status === CONSTANTS.PROPERTY_STATUS.INACTIVE
//       )
//         continue;

//       const counts = await bedDB.getCountsByPropId({ propId: prop.id });
//       beds.total += Number(counts.total) || 0;
//       beds.vacant += Number(counts.vacant) || 0;
//       beds.occupied += Number(counts.occupied) || 0;
//     }
//   }

//   const unreadNotifications = await notificationDB.getUnreadNotifications({
//     userId: clientId,
//     userType: CONSTANTS.USER_TYPE.CLIENT,
//   });

//   const pendingRequests = await requestDB.getPendingReqByClientId({
//     clientId,
//   });

//   const data = {
//     stats,
//     todaysCollection,
//     currentMonthExpenses,
//     //dueTenantCount: Number(dueTenantCount) || 0,
//     isPropertyExists: properties ? true : false,
//     isPendingPropertyExists,
//     pendingComplaintsCount: Number(pendingComplaintsCount) || 0,
//     isBankExists: banks ? true : false,
//     beds,
//     pendingRequests: Number(pendingRequests) || 0,
//     unreadNotifications: Number(unreadNotifications) || 0,
//     clientStatus: client.status,
//   };

//   return data;
// };

export const staffAdminDashboard = async (staff: staffsTypes) => {
  const staffId = staff.id;
  const clientId = staff.clientId;

  let stats = [
    {
      totalIncome: 0,
      totalDues: 0,
      month: moment().format("M"),
      year: moment().format("YYYY"),
    },
  ];

  let dueTenantCount = 0;
  let todaysCollection = 0;
  let todaysSecurityCollection = 0;
  let currentMonthExpenses = 0;
  let beds = {
    total: 0,
    vacant: 0,
    occupied: 0,
    movingOut: 0,
  };

  let summary = {
    moveIn: 0,
    moveOut: 0,
    totalTenants: 0,
    unVerified: 0,
    verified: 0,
    reserved: 0,
    newTenants: 0,
    curMonthOccupancy: 0,
    prevMonthOccupancy: 0,
  };

  let pendingRequestsCount = 0;
  let pendingComplaintsCount = 0;
  let isPendingPropertyExists = false;
  const banks = await bankDB.getByClientId({ clientId: staff.clientId });

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

  let propertyNames: string[] = [];

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

    propertyNames = staffLinkedProps.map((prop: propertiesTypes) => prop.name);

    const transactionStats = await transactionDB.getTotalIncomeStatsForStaff({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      propertiesIds,
    });
    //log.info(`transactionStats [${JSON.stringify(transactionStats)}]`);
    todaysCollection = await transactionDB.getTodaysCollectionForStaff({
      clientId,
      propertiesIds,
    });

    todaysSecurityCollection =
      await transactionDB.getTodaysSecurityCollectionForStaff({
        clientId,
        propertiesIds,
      });

    currentMonthExpenses = await expenseDB.getCurMonthExpenseForStaff({
      clientId,
      propertiesIds,
    });

    const duesStats = await duesDB.getTotalDuesStatsForStaff({
      clientId,
      propertiesIds,
    });
    stats = await createIncomeStats(stats, transactionStats, duesStats);

    const tenantCount = await duesDB.getTenantCountForStaff({
      clientId,
      propertiesIds,
    });
    dueTenantCount = tenantCount.dueTenantCount;

    pendingRequestsCount = await requestDB.getPendingReqForStaff({
      clientId,
      propertiesIds,
    });

    pendingComplaintsCount = await complaintDB.getPendingComplaintsForStaff({
      clientId,
      propertiesIds,
    });

    if (staff.role === CONSTANTS.STAFF_ROLES.WARDEN) {
      pendingComplaintsCount = await complaintDB.getComplaintCountForStaff({
        assignedTo: staffId,
        status: CONSTANTS.COMPLAINT_STATUS.ASSIGNED,
      });
    }

    const isOtherThanPending = staffLinkedProps.find(
      (prop: propertiesTypes) =>
        prop.status !== CONSTANTS.PROPERTY_STATUS.PENDING
    );

    for (let prop of staffLinkedProps) {
      if (prop.status === CONSTANTS.PROPERTY_STATUS.PENDING && !isOtherThanPending)
        isPendingPropertyExists = true;

      // if (
      //   prop.status === CONSTANTS.PROPERTY_STATUS.PENDING ||
      //   prop.status === CONSTANTS.PROPERTY_STATUS.INACTIVE
      // )
      //   continue;

      if (prop.status != CONSTANTS.PROPERTY_STATUS.ACTIVE) continue;

      const counts = await bedDB.getCountsByPropId({ propId: prop.id });
      beds.total += Number(counts.total) || 0;
      beds.vacant += Number(counts.vacant) || 0;
      beds.occupied += Number(counts.occupied) || 0;
      beds.movingOut += Number(counts.movingOut) || 0;

      const data = await occupancyDB.getOccupancyStatsByPropId(
        clientId,
        prop.id
      );
      summary.moveIn += Number(data.moveIn) || 0;
      summary.moveOut += Number(data.moveOut) || 0;
      summary.totalTenants += Number(data.totalTenants) || 0;
      summary.unVerified += Number(data.unVerified) || 0;
      summary.verified += Number(data.verified) || 0;
      summary.reserved += Number(data.reserved) || 0;
      summary.newTenants += Number(data.newTenants) || 0;
    }

    // const occupancyData = await occupancyReportDB.getOccupancyReportForStaff({
    //   clientId: clientId,
    //   propertiesIds: propertiesIds
    // });

    let curMonthOccupancy = ((beds.occupied / beds.total) * 100).toFixed(2) || 0;
    let prevMonthOccupancy = null;

    // if (occupancyData && occupancyData.length > 0) {
    //   const curMonth = occupancyData?.find((d: any) => d.month === Number(moment().month() + 1));
    //   const prevMonth = occupancyData?.find((d: any) => d.month === Number(moment().month()));

    //   curMonthOccupancy = ((beds.occupied / beds.total) * 100).toFixed(2) || 0;
    //   prevMonthOccupancy = ((prevMonth?.occupied / prevMonth?.total) * 100).toFixed(2) || 0;
    // }

  const prevMonthOccupancyData = await occupancyReportDB.getOccupancyReportForStaffByYearMonth({
    clientId,
    propertiesIds: propertiesIds,
    year: moment().subtract(1, "month").format("YYYY"),
    month: moment().subtract(1, "month").format("MM"),
  });

  if (prevMonthOccupancyData) {    
    prevMonthOccupancy = ((prevMonthOccupancyData?.occupied / prevMonthOccupancyData?.total) * 100).toFixed(2) || 0;
  }

    summary.curMonthOccupancy = Number(curMonthOccupancy) || 0;
    summary.prevMonthOccupancy = Number(prevMonthOccupancy) || 0;
  }

  const unreadNotifications = await notificationDB.getUnreadNotifications({
    userId: staffId,
    userType: CONSTANTS.USER_TYPE.STAFF,
  });

  const data = {
    stats,
    todaysCollection: todaysCollection || 0,
    todaysSecurityCollection: todaysSecurityCollection || 0,
    currentMonthExpenses,
    propertyNames,
    dueTenantCount: Number(dueTenantCount) || 0,
    pendingComplaintsCount,
    isPropertyExists: true,
    isPendingPropertyExists,
    isBankExists: banks ? true : false,
    beds,
    summary,
    pendingRequests: Number(pendingRequestsCount) || 0,
    unreadNotifications: Number(unreadNotifications) || 0,
    staffStatus: staff.status,
    isSuperAdmin: staff?.isSuperAdmin || 0,
    permissions: staff.permissions,
  };
  return data;
};

export const staffDashboard = async (staff: staffsTypes) => {
  const staffId = staff.id;

  let resolvedCount = await complaintDB.getComplaintCountForStaff({
    assignedTo: staffId,
    status: CONSTANTS.COMPLAINT_STATUS.RESOLVED,
  });
  let pendingCount = await complaintDB.getComplaintCountForStaff({
    assignedTo: staffId,
    status: CONSTANTS.COMPLAINT_STATUS.ASSIGNED,
  });

  const unreadNotifications = await notificationDB.getUnreadNotifications({
    userId: staffId,
    userType: CONSTANTS.USER_TYPE.STAFF,
  });
  let recentComplaints: any = null;
  if(Number(staff?.role) === CONSTANTS.STAFF_ROLES.MAINTENANCE_SUPERVISOR) {
    const staffLinkedProps = await propertyDB.getPropsByStaffId({
      staffId,
    });
    const propertiesIds = staffLinkedProps
          .map((prop: propertiesTypes) => prop.id)
          .join(",");
    let titleFilter: any = "Electronics/Appliance Issue,Maintenance and Infrastructure,Plumbing Issues";
    if (titleFilter && titleFilter !== "null" && titleFilter !== "undefined" && String(titleFilter).trim() !== "" && typeof titleFilter === 'string') {
      titleFilter = titleFilter.split(',').map(v => v.trim()).filter(Boolean);
    }
    recentComplaints = await complaintDB.getByClientIdAndFilters({
      clientId: staff?.clientId,
      title: titleFilter ? titleFilter : [],
      assignedTo: [],
      status: null,
      propId: propertiesIds,
      pageNum:1,
      limit:5,
    });
    let complaintCounts = await complaintDB.getCountByClientIdFilters({
      clientId: staff?.clientId,
      title: titleFilter ? titleFilter : [],
      assignedTo: [],
      propId: propertiesIds,
    });
    pendingCount = complaintCounts?.new;
    resolvedCount = complaintCounts?.closed;
  } else {
   recentComplaints =
    await complaintDB.getRecentAssignedComplaintsByStaffId({
      assignedTo: staffId,
      limit: 5,
    });
  }

  if (recentComplaints && recentComplaints.length > 0) {
    for (let complaint of recentComplaints) {
      if (complaint.status >= CONSTANTS.COMPLAINT_STATUS.ASSIGNED) {
        const { name } = await staffDB.getById({
          id: complaint.assignedTo,
        });
        complaint.staffName = name;
      }
    }
  }

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

  let propertyNames: string[] = [];

  if (staffLinkedProps) {
    propertyNames = staffLinkedProps.map((prop: propertiesTypes) => prop.name);
  }

  const data = {
    stats: {
      pending: Number(pendingCount) || 0,
      resolved: Number(resolvedCount) || 0,
    },
    recentComplaints: recentComplaints || [],
    unreadNotifications: Number(unreadNotifications) || 0,
    staffStatus: staff.status,
    propertyNames,
    permissions: staff.permissions,
  };

  return data;
};

// export const DashboardDetails = async (client: clientsTypes) => {
//   const clientId = client.id;
//   const properties = await propertyDB.getPropIdsByClientId({
//     clientId,
//     status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
//   });
//   let stats = [
//     {
//       totalIncome: 0,
//       totalDues: 0,
//       month: moment().format("M"),
//     },
//   ];
//   let dueTenantCount = 0;
//   let todaysCollection = 0;
//   if (properties) {
//     todaysCollection = await transactionDB.getTodaysCollection({
//       clientId,
//     });
//     const transactionStats = await transactionDB.getTotalIncomeStats({
//       clientId,
//       status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
//     });
//     const duesStats = await duesDB.getTotalDuesStats({
//       clientId,
//     });
//     stats = await createIncomeStats(stats, transactionStats, duesStats);
//     const tenantCount = await duesDB.getTenantCount({ clientId });
//     dueTenantCount = tenantCount.dueTenantCount;
//   }
//   const data = {
//     stats,
//     todaysCollection,
//     dueTenantCount: Number(dueTenantCount) || 0,
//   };
//   return data;
// };

export const getStaffAdminDashboardByYearMonth = async (
  staff: staffsTypes,
  year: any,
  month: any
) => {
  const staffId = staff.id;
  const clientId = staff.clientId;
  let dueTenantCount = 0;
  let todaysCollection = 0;
  const staffLinkedProps = await propertyDB.getPropsByStaffId({
    staffId,
  });

  let propertyNames: string[] = [];

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

    propertyNames = staffLinkedProps.map((prop: propertiesTypes) => prop.name);

    const transactionStats =
      await transactionDB.getTotalIncomeStatsForStaffByYearMonth({
        clientId,
        status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
        propertiesIds,
        year,
        month,
      });

    // todaysCollection =
    //   await transactionDB.getTodaysCollectionForStaffByYearMonth({
    //     clientId,
    //     propertiesIds,
    //     year,
    //     month,
    //   });
    const duesStats = await duesDB.getDuesByMonthForStaff({
      clientId,
      propertiesIds,
      year,
      month,
    });
    const tenantCount = await duesDB.getTenantCountForStaff({
      clientId,
      propertiesIds,
    });
    dueTenantCount = tenantCount.dueTenantCount;

    const expectedRent = await occupancyDB.getExpectedRentForStaff({
      clientId,
      propertiesIds,
      year,
      month,
    });

    const expectedExtraCharges = await occupancyDB.getExpectedExtraChargesForStaff({
      clientId,
      propertiesIds,
    });

    const expectedSecurity = await occupancyDB.getExpectedSecurityForStaff({
      clientId,
      propertiesIds,
    });

    let vacancyLoss = 0;
    let vacancyLossFullMonth = 0;
    let vacantBed = await roomDB.getVacancyLossForStaff({
      clientId,
      propertiesIds,
    });
    if (vacantBed) {
      for (let bed of vacantBed) {
        const lastTenant = await moveOutDB.getByBedId({
          bedId: bed.bedId,
        });
        let moveOut = bed.createdAt;
        if (lastTenant) {
          moveOut = lastTenant.moveOutDate;
        }
        if (moment(moveOut).startOf("day").isBefore(moment().startOf("month"))) {
          moveOut = moment().startOf("month");
        }
        const daysVacant = Math.abs(
          moment(moveOut).startOf("day").diff(moment().startOf("day"), "days")
        );
        const loss = Math.ceil((bed.rent) / Number(moment().daysInMonth())) * daysVacant;
        vacancyLoss += loss;
        vacancyLossFullMonth += bed.rent;
      }
    }

    let incomeData = await transactionDB.getTotalIncomeStatsByMonthStaff({
      clientId: clientId,
      propertiesIds: propertiesIds,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      year: moment().year(),
      month: moment().month() + 1,
    });

    let incomeDataWithoutRefunds = await transactionDB.getTotalIncomeStatsByMonthStaffWithoutRefunds({
      clientId: clientId,
      propertiesIds: propertiesIds,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      year: moment().year(),
      month: moment().month() + 1,
    });

    let income = incomeDataWithoutRefunds[0]?.totalIncome || 0;
    let incomeDataWitRefunds = incomeData[0]?.totalIncome || 0;

    let expense = await expenseDB.getTotalByDueDateClientIdForStaff({
      clientId,
      propertiesIds: propertiesIds,
      month: moment().format("YYYY-MM-DD"),
      sortBy: Number(clientId) === 113 ? "DD" : "PD",
    });

    if (expense === null) {
      expense = 0;
    }

    let netProfitLoss = Number(incomeDataWitRefunds) - Number(expense);

    const data = {
      transactionStats,
      duesStats,
      //todaysCollection,
      dueTenantCount: Number(dueTenantCount) || 0,
      expectedRent,
      expectedSecurity,
      expectedExtraCharges,
      vacancyLoss,
      vacancyLossFullMonth,
      income,
      expense,
      netProfitLoss,
      permissions: staff.permissions,
    };

    return data;
  }
};

export const clientIncomeDetails = async (
  client: clientsTypes,
  year: any,
  month: any
) => {
  const clientId = client.id;
  const properties = await propertyDB.getPropIdsByClientId({
    clientId,
    status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
  });
  let dueTenantCount = 0;
  let todaysCollection = 0;
  let transactionStats = [];
  let duesStats = 0;
  let vacancyLoss = 0;
  let vacancyLossFullMonth = 0;
  let income = 0;
  let expense = 0;
  let netProfitLoss = 0;
  if (properties) {
    // todaysCollection = await transactionDB.getTodaysCollection({
    //   clientId,
    // });
    transactionStats = await transactionDB.getTotalIncomeStatsByMonth({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      year,
      month,
    });
    duesStats = await duesDB.getDuesByMonth({
      clientId,
      year,
      month,
    });
    const tenantCount = await duesDB.getTenantCountYearMonth({
      clientId,
      month,
      year,
    });
    dueTenantCount = tenantCount.dueTenantCount;

    const vacantBeds = await roomDB.getVacancyLossForClient({
      clientId,
    });
    // if (vacantBeds) {
    //   for (let bed of vacantBeds) {
    //     const lastTenant = await moveOutDB.getByBedId({
    //       bedId: bed.bedId,
    //     });
    //     let moveOut = moment(bed.createdAt);
    //     if (lastTenant) {
    //       moveOut = moment(lastTenant.moveOutDate);
    //     }
    //     if (moment(moveOut).startOf("day").isBefore(moment().startOf("month"))) {
    //       moveOut = moment().startOf("month");
    //     }
    //     const daysVacant = Math.abs(
    //       moment(moveOut).startOf("day").diff(moment().startOf("day"), "days")
    //     );
    //     const loss = Math.ceil((bed.rent)/Number(moment().daysInMonth())) * daysVacant;
    //     vacancyLoss += loss;
    //   }
    // }

    if (vacantBeds && vacantBeds.length > 0) {
      const bedIds = vacantBeds.map((b: any) => b.bedId);
      const lastMoveOuts = await moveOutDB.getLastMoveOutsByBedIds({
        bedIds,
        clientId,
      });

      const moveOutMap = new Map<number, string>();
      lastMoveOuts.forEach((entry: any) => {
        moveOutMap.set(entry.bedId, entry.moveOutDate);
      });

      const today = moment().startOf("day");
      const monthStart = moment().startOf("month");
      const daysInMonth = moment().daysInMonth();

      for (let bed of vacantBeds) {
        let moveOut = bed.createdAt;

        if (moveOutMap.has(bed.bedId)) {
          moveOut = moveOutMap.get(bed.bedId)!;
        }

        if (moveOut === null || moveOut === undefined) {
          moveOut = bed.createdAt;
        }

        let moveOutMoment = moment(moveOut).startOf("day");

        if (moveOutMoment.isBefore(monthStart)) {
          moveOutMoment = monthStart;
        }

        const daysVacant = today.diff(moveOutMoment, "days");
        const perDayRent = Math.ceil(bed.rent / daysInMonth);
        vacancyLoss += perDayRent * daysVacant;
        vacancyLossFullMonth += bed.rent;
      }
    }


    let incomeData = await transactionDB.getTotalIncomeStatsByMonth({
      clientId: clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      year: moment().year(),
      month: moment().month() + 1,
    });

    let incomeDataWithoutRefunds = await transactionDB.getTotalIncomeStatsByMonthWithoutRefunds({
      clientId: clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      year: moment().year(),
      month: moment().month() + 1,
    });

    income = incomeDataWithoutRefunds[0]?.totalIncome || 0;

    let incomeWithRefunds = incomeData[0]?.totalIncome || 0; //Now based on flag 2026-01-14

    expense = await expenseDB.getTotalByDueDateClientId({
      clientId,
      month: moment().format("YYYY-MM-DD"),
      sortBy: Number(clientId) === 113 ? "DD" : "PD",
    });

    if (expense === null) {
      expense = 0;
    }

    netProfitLoss = Number(incomeWithRefunds) - Number(expense);
  }
  const data = {
    transactionStats,
    duesStats,
    //todaysCollection,
    dueTenantCount: Number(dueTenantCount) || 0,
    vacancyLoss: Number(vacancyLoss) || 0,
    vacancyLossFullMonth: Number(vacancyLossFullMonth) || 0,
    income,
    expense,
    netProfitLoss,
  };
  return data;
};

// export const clientPendingRentDetails = async (client: clientsTypes) => {
//   const clientId = client.id;
//   const properties = await propertyDB.getPropIdsByClientId({
//     clientId,
//     status: CONSTANTS.PROPERTY_STATUS.ACTIVE,
//   });

//   let stats = [
//     {
//       totalIncome: 0,
//       totalDues: 0,
//       dueTenantCount: 0,
//       month: moment().format("M"),
//       year: moment().format("YYYY"),
//     },
//   ];

//   let dueTenantCount = 0;

//   if (properties) {

//     const transactionStats = await transactionDB.getTotalIncomeStats({
//       clientId,
//       status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
//     });

//     const duesStats = await duesDB.getTotalDuesStats({
//       clientId,
//     });

//     // const isOtherThanPending = properties.find(
//     //   (prop: propertiesTypes) =>
//     //     prop.status !== CONSTANTS.PROPERTY_STATUS.PENDING
//     // );

//     stats = await createIncomeStats(stats, transactionStats, duesStats);

//     for (let stat of stats) {

//       const tenantCount = await duesDB.getTenantCountYearMonth({ clientId, month: stat.month, year: stat.year });

//       dueTenantCount = tenantCount.dueTenantCount;
//       stat.dueTenantCount = dueTenantCount;
//       //const counts = await bedDB.getCountsByPropId({ propId: prop.id });
//       // beds.total += Number(counts.total) || 0;
//       // beds.vacant += Number(counts.vacant) || 0;
//       // beds.occupied += Number(counts.occupied) || 0;
//     }

//   }

//   const data = {
//     stats,
//     dueTenantCount: Number(dueTenantCount) || 0,
//     clientStatus: client.status,
//   };

//   return data;
// };

export const salesHeadWebDashboardData = async (
  staff: staffsTypes,
  propertyId: number | null,
  locationId: number | null
) => {

  const leadSummary = await leadDB.getSummaryByClientIdForSalesHead({
    clientId: staff?.clientId,
    // staffId: staff?.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null,
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null,
  });

  const bookings = await bookingsDB.getCountByClientIdForSalesHead({
    clientId: staff?.clientId,
    staffId: staff?.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null,
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null,
  });

  // const vacantBeds = await bedDB.vacantBedsForSalesHead({ 
  //   clientId: staff?.clientId, 
  //   staffId: staff?.id, 
  //   propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
  //   locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  // });

  const vacantBeds = await bedDB.vacantBeds({ 
    clientId: staff?.clientId,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });

  const bedStats = await bedDB.getStatsForSalesHead({ 
    clientId: staff?.clientId,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });

  // log.info(`Lead Summary [${JSON.stringify(leadSummary)}]`);
  
  const summary = {
    totalLeads: Number(leadSummary?.totalLeads) || 0,
    todayLeads: Number(leadSummary?.todayLeads) || 0,
    newLeads: Number(leadSummary?.newLeads) || 0,
    activeLeads: Number(leadSummary?.activeLeads) || 0,
    todayFollowup: Number(leadSummary?.todayFollowUp) || 0,
    todayVisits: Number(leadSummary?.todayVisits) || 0,
    totalBookings: Number(bookings?.totalBookings) || 0,
    todayBookings: Number(bookings?.todayBookings) || 0,
    vacantBeds: Number(vacantBeds) || 0,
    occupiedBeds: Number(bedStats?.occupied) || 0,
  };

  // log.info(`Summary [${JSON.stringify(summary)}]`);

  const statsByStaff = await leadDB.getStaffWiseStatsForSalesHead({
    clientId: staff?.clientId,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });


  let staffSummary = [];

  if (statsByStaff) {
    for (let record of statsByStaff) {
      staffSummary.push({
        staffId: record.staffId,
        staffName: record.staffName,
        staffMobile: record.staffMobile,
        totalLeads: Number(record.totalLeads) || 0,
        activeLeads: Number(record.activeLeads) || 0,
        pendingFollowUps: Number(record.pendingFollowUps) || 0,
        pendingVisits: Number(record.pendingVisits) || 0,
        convertedLeads: Number(record.convertedLeads) || 0,
        totalBookings: Number(record.totalBookings) || 0,
      });
    }
  }

  const statsByLeadSource = await leadDB.getSourceWiseStatsForSalesHead({
    clientId: staff?.clientId,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });

  let leadSourceSummary = [];

  if (statsByLeadSource) {
    for (let record of statsByLeadSource) {
      leadSourceSummary.push({
        source: record.source,
        totalLeads: Number(record.totalLeads) || 0,
        activeLeads: Number(record.activeLeads) || 0,
        pendingFollowUps: Number(record.pendingFollowUps) || 0,
        pendingVisits: Number(record.pendingVisits) || 0,
        convertedLeads: Number(record.convertedLeads) || 0,
        lostLeads: Number(record.lostLeads) || 0,
      });
    }
  }

  // log.info(`Lead Summary [${JSON.stringify(leadSummary)}], Bookings [${JSON.stringify(bookings)}], Vacant Beds [${JSON.stringify(vacantBeds)}], Summary [${JSON.stringify(summary)}], Stats By Staff [${JSON.stringify(statsByStaff)}], Staff Summary [${JSON.stringify(staffSummary)}], Stats By Lead Source [${JSON.stringify(statsByLeadSource)}], Lead Source Summary [${JSON.stringify(leadSourceSummary)}]`);

  return {summary, staffSummary, leadSourceSummary};
}

export const salesHeadWebDashboardDataForClient = async (
  client: clientsTypes,
  propertyId: number | null,
  locationId: number | null
) => {

  const leadSummary = await leadDB.getSummaryByClientIdForSalesHead({
    clientId: client.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null,
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null,
  });

  const bookings = await bookingsDB.getCountByClientId({
    clientId: client.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null,
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null,
  });

  const vacantBeds = await bedDB.vacantBeds({ 
    clientId: client.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });

  // log.info(`Lead Summary [${JSON.stringify(leadSummary)}]`);
  const beds = await bedDB.getCountsByClientId({ clientId: client.id });
  let bedCount = beds?.total || 0;
  let occupiedBeds = beds?.occupied || 0;
  const summary = {
    totalLeads: Number(leadSummary?.totalLeads) || 0,
    todayLeads: Number(leadSummary?.todayLeads) || 0,
    newLeads: Number(leadSummary?.newLeads) || 0,
    activeLeads: Number(leadSummary?.activeLeads) || 0,
    todayFollowup: Number(leadSummary?.todayFollowUp) || 0,
    todayVisits: Number(leadSummary?.todayVisits) || 0,
    totalBookings: Number(bookings?.totalBookings) || 0,
    todayBookings: Number(bookings?.todayBookings) || 0,
    vacantBeds: Number(vacantBeds) || 0,
    occupiedBeds: Number(occupiedBeds) || 0,
  };

  // log.info(`Summary [${JSON.stringify(summary)}]`);

  const statsByStaff = await leadDB.getStaffWiseStatsForSalesHead({
    clientId: client.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });


  let staffSummary = [];

  if (statsByStaff) {
    for (let record of statsByStaff) {
      staffSummary.push({
        staffId: record.staffId,
        staffName: record.staffName,
        staffMobile: record.staffMobile,
        totalLeads: Number(record.totalLeads) || 0,
        activeLeads: Number(record.activeLeads) || 0,
        pendingFollowUps: Number(record.pendingFollowUps) || 0,
        pendingVisits: Number(record.pendingVisits) || 0,
        convertedLeads: Number(record.convertedLeads) || 0,
        totalBookings: Number(record.totalBookings) || 0,
      });
    }
  }

  const statsByLeadSource = await leadDB.getSourceWiseStatsForSalesHead({
    clientId: client.id,
    propertyId: Number(propertyId) && Number(propertyId) > 0 ? Number(propertyId) : null, 
    locationId: Number(locationId) && Number(locationId) > 0 ? Number(locationId) : null, 
  });

  let leadSourceSummary = [];

  if (statsByLeadSource) {
    for (let record of statsByLeadSource) {
      leadSourceSummary.push({
        source: record.source,
        totalLeads: Number(record.totalLeads) || 0,
        activeLeads: Number(record.activeLeads) || 0,
        pendingFollowUps: Number(record.pendingFollowUps) || 0,
        pendingVisits: Number(record.pendingVisits) || 0,
        convertedLeads: Number(record.convertedLeads) || 0,
        lostLeads: Number(record.lostLeads) || 0,
      });
    }
  }

  // log.info(`Lead Summary [${JSON.stringify(leadSummary)}], Bookings [${JSON.stringify(bookings)}], Vacant Beds [${JSON.stringify(vacantBeds)}], Summary [${JSON.stringify(summary)}], Stats By Staff [${JSON.stringify(statsByStaff)}], Staff Summary [${JSON.stringify(staffSummary)}], Stats By Lead Source [${JSON.stringify(statsByLeadSource)}], Lead Source Summary [${JSON.stringify(leadSourceSummary)}]`);

  return {summary, staffSummary, leadSourceSummary};
};
