/**
 * Pure helpers for the Financial report. No DB / no currency I/O — kept
 * separate from `financial.service.ts` so the bucketing + date maths are
 * unit-testable in isolation.
 */

export type AgingBucket = '0-30' | '31-60' | '61-90' | '90+';

/** Ascending so chart rows render oldest-band-last in a stable order. */
export const AGING_BUCKETS: AgingBucket[] = ['0-30', '31-60', '61-90', '90+'];

/**
 * Map a day count to one of the four age bands. Used for the
 * "expected deposits outstanding by deal age" chart — the payments-model
 * analogue of invoice AR aging (we have no invoice due dates, so age is
 * measured from when the deal started expecting a deposit).
 */
export function agingBucket(daysOutstanding: number): AgingBucket {
  if (daysOutstanding <= 30) return '0-30';
  if (daysOutstanding <= 60) return '31-60';
  if (daysOutstanding <= 90) return '61-90';
  return '90+';
}

/** Zero-padded `YYYY-MM` key in UTC, for grouping money rows by month. */
export function monthKey(d: Date): string {
  const y = d.getUTCFullYear();
  const m = String(d.getUTCMonth() + 1).padStart(2, '0');
  return `${y}-${m}`;
}

/**
 * Continuous ascending list of `YYYY-MM` keys spanning `from`..`to`
 * inclusive. Gives the month/cash-flow charts a gap-free x-axis even for
 * months with no rows (which then render as zero, not a missing bar).
 */
export function monthRange(from: Date, to: Date): string[] {
  const keys: string[] = [];
  const cursor = new Date(Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), 1));
  const end = new Date(Date.UTC(to.getUTCFullYear(), to.getUTCMonth(), 1));
  while (cursor <= end) {
    keys.push(monthKey(cursor));
    cursor.setUTCMonth(cursor.getUTCMonth() + 1);
  }
  return keys;
}

/** Net contribution = revenue collected − expenses. */
export function netContribution(revenue: number, expenses: number): number {
  return revenue - expenses;
}
