import moment, { max, min } from "moment";
import CONSTANTS from "../../config/constants";
import clientsTypes from "../../schemas/client.schema";
import transactionDB from "../../models/transaction.model";
import expenseDB from "../../models/expense.model";
import complaintDB from "../../models/complaint.model";
import bedDB from "../../models/beds.model";
import years, { getCurrentMonthDates, getLast31Days } from "./getYearsArray";
import occupancyDB from "../../models/occupancy.model";
import occupancyReportDB from "../../models/occupancyReport.model";
import log from "../../config/log";
import propertiesTypes from "../../schemas/property.schema";
import staffsTypes from "../../schemas/staff.schema";
import duesDB from "../../models/dues.model";
import propertyDB from "../../models/property.model";
import clientDB from "../../models/client.model";

export const clientCollectionGraph = async (
  client: clientsTypes,
  term: any
) => {
  const clientId = client.id;
  let stats = [];
  let graphStats;
  let allYears = [];

  let curYear = moment().year();
  let FYStartDate = moment().date(1).month(3).format("YYYY-MM-DD");
  let FYEndDate = moment().year(curYear+1).date(31).month(2).format("YYYY-MM-DD");
  const curFYCollection = await transactionDB.getTotalByDateRange({
    clientId,
    startDate: FYStartDate,
    endDate: FYEndDate,
  });

  const monthRemainingInFY = moment(FYEndDate).diff(moment(), "month");
  const potentialRentPerMonth = await occupancyDB.potentialRentPerMonth({clientId});
  const { totalDues } = await duesDB.getTotalDuesByClientId({clientId});
  const duesToBeAdded = await occupancyDB.getRentToBeAddedForClient({clientId});
  const potentialFYIncome = Number(curFYCollection) + Number(duesToBeAdded) + Number(totalDues) + (Number(potentialRentPerMonth) * Number(monthRemainingInFY));
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();

  if (2 == term) {

    allYears = await years(joiningYear, 5);
    const transData = await transactionDB.getYearRentTransaction({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueYear = null;
    let maxValueYear = null;
    stats = allYears.reduce((acc: any, cur: any) => {
      const yearData = transData.find((d: any) => d.year === cur);
      const stat = {
        amount: (yearData && Number(yearData.amount)) || 0,
        year: cur,
      };
      totalCollection += stat.amount;
      if (stat.amount < minvalue) {
        minvalue = stat.amount;
        minValueYear = stat.year;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueYear = stat.year;
      }
      acc.push(stat);
      return acc;
    }, []);

    averageCollection = totalCollection / stats.length;
    graphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        year: minValueYear,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        year: maxValueYear,
      },
      {
        label: "Projected FY Collection",
        value: potentialFYIncome || 0,
      },
    ];
  } else if (1 == term) {
    //FY monthly

    const getMonthIndex = (year: number, month: number) =>
      year * 12 + month;

    let year = Number(moment().format("YYYY"));
      
    if (moment().month() < 3) {
      year = year - 1;      
    }
    const FYStartDate = year
    const FYEndDate = year + 1;
    const currentMonth = moment().month() + 1;
    const currentYear = moment().year();
    const joiningDateObj = moment(clientCreatedOn);
    const joiningMonth = joiningDateObj.month() + 1;
    const joiningYear = joiningDateObj.year();

    let fy = [
      { month: 4, year: FYStartDate },
      { month: 5, year: FYStartDate },
      { month: 6, year: FYStartDate },
      { month: 7, year: FYStartDate },
      { month: 8, year: FYStartDate },
      { month: 9, year: FYStartDate },
      { month: 10, year: FYStartDate },
      { month: 11, year: FYStartDate },
      { month: 12, year: FYStartDate },
      { month: 1, year: FYEndDate },
      { month: 2, year: FYEndDate },
      { month: 3, year: FYEndDate },
    ];
    // fy = fy.filter((item) => {
    //   return (
    //     item.year < currentYear ||
    //     (item.year === currentYear && item.month <= currentMonth)
    //   );
    // });

    fy = fy.filter((item) => {
      const itemValue = item.year * 12 + item.month;
      const joiningValue = joiningYear * 12 + joiningMonth;
      const currentValue = currentYear * 12 + currentMonth;

      return itemValue >= joiningValue && itemValue <= currentValue;
    });

    const transData = await transactionDB.getMonthlyRentTransactionByDateRangeWithoutSecuirty({
      clientId,
      startDate: moment(`${year}-04-01`).format("YYYY-MM-DD"),
      endDate: moment(`${year + 1}-03-31`).format("YYYY-MM-DD"),
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });

    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let minValueYear = null;
    let maxValueMonth = null;
    let maxValueYear = null;
    stats = fy.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur.month && d.year === cur.year);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalCollection += stat.amount;

      const statIndex = getMonthIndex(cur.year, cur.month);
      const currentIndex = new Date().getFullYear() * 12 + new Date().getMonth() + 1;

      if (
        stat.amount < minvalue &&
        statIndex <= currentIndex
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
        minValueYear = stat.year;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
        maxValueYear = stat.year;
      }
      acc.push(stat);
      return acc;
    }, []);

    const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);
    let completedMonths = stats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageCollection = totalCollection / completedMonths;
    graphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
      {
        label: "Projected FY Collection",
        value: potentialFYIncome || 0,
      },
    ];
  } else {
    const transData = await transactionDB.getMonthlyRentTransaction({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let maxValueMonth = null;
    stats = allMonths.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur,
      };
      totalCollection += stat.amount;
      if (
        stat.amount < minvalue &&
        Number(stat.month) <= new Date().getMonth() + 1
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
      }
      acc.push(stat);
      return acc;
    }, []);
    averageCollection = totalCollection / Number(new Date().getMonth() + 1);
    graphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
      {
        label: "Projected FY Collection",
        value: potentialFYIncome || 0,
      },
    ];
  }

  let data = {
    graphData: stats,
    stats: graphStats,
  };
  return data;
};

export const clientOccupancyGraph = async (client: clientsTypes) => {
  const clientId = client.id;
  let stats = [];
  const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
  let occupancyData = await occupancyReportDB.getOccupancyReport({ clientId });
  let currentMonthData = await bedDB.getBedOccupancyCount({ clientId });
  stats = allMonths.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur);
    if (cur != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const clientOccupancyGraphFY = async (
  client: clientsTypes,
) => {
  const clientId = client.id;
  let year = Number(moment().format("YYYY"));
    
  if (moment().month() < 3) {
    year = year - 1;      
  }
  const FYStartDate = year
  const FYEndDate = year + 1;

  let stats = [];
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  const currentMonth = moment().month() + 1;
  const currentYear = moment().year();

  const joiningDateObj = moment(clientCreatedOn);
  const joiningMonth = joiningDateObj.month() + 1;
  joiningYear = joiningDateObj.year();

  let fy = [
    { month: 4, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 5, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 6, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 7, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 8, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 9, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 10, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 11, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 12, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 1, year: FYEndDate, occupied: 0, vacant: 0 },
    { month: 2, year: FYEndDate, occupied: 0, vacant: 0 },
    { month: 3, year: FYEndDate, occupied: 0, vacant: 0 },
  ];
  const joiningValue = joiningYear * 12 + joiningMonth;
  const currentValue = currentYear * 12 + currentMonth;

  fy = fy.filter((item) => {
    const itemValue = item.year * 12 + item.month;

    return itemValue >= joiningValue && itemValue <= currentValue;
  });
  
  let occupancyData = await occupancyReportDB.getOccupancyReportFY({ 
    clientId,
    startYear: FYStartDate,
    endYear: FYEndDate,
  });
  let currentMonthData = await bedDB.getBedOccupancyCount({ clientId });
  stats = fy.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur.month);
    if (cur.month != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur.month,
        year: cur.year,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const clientOccupancyGraphFYForWeb = async (
  client: clientsTypes,
  propIds: any,
) => {
  const clientId = client.id;
  let year = Number(moment().format("YYYY"));
    
  if (moment().month() < 3) {
    year = year - 1;      
  }
  const FYStartDate = year
  const FYEndDate = year + 1;

  let stats = [];
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  const currentMonth = moment().month() + 1;
  const currentYear = moment().year();

  const joiningDateObj = moment(clientCreatedOn);
  const joiningMonth = joiningDateObj.month() + 1;
  joiningYear = joiningDateObj.year();

  let fy = [
    { month: 4, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 5, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 6, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 7, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 8, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 9, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 10, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 11, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 12, year: FYStartDate, occupied: 0, vacant: 0 },
    { month: 1, year: FYEndDate, occupied: 0, vacant: 0 },
    { month: 2, year: FYEndDate, occupied: 0, vacant: 0 },
    { month: 3, year: FYEndDate, occupied: 0, vacant: 0 },
  ];

  const joiningValue = joiningYear * 12 + joiningMonth;
  const currentValue = currentYear * 12 + currentMonth;

  fy = fy.filter((item) => {
    const itemValue = item.year * 12 + item.month;

    return itemValue >= joiningValue && itemValue <= currentValue;
  });

  let occupancyData = await occupancyReportDB.getOccupancyReportFYForWeb({ 
    clientId,
    propIds: propIds,
    startYear: FYStartDate,
    endYear: FYEndDate,
  });
  let currentMonthData = await bedDB.getBedOccupancyCountForWeb({ clientId, propIds: propIds, });
  stats = fy.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur.month);
    if (cur.month != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur.month,
        year: cur.year,
      };
    } else {
      stat = currentMonthData;
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const staffOccupancyGraph = async (staff: staffsTypes) => {
  const clientId = staff.clientId;
  let stats = [];
  const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
  let occupancyData = await occupancyReportDB.getOccupancyReportForStaffForWeb({ clientId, staffId: staff.id });
  let currentMonthData = await bedDB.getBedOccupancyCountForStaff({ clientId, staffId: staff.id });
  stats = allMonths.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur);
    if (cur != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const staffOccupancyGraphFY = async (
  staff: staffsTypes,
) => {
  const clientId = staff.clientId;
  let year = Number(moment().format("YYYY"));
  
  if (moment().month() < 3) {
    year = year - 1;      
  }
  const FYStartDate = year
  const FYEndDate = year + 1;
  let stats = [];
  let client = await clientDB.getById({id: clientId});
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  const currentMonth = moment().month() + 1;
  const currentYear = moment().year();

  const joiningDateObj = moment(clientCreatedOn);
  const joiningMonth = joiningDateObj.month() + 1;
  joiningYear = joiningDateObj.year();

  let fy = [
      { month: 1, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 2, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 3, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 4, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 5, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 6, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 7, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 8, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 9, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 10, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 11, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 12, year: FYStartDate, occupied: 0, vacant: 0 },
  ];
  const joiningValue = joiningYear * 12 + joiningMonth;
  const currentValue = currentYear * 12 + currentMonth;

  fy = fy.filter((item) => {
    const itemValue = item.year * 12 + item.month;

    return itemValue >= joiningValue && itemValue <= currentValue;
  });
  const staffLinkedProps = await propertyDB.getPropsByStaffId({
    staffId: staff.id,
  });
  let propertiesIds = [];
  if (staffLinkedProps) {
    propertiesIds = staffLinkedProps
      .map((prop: propertiesTypes) => prop.id)
      .join(",");
  }
  let occupancyData = await occupancyReportDB.getOccupancyReportFYForStaff({ 
    clientId,
    propertiesIds,
    startYear: FYStartDate,
    endYear: FYEndDate,
  });
  let currentMonthData = await bedDB.getBedOccupancyCountForStaff({ clientId, staffId: staff.id});
  stats = fy.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur.month);
    if (cur.month != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur.month,
        year: cur.year,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};
export const staffOccupancyGraphFYWeb = async (
  staff: staffsTypes,
  propIds: any,
) => {
  const clientId = staff.clientId;
  let year = Number(moment().format("YYYY"));
  
  if (moment().month() < 3) {
    year = year - 1;      
  }
  const FYStartDate = year
  const FYEndDate = year + 1;
  let stats = [];
  let client = await clientDB.getById({id: clientId});
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  const currentMonth = moment().month() + 1;
  const currentYear = moment().year();

  const joiningDateObj = moment(clientCreatedOn);
  const joiningMonth = joiningDateObj.month() + 1;
  joiningYear = joiningDateObj.year();
  let fy = [
      { month: 1, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 2, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 3, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 4, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 5, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 6, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 7, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 8, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 9, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 10, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 11, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 12, year: FYStartDate, occupied: 0, vacant: 0 },
  ];

  const joiningValue = joiningYear * 12 + joiningMonth;
  const currentValue = currentYear * 12 + currentMonth;

  fy = fy.filter((item) => {
    const itemValue = item.year * 12 + item.month;

    return itemValue >= joiningValue && itemValue <= currentValue;
  });
  
  const staffLinkedProps = await propertyDB.getPropsByStaffId({
    staffId: staff.id,
  });
  let propertiesIds = [];
  if (staffLinkedProps) {
    propertiesIds = staffLinkedProps
      .map((prop: propertiesTypes) => prop.id)
      .join(",");
  }
  let occupancyData = await occupancyReportDB.getOccupancyReportFYForWebStaff({ 
    clientId,
    propIds: propIds,
    propertiesIds,
    startYear: FYStartDate,
    endYear: FYEndDate,
  });
  let currentMonthData = await bedDB.getBedOccupancyCountForWebStaff({ clientId, staffId: staff.id, propIds: propIds,});
  stats = fy.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur.month);
    if (cur.month != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur.month,
        year: cur.year,
      };
    } else {
      stat = currentMonthData;
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const propertyOccupancyGraph = async (property: propertiesTypes) => {
  // const clientId = client.id;
  const propId = property.id;
  let stats = [];
  const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
  let occupancyData = await occupancyReportDB.getOccupancyReportForProp({
    propId,
  });
  let currentMonthData = await bedDB.getBedOccupancyCountForProp({ propId });
  stats = allMonths.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur);
    if (cur != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const propertyOccupancyGraphFY = async (
  property: propertiesTypes,
) => {
  const propId = property.id;
  let year = Number(moment().format("YYYY"));
  
  if (moment().month() < 3) {
    year = year - 1;      
  }
  const FYStartDate = year
  const FYEndDate = year + 1;
  let stats = [];
  let fy = [
      { month: 1, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 2, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 3, year: FYEndDate, occupied: 0, vacant: 0 },
      { month: 4, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 5, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 6, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 7, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 8, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 9, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 10, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 11, year: FYStartDate, occupied: 0, vacant: 0 },
      { month: 12, year: FYStartDate, occupied: 0, vacant: 0 },
  ];
  let occupancyData = await occupancyReportDB.getOccupancyReportFYForProp({ 
    propId,
    startYear: FYStartDate,
    endYear: FYEndDate,
  });
  let currentMonthData = await bedDB.getBedOccupancyCountForProp({ propId });
  stats = fy.reduce((acc: any, cur: any) => {
    let stat;
    const occupiedData = occupancyData.find((d: any) => d.month === cur.month);
    if (cur.month != moment().format("MM")) {
      stat = {
        occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
        vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
        month: cur.month,
        year: cur.year,
      };
    } else {
      stat = currentMonthData;
      // stat = {
      //   occupied: (occupiedData && Number(occupiedData.occupied)) || 0,
      //   vacant: (occupiedData && Number(occupiedData.vacant)) || 0,
      //   month: cur,
      // };
    }
    acc.push(stat);
    return acc;
  }, []);

  let data = {
    graphData: stats,
  };
  return data;
};

export const clientExpenseGraph = async (client: clientsTypes, term: any) => {
  const clientId = client.id;
  let stats = [];
  let graphStats;
  let collectionGraphStats;
  let allYears = [];
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  if (2 == term) {
    allYears = await years(joiningYear, 5);
    let expenses = [
      { year: allYears[0], income: 0, expense: 0 },
      { year: allYears[1], income: 0, expense: 0 },
      { year: allYears[2], income: 0, expense: 0 },
      { year: allYears[3], income: 0, expense: 0 },
      { year: allYears[4], income: 0, expense: 0 },
      { year: allYears[5], income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getYearlyRentTransactionWithoutSecurity({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let totalExpense = 0;
    let totalIncome = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseYear = null;
    let minExpenseYear = null;
    let maxProfit = Number.NEGATIVE_INFINITY;
    let minProfit = Number.POSITIVE_INFINITY;
    let maxProfitYear = null;
    let minProfitYear = null;
    let totalProfit = 0;
    let averageProfit = 0;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "expense"
      );
      const incomeData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "income"
      );
      const stat = {
        income: (incomeData && Number(incomeData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        year: cur.year,
      };
      totalIncome += stat.income;
      totalExpense += stat.expense;
      totalProfit += stat.income - stat.expense;
      let profit = stat.income - stat.expense;
      if (stat.expense < minExpense) {
        minExpense = stat.expense;
        minExpenseYear = stat.year;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseYear = stat.year;
      }

      if (profit < minProfit) {
        minProfit = profit;
        minProfitYear = stat.year;
      }
      if (profit > maxProfit) {
        maxProfit = profit;
        maxProfitYear = stat.year;
      }

      acc.push(stat);
      return acc;
    }, []);
    let avgExpense = totalExpense / expenses.length;
    averageProfit = totalProfit / Number(new Date().getMonth() + 1);
    graphStats = [
      { label: "Total Profit", value: totalProfit.toFixed(2) },
      { label: "Average Profit", value: averageProfit.toFixed(2) },
      {
        label: "Min. Profit",
        value: minProfit.toFixed(2),
        year: minProfitYear,
      },
      { label: "Max. Profit", value: maxProfit, year: maxProfitYear },

      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: avgExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        year: minExpenseYear,
      },
      {
        label: "Max. Expense",
        value: maxExpense.toFixed(2),
        year: maxExpenseYear,
      },
    ];
    const transData = await transactionDB.getYearRentTransaction({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueYear = null;
    let maxValueYear = null;
    let collectionStats = allYears.reduce((acc: any, cur: any) => {
      const yearData = transData.find((d: any) => d.year === cur);
      const stat = {
        amount: (yearData && Number(yearData.amount)) || 0,
        year: cur,
      };
      totalCollection += stat.amount;
      if (stat.amount < minvalue) {
        minvalue = stat.amount;
        minValueYear = stat.year;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueYear = stat.year;
      }
      acc.push(stat);
      return acc;
    }, []);

    averageCollection = totalCollection / stats.length;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        year: minValueYear,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        year: maxValueYear,
      },
    ];
  // } else if (3 === Number(term)) {
  } else {
    const getMonthIndex = (year: number, month: number) =>
      year * 12 + month;

    const currentYear = new Date().getFullYear();
    const currentMonth = new Date().getMonth() + 1;

    let year = Number(moment().format("YYYY"));
    
    if (moment().month() < 3) {
      year = year - 1;      
    }
    
    const FYStartDate = moment(`${year}-04-01`).format("YYYY-MM-DD");
    const FYEndDate = moment(`${year + 1}-03-31`).format("YYYY-MM-DD");

    const curYear = year
    const nextYear = year + 1;

    let expenses = [
      { month: 4, year: curYear, income: 0, expense: 0 },
      { month: 5, year: curYear, income: 0, expense: 0 },
      { month: 6, year: curYear, income: 0, expense: 0 },
      { month: 7, year: curYear, income: 0, expense: 0 },
      { month: 8, year: curYear, income: 0, expense: 0 },
      { month: 9, year: curYear, income: 0, expense: 0 },
      { month: 10, year: curYear, income: 0, expense: 0 },
      { month: 11, year: curYear, income: 0, expense: 0 },
      { month: 12, year: curYear, income: 0, expense: 0 },
      { month: 1, year: nextYear, income: 0, expense: 0 },
      { month: 2, year: nextYear, income: 0, expense: 0 },
      { month: 3, year: nextYear, income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getMonthlyIncomeExpenseByDateRangeWithoutSecurity({
      clientId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let totalExpense = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseMonth = null;
    let minExpenseMonth = null;
    let maxProfit = Number.NEGATIVE_INFINITY;
    let minProfit = Number.POSITIVE_INFINITY;
    let maxProfitMonth = null;
    let minProfitMonth = null;
    let totalProfit = 0;
    let averageProfit = 0;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "expense"
      );
      const incomedData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "income"
      );
      //if (11 == cur.month)
      //log.info(
      //  `Amount [${incomedData.amount}], Month [${incomedData.month}]`
      //);

      const stat = {
        income: (incomedData && Number(incomedData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalExpense += stat.expense;
      totalProfit += stat.income - stat.expense;
      let profit = stat.income - stat.expense;
      const statIndex = cur.month * 12 + cur.month;
      const currentIndex = new Date().getFullYear() * 12 + new Date().getMonth() + 1;
      if (
        stat.expense < minExpense &&
        statIndex <= currentIndex
      ) {
        minExpense = stat.expense;
        minExpenseMonth = stat.month;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseMonth = stat.month;
      }
      
      if (
        profit < minProfit &&
        statIndex <= currentIndex
      ) {
        minProfit = profit;
        minProfitMonth = stat.month;
      }
      if (profit > maxProfit) {
        maxProfit = profit;
        maxProfitMonth = stat.month;
      }

      acc.push(stat);
      return acc;
    }, []);

    const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);

    let completedMonths = stats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageExpense = totalExpense / completedMonths;
    averageProfit = totalProfit / completedMonths;
    graphStats = [
      { label: "Total Profit", value: totalProfit.toFixed(2) },
      { label: "Average Profit", value: averageProfit.toFixed(2) },
      {
        label: "Min. Profit",
        value: minProfit.toFixed(2),
        month: minProfitMonth,
      },
      { label: "Max. Profit", value: maxProfit, month: maxProfitMonth },
      
      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: averageExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        month: minExpenseMonth,
      },
      { label: "Max. Expense", value: maxExpense, month: maxExpenseMonth },
    ];
    const transData = await transactionDB.getMonthlyRentTransactionByDateRange({
      clientId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let maxValueMonth = null;
    let collectionStats = expenses.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur.month && d.year === cur.year);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalCollection += stat.amount;
      const statIndex = getMonthIndex(cur.year, cur.month);
      const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);
      if (
        stat.amount < minvalue &&
        statIndex <= currentIndex
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
      }
      acc.push(stat);
      return acc;
    }, []);

    completedMonths = collectionStats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageCollection = totalCollection / completedMonths;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
    ];
  } 
  // else {
  //   const year = moment().format("YYYY");
  //   let expenses = [
  //     { month: 1, income: 0, expense: 0 },
  //     { month: 2, income: 0, expense: 0 },
  //     { month: 3, income: 0, expense: 0 },
  //     { month: 4, income: 0, expense: 0 },
  //     { month: 5, income: 0, expense: 0 },
  //     { month: 6, income: 0, expense: 0 },
  //     { month: 7, income: 0, expense: 0 },
  //     { month: 8, income: 0, expense: 0 },
  //     { month: 9, income: 0, expense: 0 },
  //     { month: 10, income: 0, expense: 0 },
  //     { month: 11, income: 0, expense: 0 },
  //     { month: 12, income: 0, expense: 0 },
  //   ];
  //   let newExpense = await expenseDB.getMonthlyIncomeExpense({
  //     clientId,
  //     year,
  //     status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
  //   });
  //   let totalExpense = 0;
  //   let averageExpense = 0;
  //   let maxExpense = Number.NEGATIVE_INFINITY;
  //   let minExpense = Number.POSITIVE_INFINITY;
  //   let maxExpenseMonth = null;
  //   let minExpenseMonth = null;
  //   let maxProfit = Number.NEGATIVE_INFINITY;
  //   let minProfit = Number.POSITIVE_INFINITY;
  //   let maxProfitMonth = null;
  //   let minProfitMonth = null;
  //   let totalProfit = 0;
  //   let averageProfit = 0;
  //   stats = expenses.reduce((acc: any, cur: any) => {
  //     const expenseData = newExpense.find(
  //       (d: any) => d.month === cur.month && d.type === "expense"
  //     );
  //     const incomedData = newExpense.find(
  //       (d: any) => d.month === cur.month && d.type === "income"
  //     );
  //     //if (11 == cur.month)
  //     //log.info(
  //     //  `Amount [${incomedData.amount}], Month [${incomedData.month}]`
  //     //);

  //     const stat = {
  //       income: (incomedData && Number(incomedData.amount)) || 0,
  //       expense: (expenseData && Number(expenseData.amount)) || 0,
  //       month: cur.month,
  //     };
  //     totalExpense += stat.expense;
  //     totalProfit += stat.income - stat.expense;
  //     let profit = stat.income - stat.expense;
  //     if (
  //       stat.expense < minExpense &&
  //       Number(stat.month) <= new Date().getMonth() + 1
  //     ) {
  //       minExpense = stat.expense;
  //       minExpenseMonth = stat.month;
  //     }
  //     if (stat.expense > maxExpense) {
  //       maxExpense = stat.expense;
  //       maxExpenseMonth = stat.month;
  //     }
      
  //     if (
  //       profit < minProfit &&
  //       Number(stat.month) <= new Date().getMonth() + 1
  //     ) {
  //       minProfit = profit;
  //       minProfitMonth = stat.month;
  //     }
  //     if (profit > maxProfit) {
  //       maxProfit = profit;
  //       maxProfitMonth = stat.month;
  //     }

  //     acc.push(stat);
  //     return acc;
  //   }, []);

  //   averageExpense = totalExpense / Number(new Date().getMonth() + 1);
  //   averageProfit = totalProfit / Number(new Date().getMonth() + 1);
  //   graphStats = [
  //     { label: "Total Profit", value: totalProfit.toFixed(2) },
  //     { label: "Average Profit", value: averageProfit.toFixed(2) },
  //     {
  //       label: "Min. Profit",
  //       value: minProfit.toFixed(2),
  //       month: minProfitMonth,
  //     },
  //     { label: "Max. Profit", value: maxProfit, month: maxProfitMonth },
      
  //     { label: "Total Expense", value: totalExpense.toFixed(2) },
  //     { label: "Average Expense", value: averageExpense.toFixed(2) },
  //     {
  //       label: "Min. Expense",
  //       value: minExpense.toFixed(2),
  //       month: minExpenseMonth,
  //     },
  //     { label: "Max. Expense", value: maxExpense, month: maxExpenseMonth },
  //   ];
  //   const transData = await transactionDB.getMonthlyRentTransaction({
  //     clientId,
  //     status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
  //   });
  //   const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
  //   let minvalue = Number.POSITIVE_INFINITY;
  //   let maxValue = Number.NEGATIVE_INFINITY;
  //   let totalCollection = 0;
  //   let averageCollection = 0;
  //   let minValueMonth = null;
  //   let maxValueMonth = null;
  //   let collectionStats = allMonths.reduce((acc: any, cur: any) => {
  //     const monthData = transData.find((d: any) => d.month === cur);
  //     const stat = {
  //       amount: (monthData && Number(monthData.amount)) || 0,
  //       month: cur,
  //     };
  //     totalCollection += stat.amount;
  //     if (
  //       stat.amount < minvalue &&
  //       Number(stat.month) <= new Date().getMonth() + 1
  //     ) {
  //       minvalue = stat.amount;
  //       minValueMonth = stat.month;
  //     }
  //     if (stat.amount > maxValue) {
  //       maxValue = stat.amount;
  //       maxValueMonth = stat.month;
  //     }
  //     acc.push(stat);
  //     return acc;
  //   }, []);
  //   averageCollection = totalCollection / Number(new Date().getMonth() + 1);
  //   collectionGraphStats = [
  //     { label: "Total Collection", value: totalCollection.toFixed(2) },
  //     { label: "Avg. Collection", value: averageCollection.toFixed(2) },
  //     {
  //       label: "Min. Collection",
  //       value: minvalue.toFixed(2),
  //       month: minValueMonth,
  //     },
  //     {
  //       label: "Max. Collection",
  //       value: maxValue.toFixed(2),
  //       month: maxValueMonth,
  //     },
  //   ];
  // }

  let data = {
    graphData: stats,
    stats: graphStats,
    collectionStats: collectionGraphStats,
  };
  return data;
};

export const clientExpenseGraphWeb = async (client: clientsTypes, term: any, propIds: any,) => {
  const clientId = client.id;
  let stats = [];
  let graphStats;
  let collectionGraphStats;
  let allYears = [];
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  if (2 == term) {
    allYears = await years(joiningYear, 5);
    // let expenses = [
    //   { year: allYears[0], income: 0, expense: 0 },
    //   { year: allYears[1], income: 0, expense: 0 },
    //   { year: allYears[2], income: 0, expense: 0 },
    //   { year: allYears[3], income: 0, expense: 0 },
    //   { year: allYears[4], income: 0, expense: 0 },
    //   { year: allYears[5], income: 0, expense: 0 },
    // ];
    let expenses = allYears.map((year: number) => ({
      year,
      income: 0,
      expense: 0
    }));
    let newExpense = await expenseDB.getYearlyRentTransactionWithoutSecurityForWeb({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      propIds,
    });
    let totalExpense = 0;
    let totalIncome = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseYear = null;
    let minExpenseYear = null;
    let maxProfit = Number.NEGATIVE_INFINITY;
    let minProfit = Number.POSITIVE_INFINITY;
    let maxProfitYear = null;
    let minProfitYear = null;
    let totalProfit = 0;
    let averageProfit = 0;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "expense"
      );
      const incomeData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "income"
      );
      const stat = {
        income: (incomeData && Number(incomeData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        year: cur.year,
      };
      totalIncome += stat.income;
      totalExpense += stat.expense;
      totalProfit += stat.income - stat.expense;
      let profit = stat.income - stat.expense;
      if (stat.expense < minExpense) {
        minExpense = stat.expense;
        minExpenseYear = stat.year;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseYear = stat.year;
      }

      if (profit < minProfit) {
        minProfit = profit;
        minProfitYear = stat.year;
      }
      if (profit > maxProfit) {
        maxProfit = profit;
        maxProfitYear = stat.year;
      }

      acc.push(stat);
      return acc;
    }, []);
    let avgExpense = totalExpense / expenses.length;
    averageProfit = totalProfit / Number(new Date().getMonth() + 1);
    graphStats = [
      { label: "Total Profit", value: totalProfit.toFixed(2) },
      { label: "Average Profit", value: averageProfit.toFixed(2) },
      {
        label: "Min. Profit",
        value: minProfit.toFixed(2),
        year: minProfitYear,
      },
      { label: "Max. Profit", value: maxProfit, year: maxProfitYear },

      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: avgExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        year: minExpenseYear,
      },
      {
        label: "Max. Expense",
        value: maxExpense.toFixed(2),
        year: maxExpenseYear,
      },
    ];
    const transData = await transactionDB.getYearRentTransactionForWeb({
      clientId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      propIds,
    });
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueYear = null;
    let maxValueYear = null;
    let collectionStats = allYears.reduce((acc: any, cur: any) => {
      const yearData = transData.find((d: any) => d.year === cur);
      const stat = {
        amount: (yearData && Number(yearData.amount)) || 0,
        year: cur,
      };
      totalCollection += stat.amount;
      if (stat.amount < minvalue) {
        minvalue = stat.amount;
        minValueYear = stat.year;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueYear = stat.year;
      }
      acc.push(stat);
      return acc;
    }, []);

    averageCollection = totalCollection / stats.length;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        year: minValueYear,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        year: maxValueYear,
      },
    ];
  // } else if (3 === Number(term)) {
  } else {
    const getMonthIndex = (year: number, month: number) => year * 12 + month;

    let year = Number(moment().format("YYYY"));
    
    if (moment().month() < 3) {
      year = year - 1;      
    }
    
    const FYStartDate = moment(`${year}-04-01`).format("YYYY-MM-DD");
    const FYEndDate = moment(`${year + 1}-03-31`).format("YYYY-MM-DD");

    const curYear = year
    const nextYear = year + 1;

    let expenses = [
      { month: 4, year: curYear, income: 0, expense: 0 },
      { month: 5, year: curYear, income: 0, expense: 0 },
      { month: 6, year: curYear, income: 0, expense: 0 },
      { month: 7, year: curYear, income: 0, expense: 0 },
      { month: 8, year: curYear, income: 0, expense: 0 },
      { month: 9, year: curYear, income: 0, expense: 0 },
      { month: 10, year: curYear, income: 0, expense: 0 },
      { month: 11, year: curYear, income: 0, expense: 0 },
      { month: 12, year: curYear, income: 0, expense: 0 },
      { month: 1, year: nextYear, income: 0, expense: 0 },
      { month: 2, year: nextYear, income: 0, expense: 0 },
      { month: 3, year: nextYear, income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getMonthlyIncomeExpenseByDateRangeWithoutSecurityForWeb({
      clientId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      propIds,
    });
    let totalExpense = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseMonth = null;
    let minExpenseMonth = null;
    let maxProfit = Number.NEGATIVE_INFINITY;
    let minProfit = Number.POSITIVE_INFINITY;
    let maxProfitMonth = null;
    let minProfitMonth = null;
    let totalProfit = 0;
    let averageProfit = 0;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "expense"
      );
      const incomedData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "income"
      );
      const stat = {
        income: (incomedData && Number(incomedData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalExpense += stat.expense;
      totalProfit += stat.income - stat.expense;
      let profit = stat.income - stat.expense;
      const statIndex = cur.month * 12 + cur.month;
      const currentIndex = new Date().getFullYear() * 12 + new Date().getMonth() + 1;
      if (
        stat.expense < minExpense &&
        statIndex <= currentIndex
      ) {
        minExpense = stat.expense;
        minExpenseMonth = stat.month;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseMonth = stat.month;
      }
      
      if (
        profit < minProfit &&
        statIndex <= currentIndex
      ) {
        minProfit = profit;
        minProfitMonth = stat.month;
      }
      if (profit > maxProfit) {
        maxProfit = profit;
        maxProfitMonth = stat.month;
      }

      acc.push(stat);
      return acc;
    }, []);

    const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);

    let completedMonths = stats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageExpense = totalExpense / completedMonths;
    averageProfit = totalProfit / completedMonths;
    graphStats = [
      { label: "Total Profit", value: totalProfit.toFixed(2) },
      { label: "Average Profit", value: averageProfit.toFixed(2) },
      {
        label: "Min. Profit",
        value: minProfit.toFixed(2),
        month: minProfitMonth,
      },
      { label: "Max. Profit", value: maxProfit, month: maxProfitMonth },
      
      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: averageExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        month: minExpenseMonth,
      },
      { label: "Max. Expense", value: maxExpense, month: maxExpenseMonth },
    ];
    const transData = await transactionDB.getMonthlyRentTransactionByDateRangeForWeb({
      clientId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
      propIds,
    });
    const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let maxValueMonth = null;
    let collectionStats = expenses.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur.month && d.year === cur.year);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalCollection += stat.amount;
      const statIndex = getMonthIndex(cur.year, cur.month);
      const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);
      if (
        stat.amount < minvalue &&
        statIndex <= currentIndex
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
      }
      acc.push(stat);
      return acc;
    }, []);

    completedMonths = collectionStats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageCollection = totalCollection / completedMonths;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
    ];
  }

  let data = {
    graphData: stats,
    stats: graphStats,
    collectionStats: collectionGraphStats,
  };
  return data;
};

export const propertyExpenseGraph = async (
  property: propertiesTypes,
  term: any
) => {
  // const clientId = client.id;
  const propId = property.id;
  let stats = [];
  let graphStats;
  let collectionGraphStats;
  let allYears = [];
  let client = await clientDB.getById({id: property.clientId});
  let clientCreatedOn = client.createdAt;
  let joiningYear = moment(clientCreatedOn).year();
  if (2 == term) {
    allYears = await years(joiningYear, 5);
    let expenses = [
      { year: allYears[0], income: 0, expense: 0 },
      { year: allYears[1], income: 0, expense: 0 },
      { year: allYears[2], income: 0, expense: 0 },
      { year: allYears[3], income: 0, expense: 0 },
      { year: allYears[4], income: 0, expense: 0 },
      { year: allYears[5], income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getYearlyRentTransactionForProp({
      propId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let totalExpense = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseYear = null;
    let minExpenseYear = null;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "expense"
      );
      const incomeData = newExpense.find(
        (d: any) => d.year === cur.year && d.type === "income"
      );
      const stat = {
        income: (incomeData && Number(incomeData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        year: cur.year,
      };
      totalExpense += stat.expense;
      if (stat.expense < minExpense) {
        minExpense = stat.expense;
        minExpenseYear = stat.year;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseYear = stat.year;
      }

      acc.push(stat);
      return acc;
    }, []);
    let avgExpense = totalExpense / expenses.length;
    graphStats = [
      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: avgExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        year: minExpenseYear,
      },
      {
        label: "Max. Expense",
        value: maxExpense.toFixed(2),
        year: maxExpenseYear,
      },
    ];
    const transData = await transactionDB.getYearRentTransactionForProp({
      propId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueYear = null;
    let maxValueYear = null;
    let collectionStats = allYears.reduce((acc: any, cur: any) => {
      const yearData = transData.find((d: any) => d.year === cur);
      const stat = {
        amount: (yearData && Number(yearData.amount)) || 0,
        year: cur,
      };
      totalCollection += stat.amount;
      if (stat.amount < minvalue) {
        minvalue = stat.amount;
        minValueYear = stat.year;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueYear = stat.year;
      }
      acc.push(stat);
      return acc;
    }, []);

    averageCollection = totalCollection / stats.length;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        year: minValueYear,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        year: maxValueYear,
      },
    ];
  } else if (3 === Number(term)) {
    const getMonthIndex = (year: number, month: number) =>
      year * 12 + month;

    const currentYear = new Date().getFullYear();
    const currentMonth = new Date().getMonth() + 1;

    let year = Number(moment().format("YYYY"));
    
    if (moment().month() < 3) {
      year = year - 1;      
    }
    const FYStartDate = moment(`${year}-04-01`).format("YYYY-MM-DD");
    const FYEndDate = moment(`${year + 1}-03-31`).format("YYYY-MM-DD");

    const curYear = year
    const nextYear = year + 1;

    let expenses = [
      { month: 1, year: nextYear, income: 0, expense: 0 },
      { month: 2, year: nextYear, income: 0, expense: 0 },
      { month: 3, year: nextYear, income: 0, expense: 0 },
      { month: 4, year: curYear, income: 0, expense: 0 },
      { month: 5, year: curYear, income: 0, expense: 0 },
      { month: 6, year: curYear, income: 0, expense: 0 },
      { month: 7, year: curYear, income: 0, expense: 0 },
      { month: 8, year: curYear, income: 0, expense: 0 },
      { month: 9, year: curYear, income: 0, expense: 0 },
      { month: 10, year: curYear, income: 0, expense: 0 },
      { month: 11, year: curYear, income: 0, expense: 0 },
      { month: 12, year: curYear, income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getMonthlyIncomeExpenseByDateRangeForProp({
      propId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let totalExpense = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseMonth = null;
    let minExpenseMonth = null;
    let maxProfit = Number.NEGATIVE_INFINITY;
    let minProfit = Number.POSITIVE_INFINITY;
    let maxProfitMonth = null;
    let minProfitMonth = null;
    let totalProfit = 0;
    let averageProfit = 0;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "expense"
      );
      const incomedData = newExpense.find(
        (d: any) => d.month === cur.month && d.year === cur.year && d.type === "income"
      );
      //if (11 == cur.month)
      //log.info(
      //  `Amount [${incomedData.amount}], Month [${incomedData.month}]`
      //);

      const stat = {
        income: (incomedData && Number(incomedData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalExpense += stat.expense;
      totalProfit += stat.income - stat.expense;
      let profit = stat.income - stat.expense;
      const statIndex = cur.month * 12 + cur.month;
      const currentIndex = new Date().getFullYear() * 12 + new Date().getMonth() + 1;
      if (
        stat.expense < minExpense &&
        statIndex <= currentIndex
      ) {
        minExpense = stat.expense;
        minExpenseMonth = stat.month;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseMonth = stat.month;
      }
      
      if (
        profit < minProfit &&
        statIndex <= currentIndex
      ) {
        minProfit = profit;
        minProfitMonth = stat.month;
      }
      if (profit > maxProfit) {
        maxProfit = profit;
        maxProfitMonth = stat.month;
      }

      acc.push(stat);
      return acc;
    }, []);

    const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);

    let completedMonths = stats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageExpense = totalExpense / completedMonths;
    averageProfit = totalProfit / completedMonths;
    graphStats = [
      { label: "Total Profit", value: totalProfit.toFixed(2) },
      { label: "Average Profit", value: averageProfit.toFixed(2) },
      {
        label: "Min. Profit",
        value: minProfit.toFixed(2),
        month: minProfitMonth,
      },
      { label: "Max. Profit", value: maxProfit, month: maxProfitMonth },
      
      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: averageExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        month: minExpenseMonth,
      },
      { label: "Max. Expense", value: maxExpense, month: maxExpenseMonth },
    ];
    const transData = await transactionDB.getMonthlyRentTransactionByDateRangeForProp({
      propId,
      startDate: FYStartDate,
      endDate: FYEndDate,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let maxValueMonth = null;
    let collectionStats = expenses.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur.month && d.year === cur.year);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur.month,
        year: cur.year,
      };
      totalCollection += stat.amount;
      const statIndex = getMonthIndex(cur.year, cur.month);
      const currentIndex = getMonthIndex(new Date().getFullYear(), new Date().getMonth() + 1);
      if (
        stat.amount < minvalue &&
        statIndex <= currentIndex
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
      }
      acc.push(stat);
      return acc;
    }, []);

    completedMonths = collectionStats.filter((s: any) =>
      getMonthIndex(s.year, s.month) <= currentIndex
    ).length || 1;

    averageCollection = totalCollection / completedMonths;
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
    ];
  } else {
    const year = moment().format("YYYY");
    let expenses = [
      { month: 1, income: 0, expense: 0 },
      { month: 2, income: 0, expense: 0 },
      { month: 3, income: 0, expense: 0 },
      { month: 4, income: 0, expense: 0 },
      { month: 5, income: 0, expense: 0 },
      { month: 6, income: 0, expense: 0 },
      { month: 7, income: 0, expense: 0 },
      { month: 8, income: 0, expense: 0 },
      { month: 9, income: 0, expense: 0 },
      { month: 10, income: 0, expense: 0 },
      { month: 11, income: 0, expense: 0 },
      { month: 12, income: 0, expense: 0 },
    ];
    let newExpense = await expenseDB.getMonthlyIncomeExpenseForProp({
      propId,
      year,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    let totalExpense = 0;
    let averageExpense = 0;
    let maxExpense = Number.NEGATIVE_INFINITY;
    let minExpense = Number.POSITIVE_INFINITY;
    let maxExpenseMonth = null;
    let minExpenseMonth = null;
    stats = expenses.reduce((acc: any, cur: any) => {
      const expenseData = newExpense.find(
        (d: any) => d.month === cur.month && d.type === "expense"
      );
      const incomedData = newExpense.find(
        (d: any) => d.month === cur.month && d.type === "income"
      );
      //if (11 == cur.month)
      //log.info(
      //  `Amount [${incomedData.amount}], Month [${incomedData.month}]`
      //);

      const stat = {
        income: (incomedData && Number(incomedData.amount)) || 0,
        expense: (expenseData && Number(expenseData.amount)) || 0,
        month: cur.month,
      };
      totalExpense += stat.expense;
      if (
        stat.expense < minExpense &&
        Number(stat.month) <= new Date().getMonth() + 1
      ) {
        minExpense = stat.expense;
        minExpenseMonth = stat.month;
      }
      if (stat.expense > maxExpense) {
        maxExpense = stat.expense;
        maxExpenseMonth = stat.month;
      }

      acc.push(stat);
      return acc;
    }, []);

    averageExpense = totalExpense / Number(new Date().getMonth() + 1);
    graphStats = [
      { label: "Total Expense", value: totalExpense.toFixed(2) },
      { label: "Average Expense", value: averageExpense.toFixed(2) },
      {
        label: "Min. Expense",
        value: minExpense.toFixed(2),
        month: minExpenseMonth,
      },
      { label: "Max. Expense", value: maxExpense, month: maxExpenseMonth },
    ];
    const transData = await transactionDB.getMonthlyRentTransactionForProp({
      propId,
      status: CONSTANTS.TRANSACTION_STATUS.SUCCESS,
    });
    const allMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
    let minvalue = Number.POSITIVE_INFINITY;
    let maxValue = Number.NEGATIVE_INFINITY;
    let totalCollection = 0;
    let averageCollection = 0;
    let minValueMonth = null;
    let maxValueMonth = null;
    let collectionStats = allMonths.reduce((acc: any, cur: any) => {
      const monthData = transData.find((d: any) => d.month === cur);
      const stat = {
        amount: (monthData && Number(monthData.amount)) || 0,
        month: cur,
      };
      totalCollection += stat.amount;
      if (
        stat.amount < minvalue &&
        Number(stat.month) <= new Date().getMonth() + 1
      ) {
        minvalue = stat.amount;
        minValueMonth = stat.month;
      }
      if (stat.amount > maxValue) {
        maxValue = stat.amount;
        maxValueMonth = stat.month;
      }
      acc.push(stat);
      return acc;
    }, []);
    averageCollection = totalCollection / Number(new Date().getMonth() + 1);
    collectionGraphStats = [
      { label: "Total Collection", value: totalCollection.toFixed(2) },
      { label: "Avg. Collection", value: averageCollection.toFixed(2) },
      {
        label: "Min. Collection",
        value: minvalue.toFixed(2),
        month: minValueMonth,
      },
      {
        label: "Max. Collection",
        value: maxValue.toFixed(2),
        month: maxValueMonth,
      },
    ];
  }

  let data = {
    graphData: stats,
    stats: graphStats,
    collectionStats: collectionGraphStats,
  };
  return data;
};

export const clientComplaintGraph = async (
  client: clientsTypes,
  term: any,
  month: any,
  year: any
) => {
  if (!month) {
    month = moment().month();
  }
  if (!year) {
    year = moment().year();
  }
  const clientId = client.id;
  let stats = [];
  let graphStats;
  let topComplaints = [];
  let topComplaintsByProp = [];
  const colors = [
    "#003f5c", "#2f4b7c", "#665191", "#a05195", "#d45087", "#f95d6a", "#ff7c43", "#ffa600", "#bc5090", "#58508d"
  ];
  if (term == CONSTANTS.REPORT_TERMS.YEARLY) {
    const limit = Number(process.env.PIE_CHART_COMPLAINTS_LIMIT);
    const yearlyData = await complaintDB.getYearlyComplaints(
      { clientId },
      year
    );
    let i = 0;
    const graphData = await complaintDB.yearlyGraphData({ clientId }, year);
    const totalComplaints = graphData.totalComplaints || 0;
    const topComplaintTotal = await complaintDB.getYearlyTopTotal(
      { clientId },
      year,
      limit
    );
    for (let data of yearlyData) {
      if (i < limit) {
        topComplaints.push({
          title: data.title,
          value: data.value,
          text: `${((data.value / topComplaintTotal.total) * 100).toFixed(
            2
          )} %`,
          color: colors[i],
        });
      }
      data.text = `${((data.value / totalComplaints) * 100).toFixed(2)} %`;
      i++;
    }
    const resolvedComplaintsTime = await complaintDB.getYearlyAvgResolutionTime(
      { clientId },
      year
    );
    stats = yearlyData;
    graphStats = [
      { label: "Total Complaints", value: graphData.totalComplaints || 0 },
      { label: "Resolved Complaints", value: graphData.resolved || 0 },
      { label: "Pending Complaints", value: graphData.pending || 0 },
      { label: "Assigned Complaints", value: graphData.assigned || 0 },
      {
        label: "Average Resolution Time (Hours)",
        value: Number(resolvedComplaintsTime.avgResolution).toFixed(2) || 0,
      },
    ];
  } else {
    const limit = Number(process.env.PIE_CHART_COMPLAINTS_LIMIT);
    const monthlyData = await complaintDB.getComplaints(
      { clientId },
      month,
      year
    );

    const monthlyDataByProp = await complaintDB.getComplaintsByProperty({
      clientId,
      month,
      year,
    });

    let i = 0;
    const graphData = await complaintDB.graphData({ clientId }, month, year);
    const totalComplaints = graphData.totalComplaints || 0;

    const topComplaintTotal = await complaintDB.getTopTotal(
      { clientId },
      month,
      year,
      5
    );

    const topComplaintTotalByProp = await complaintDB.getTopTotalByProp({
      clientId,
      month,
      year,
      limit: 5
    });
    for (let data of monthlyData) {
      if (i < limit) {
        topComplaints.push({
          title: data.title,
          value: data.value,
          text: `${((data.value / topComplaintTotal.total) * 100).toFixed(
            2
          )} %`,
          color: colors[i],
        });
      }
      data.text = `${((data.value / totalComplaints) * 100).toFixed(2)}%`;
      i++;
    }

    i = 0;
    for (let data of monthlyDataByProp) {
      if (i < limit) {
        topComplaintsByProp.push({
          title: data.propName,
          value: data.value,
          text: `${((data.value / topComplaintTotalByProp.total) * 100).toFixed(
            2
          )} %`,
          color: colors[i],
        });
      }
      data.text = `${((data.value / totalComplaints) * 100).toFixed(2)}%`;
      i++;
    }
    const resolvedComplaintsTime = await complaintDB.getAvgResolutionTime(
      { clientId },
      month,
      year
    );
    stats = monthlyData;
    graphStats = [
      { label: "Total Complaints", value: graphData.totalComplaints || 0 },
      { label: "Resolved Complaints", value: graphData.resolved || 0 },
      { label: "Pending Complaints", value: graphData.pending || 0 },
      { label: "Assigned Complaints", value: graphData.assigned || 0 },
      {
        label: "Average Resolution Time (Hours)",
        value: Number(resolvedComplaintsTime.avgResolution).toFixed(2) || 0,
      },
    ];
  }
  let data = {
    graphData: topComplaints,
    propertyData: topComplaintsByProp,
    complaintStats: stats,
    stats: graphStats,
  };
  return data;
};

export const clientComplaintGraphX = async (
  client: clientsTypes,
  startDate: string,
  endDate: string
) => {
  const clientId = client.id;
  let graphStats;
  let topComplaints = [];
  let topComplaintsByProp = [];
  let topComplaintsByTenant = [];
  const colors = [
    "#003f5c", "#2f4b7c", "#665191", "#a05195", "#d45087", "#f95d6a", "#ff7c43", "#ffa600", "#bc5090", "#58508d"
  ];
  
    const limit = Number(process.env.PIE_CHART_COMPLAINTS_LIMIT);
    const complaintsCategoryData = await complaintDB.getComplaintsWithDates({ 
      clientId,
      startDate: moment(startDate).format("YYYY-MM-DD"),
      endDate: moment(endDate).format("YYYY-MM-DD"),
      limit: 5,
    });

    let i = 0;
    const graphData = await complaintDB.graphDataByDate({ 
      clientId,
      startDate: moment(startDate).format("YYYY-MM-DD"),
      endDate: moment(endDate).format("YYYY-MM-DD"),
    });

    const topComplaintTotal = await complaintDB.getTopTotalByDate({ 
      clientId,
      startDate: moment(startDate).format("YYYY-MM-DD"),
      endDate: moment(endDate).format("YYYY-MM-DD"),
      limit:  limit
    });

    for (let data of complaintsCategoryData) {
        topComplaints.push({
          category: data.title,
          count: data.value,
          text: `${((data.value / topComplaintTotal.total) * 100).toFixed(
            2
          )} %`,
          color: colors[i],
        });
      i++;
    }
    const complainDataByProp = await complaintDB.getComplaintsByPropertyWithDate({
      clientId,
      startDate: moment(startDate).format("YYYY-MM-DD"),
      endDate: moment(endDate).format("YYYY-MM-DD"),
      limit: 5,
    });
    i = 0;
    for (let data of complainDataByProp) {
        topComplaintsByProp.push({
          property: data.propName,
          count: data.value,
        });
      i++;
    }
    const complainDataByTenant = await complaintDB.getComplaintsByTenantWithDate({
      clientId,
      startDate: moment(startDate).format("YYYY-MM-DD"),
      endDate: moment(endDate).format("YYYY-MM-DD"),
      limit: 6,
    })

    for (let data of complainDataByTenant) {
        topComplaintsByTenant.push({
          name: data.name,
          count: data.total,
          mobile: data.mobile,
          resolved: Number(data?.resolved) || 0,
        });
      i++;
    }
    graphStats = {
      totalComplaints: graphData.totalComplaints || 0 ,
      resolvedComplaints: graphData.resolved || 0
    }
  let data = {
    stats: graphStats,
    graphData: topComplaints,
    propertyWise: topComplaintsByProp,
    topTenants: topComplaintsByTenant,
  };
  return data;
};

export const clientRentCollectedExpectedGraph = async (
  client: clientsTypes,
  month: any,
  year: any
) => {
  if (!month) {
    month = moment().month() + 1;
  }
  if (!year) {
    year = moment().year();
  }

  // const daysInMonth = moment(`${year}-${month}`, "YYYY-MM").daysInMonth();
  // const dates = Array.from({ length: daysInMonth }, (_, i) =>
  //   moment(`${year}-${month}-${i + 1}`, "YYYY-MM-DD").format("YYYY-MM-DD")
  // );

  const dates = getLast31Days();

  // let rentCollectionData = await ledgerDB.getDailyRentForClient({
  //   clientId: client.id,
  //   month,
  //   year,
  // });

  let rentCollectionData = await transactionDB.getDailyRentForClient({
    clientId: client.id,
  });

  let dailySecurityData = await transactionDB.getDailySecurityForClient({
    clientId: client.id,
  });

  let dailyOfflineData =
    await transactionDB.getDailyOfflineTransactionsForClient({
      clientId: client.id,
    });

  let dailyOnlineData = await transactionDB.getDailyOnlineTransactionsForClient(
    {
      clientId: client.id,
    }
  );

  let rentExpectedData = await occupancyDB.getDailyExpectedRentForClient({
    clientId: client.id,
    month,
    year,
  });

  const stats = dates.map((item: any) => {
    const rentCollection =
      rentCollectionData.find((d: any) => d.date == item.date)?.amount || 0;
    const rentExpected =
      rentExpectedData.find((d: any) => d.date == item.date)?.rentExpected || 0;
    const securityCollection =
      dailySecurityData.find((d: any) => d.date == item.date)?.amount || 0;
    const offlineCollection =
      dailyOfflineData.find((d: any) => d.date == item.date)?.amount || 0;
    const onlineCollection =
      dailyOnlineData.find((d: any) => d.date == item.date)?.amount || 0;
    return {
      date: item.date,
      totalIncome: Number(rentCollection),
      totalDues: Number(rentExpected),
      totalSecurity: Number(securityCollection),
      totalOffline: Number(offlineCollection),
      totalOnline: Number(onlineCollection),
    };
  });

  return { data: stats };
};
