// Shared earnings calculation helpers.
// Net Income and Retained Earnings are ALWAYS calculated — never stored.

export const SYSTEM_ACCOUNT_NAMES = {
  retainedEarnings: "Retained Earnings",
  currentYearEarnings: "Current Year Earnings",
  netIncome: "Net Income",
} as const;

export function isRetainedEarnings(a: { name?: string; type?: string } | null | undefined) {
  if (!a) return false;
  return a.type === "equity" && /retained\s+earnings/i.test(a.name ?? "");
}

export function isCurrentYearEarnings(a: { name?: string; type?: string } | null | undefined) {
  if (!a) return false;
  return a.type === "equity" && /current\s+year\s+earnings|net\s+income/i.test(a.name ?? "");
}

export function isSystemEquityAccount(a: { name?: string; type?: string } | null | undefined) {
  return isRetainedEarnings(a) || isCurrentYearEarnings(a);
}

export type EarningsInput = {
  invoices: Array<{ total: number | string; status?: string; issue_date?: string }>;
  expenses: Array<{ amount: number | string; date?: string; category?: string }>;
  bills?: Array<{ total: number | string; paid_amount?: number | string; status?: string; issue_date?: string }>;
};

/**
 * Net Income — ACCRUAL basis.
 * Revenue: all invoices issued in the period (status ≠ void/draft),
 *   regardless of whether payment has been received.
 * Expenses: all expenses recorded + all bills received (total billed,
 *   regardless of whether they have been paid).
 */
export function calcNetIncome(d: EarningsInput): number {
  const income = (d.invoices ?? [])
    .filter((i) => i.status !== "void" && i.status !== "draft")
    .reduce((s, i) => s + Number(i.total || 0), 0);
  const directExp = (d.expenses ?? []).reduce((s, e) => s + Number(e.amount || 0), 0);
  const billExp   = (d.bills ?? [])
    .filter((b) => b.status !== "void" && b.status !== "draft")
    .reduce((s, b) => s + Number(b.total || 0), 0);
  return income - directExp - billExp;
}

export type OpeningBalance = { account_id: string; debit: number | string; credit: number | string };

/**
 * Retained Earnings (live) =
 *   Opening RE (from opening_balances on the RE account, credit − debit)
 *   + accumulated prior-year Net Income (passed in)
 *   − owner draws / dividends (handled via their own equity accounts)
 *
 * Current Year Earnings is returned separately so it can be shown as its
 * own line on the Balance Sheet above Retained Earnings.
 */
export function calcRetainedEarnings(params: {
  openingBalances: OpeningBalance[];
  retainedEarningsAccountId?: string;
  priorYearsNetIncome?: number;
}): number {
  const { openingBalances, retainedEarningsAccountId, priorYearsNetIncome = 0 } = params;
  if (!retainedEarningsAccountId) return priorYearsNetIncome;
  const row = openingBalances.find((b) => b.account_id === retainedEarningsAccountId);
  const opening = row ? Number(row.credit || 0) - Number(row.debit || 0) : 0;
  return opening + priorYearsNetIncome;
}

export function fiscalYearStart(d = new Date()): string {
  return new Date(d.getFullYear(), 0, 1).toISOString().slice(0, 10);
}
