import log from "../../config/log";
import moment from "moment";
import transactionDB from "../../models/transaction.model";
import CONSTANTS from "../../config/constants";

type Transaction = {
  createdAt: string;
  amount: number;
  type: number;
  clientId: number;
  tenantId: number;
  description: string;
  // add other fields if needed
};

export const formatLedgerData = async (
  transactions: Transaction[],
) => {
  // Sort by date
  transactions.sort((a: Transaction, b: Transaction) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());

  // Group by year-month (e.g. "2025-10")
  const grouped: { [key: string]: Transaction[] } = {};
  for (const tx of transactions) {
    const monthKey = moment(tx.createdAt).format("YYYY-MM");
    if (!grouped[monthKey]) grouped[monthKey] = [];
    grouped[monthKey].push(tx);
  }

  let runningBalance = 0;
  type Row = {
    date: string;
    description: string;
    utr: string;
    remark: string,
    bankRefNum: string,
    recordedBy: string,
    mode: string,
    dues: number;
    payments: number;
    balance: number;
  };
  const report: {
    monthKey: string;
    month: string;
    openingBalance: number;
    rows: Row[];
    totalDues: number;
    totalPayments: number;
    closingBalance: number;
  }[] = [];

  // Process each group in descending order (latest first)
  //const sortedMonthKeys = Object.keys(grouped).sort((a, b) => b.localeCompare(a));
  const sortedMonthKeys = Object.keys(grouped).sort(
    (a, b) =>
      moment(b, "YYYY-MM").toDate().getTime() -
      moment(a, "YYYY-MM").toDate().getTime()
  );


  for (const monthKey of sortedMonthKeys) {
    const txs = grouped[monthKey];
    const monthLabel = moment(monthKey, "YYYY-MM").format("MMMM YYYY");

    const monthData: {
      monthKey: string;
      month: string;
      openingBalance: number;
      rows: Row[];
      totalDues: number;
      totalPayments: number;
      closingBalance: number;
    } = {
      monthKey,            // e.g. "2025-10"
      month: monthLabel,   // e.g. "October 2025"
      openingBalance: runningBalance,
      rows: [],
      totalDues: 0,
      totalPayments: 0,
      closingBalance: 0,
    };

    // Sort transactions descending within the month
    txs.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());

    for (const tx of txs) {
      const isPayment = tx.amount < 0;
      const dues = isPayment ? 0 : tx.amount;
      const payments = isPayment ? tx.amount : 0;
      let utr = "";
      let remark = "";
      let bankRefNum = "";
      let recordedBy = "";
      let mode = "";
      if(tx.amount < 0) {
        let transData = await transactionDB.getTransByAmountTypeClientIdTenantIdAndCreatedAt ({ 
          amount: Math.abs(tx.amount), 
          clientId: tx?.clientId, 
          tenantId: tx?.tenantId, 
          transactionFor: tx?.type, 
          createdAt: moment(tx?.createdAt).format("YYYY-MM-DD") 
        });

        utr = transData?.utrNo || "";
        remark = transData?.remarks || "";
        bankRefNum = transData?.bankRefNum || "";
        recordedBy = transData?.recordedBy || "";
        if(transData?.mode === CONSTANTS.TRANSACTION_MODES.UPI) {
          mode = "upi";
        } else if(transData?.mode === CONSTANTS.TRANSACTION_MODES.CARD) {
          mode = "Card";
        } else if(transData?.mode === CONSTANTS.TRANSACTION_MODES.NET_BANKING) {
          mode = "Net Banking";
        } else if(transData?.mode === CONSTANTS.TRANSACTION_MODES.ADJUSTED_FROM_SECURITY) {
          mode = "Adjusted from security";
        } else {
          mode = "Cash";
        }
      }
      runningBalance += tx.amount;

      monthData.rows.push({
        date: moment(tx.createdAt).format("DD MMM YYYY"),
        description: tx.description,
        utr: utr,
        remark: remark,
        mode: mode,
        bankRefNum: bankRefNum,
        recordedBy: recordedBy,
        dues: dues || 0,
        payments: payments || 0,
        balance: runningBalance,
      });

      if (dues) monthData.totalDues += dues;
      if (payments) monthData.totalPayments += payments;
    }

    monthData.closingBalance = runningBalance;
    report.push(monthData);
  }

  return report;

};

