const MONTHS = [
  'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
];

function toDouble(value) {
  if (typeof value === 'number') return value;
  const parsed = parseFloat(value);
  return Number.isFinite(parsed) ? parsed : 0;
}

function toInt(value) {
  const parsed = parseInt(value, 10);
  return Number.isFinite(parsed) ? parsed : null;
}

function parseDate(value) {
  if (!value) return null;
  const parsed = new Date(value);
  return Number.isNaN(parsed.getTime()) ? null : parsed;
}

function formatCurrency(amount) {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    maximumFractionDigits: 0,
  }).format(Number.isFinite(amount) ? amount : 0);
}

function formatShortDate(date) {
  if (!date) return '-';
  return `${MONTHS[date.getMonth()]} ${String(date.getDate()).padStart(2, '0')}, ${date.getFullYear()}`;
}

function customerName(customer) {
  const firstName = (customer.first_name || '').toString().trim();
  const lastName = (customer.last_name || '').toString().trim();
  const fullName = `${firstName} ${lastName}`.trim();
  return fullName || (customer.name || 'Unknown Customer').toString().trim() || 'Unknown Customer';
}

function riskLabel(riskLevel, balanceStatus, balance) {
  const risk = (riskLevel || '').toString().toLowerCase();
  const status = (balanceStatus || '').toString().toLowerCase();
  if (balance <= 0) return 'Low Risk';
  if (risk.includes('critical') || risk.includes('high') || status === 'past_due') return 'High Risk';
  if (risk.includes('medium') || risk.includes('moderate')) return 'Medium Risk';
  if (risk.includes('low')) return 'Low Risk';
  return 'Low Risk';
}

function agingBucket(latestPayment, balanceStatus, riskLevel, now) {
  if (latestPayment) {
    const diffDays = Math.floor((now.getTime() - latestPayment.getTime()) / (24 * 60 * 60 * 1000));
    if (diffDays <= 15) return '0-15';
    if (diffDays <= 30) return '16-30';
    if (diffDays <= 60) return '31-60';
    return '61+';
  }

  if ((balanceStatus || '').toString().toLowerCase() === 'current') return '0-15';
  if ((balanceStatus || '').toString().toLowerCase() === 'past_due' || (riskLevel || '').toString().toLowerCase().includes('high')) return '61+';
  return '31-60';
}

function parseSnapshotMonth(snapshotMonth, fallbackDate) {
  if (!snapshotMonth) {
    return {
      monthStart: new Date(fallbackDate.getFullYear(), fallbackDate.getMonth(), 1),
      monthEndExclusive: new Date(fallbackDate.getFullYear(), fallbackDate.getMonth() + 1, 1),
      yearStart: new Date(fallbackDate.getFullYear(), 0, 1),
    };
  }

  const [yearStr, monthStr] = snapshotMonth.split('-');
  const year = parseInt(yearStr, 10);
  const month = parseInt(monthStr, 10) - 1;
  const monthStart = new Date(year, month, 1);
  const monthEndExclusive = new Date(year, month + 1, 1);
  const yearStart = new Date(year, 0, 1);
  return { monthStart, monthEndExclusive, yearStart };
}

function buildMonthlyReportSnapshot({
  snapshotMonth,
  generatedAt,
  accountManager,
  customers,
  payments,
}) {
  const now = generatedAt || new Date();
  const { monthStart, monthEndExclusive, yearStart } = parseSnapshotMonth(snapshotMonth, now);

  const latestPaymentByCustomer = new Map();
  let debtClearedThisMonth = 0;
  let debtClearedYearToDate = 0;

  for (const payment of payments || []) {
    const createdAt = parseDate(payment.created_at);
    if (!createdAt) continue;

    if (createdAt >= monthStart && createdAt < monthEndExclusive) {
      debtClearedThisMonth += toDouble(payment.amount);
    }
    if (createdAt >= yearStart && createdAt <= now) {
      debtClearedYearToDate += toDouble(payment.amount);
    }

    const customerId = toInt(payment.customer_id);
    if (customerId == null) continue;
    const existing = latestPaymentByCustomer.get(customerId);
    if (!existing || createdAt > existing) {
      latestPaymentByCustomer.set(customerId, createdAt);
    }
  }

  const outstandingCustomers = (customers || [])
    .filter((customer) => toDouble(customer.ledger_balance) > 0)
    .slice()
    .sort((a, b) => toDouble(b.ledger_balance) - toDouble(a.ledger_balance));

  let totalOutstanding = 0;
  let newDebtAddedThisMonth = 0;
  let highRiskAccounts = 0;
  let newDebtAccounts = 0;
  const buckets = {
    '0-15': 0,
    '16-30': 0,
    '31-60': 0,
    '61+': 0,
  };

  const debtors = outstandingCustomers.map((customer) => {
    const balance = toDouble(customer.ledger_balance);
    totalOutstanding += balance;

    const createdAt = parseDate(customer.created_at);
    if (createdAt && createdAt >= monthStart && createdAt < monthEndExclusive) {
      newDebtAddedThisMonth += balance;
      newDebtAccounts += 1;
    }

    const riskStatus = riskLabel(customer.risk_level, customer.balance_status, balance);
    if (riskStatus.toLowerCase().includes('high')) {
      highRiskAccounts += 1;
    }

    const latestPayment = customer.last_payment_date
      ? parseDate(customer.last_payment_date)
      : latestPaymentByCustomer.get(toInt(customer.id));
    const bucket = agingBucket(latestPayment, customer.balance_status, riskStatus, now);
    buckets[bucket] += balance;

    return {
      name: customerName(customer),
      costPrice: '-',
      sellingPrice: '-',
      totalOwed: formatCurrency(balance),
      lastPaymentDate: formatShortDate(latestPayment),
      riskStatus,
    };
  });

  const monthlyEfficiency = debtClearedThisMonth <= 0
    ? 0
    : (debtClearedThisMonth / (debtClearedThisMonth + newDebtAddedThisMonth + 0.0001)) * 100;

  return {
    generatedAt: now.toISOString(),
    accountManager,
    totalOutstanding,
    newDebtAddedThisMonth,
    debtClearedThisMonth,
    debtClearedYearToDate,
    highRiskAccounts,
    outstandingChangeLabel: totalOutstanding > 0 ? '+12% VS LAST MO' : 'NO OUTSTANDING BALANCE',
    newDebtAccountsLabel: `${newDebtAccounts} ACCOUNTS`,
    monthlyEfficiencyLabel: `EFFICIENCY: ${Math.round(monthlyEfficiency)}%`,
    ytdTargetLabel: 'TARGET: $120K',
    highRiskLabel: highRiskAccounts === 0 ? 'NO HIGH RISK ACCOUNTS' : `${highRiskAccounts} OVER 120 DAYS`,
    pageLabel: '01 / 01',
    agingBuckets: [
      { label: '0-15', amount: buckets['0-15'] },
      { label: '16-30', amount: buckets['16-30'] },
      { label: '31-60', amount: buckets['31-60'] },
      { label: '61+', amount: buckets['61+'] },
    ],
    debtors,
    raw: {
      snapshotMonth,
      customers: customers || [],
      payments: payments || [],
    },
  };
}

module.exports = {
  buildMonthlyReportSnapshot,
};
