/**
 * Statement aging helper — customer-statement (wave-16, spec 183).
 *
 * Computes the aging summary for open invoices as of a given date.
 * Used by buildCustomerStatement to populate the aging footer on the statement.
 *
 * Included statuses: SENT, APPROVED, TAX_ISSUED, PARTIALLY_PAID
 * Age = asOf - effectiveDueDate in days where
 *   effectiveDueDate = COALESCE(due_date, sentAt + defaultPaymentTermsDays)
 *
 * d0_30:   age <= 30 (includes current / not-yet-due)
 * d31_60:  31 <= age <= 60
 * d61_90:  61 <= age <= 90
 * d90plus: age > 90
 *
 * For PARTIALLY_PAID: outstanding = total - amountPaid
 * For others: outstanding = total
 */
import type { StatementAgingSummary } from '@zync/types'

const OPEN_STATUSES = new Set(['SENT', 'APPROVED', 'TAX_ISSUED', 'PARTIALLY_PAID'])

export interface OpenInvoiceForAging {
  status: string
  dueDate: string | null
  sentAt: string | null
  total: number
  totalIls: number | null
  amountPaid: number
}

export function computeStatementAging(
  invoices: OpenInvoiceForAging[],
  asOf: string,
  defaultPaymentTermsDays: number,
): StatementAgingSummary {
  const asOfDate = new Date(asOf)
  asOfDate.setHours(0, 0, 0, 0)

  const result: StatementAgingSummary = { d0_30: 0, d31_60: 0, d61_90: 0, d90plus: 0 }

  for (const inv of invoices) {
    if (!OPEN_STATUSES.has(inv.status)) continue

    // Outstanding amount: use totalIls when available, else total
    const base = inv.totalIls != null ? inv.totalIls : inv.total
    const outstanding =
      inv.status === 'PARTIALLY_PAID' ? Math.max(0, base - inv.amountPaid) : base

    if (outstanding <= 0) continue

    // Effective due date
    let effectiveDueDate: Date | null = null
    if (inv.dueDate) {
      effectiveDueDate = new Date(inv.dueDate)
      effectiveDueDate.setHours(0, 0, 0, 0)
    } else if (inv.sentAt) {
      effectiveDueDate = new Date(inv.sentAt)
      effectiveDueDate.setHours(0, 0, 0, 0)
      effectiveDueDate.setDate(effectiveDueDate.getDate() + defaultPaymentTermsDays)
    }

    // Age in days (negative = not yet due → treated as 0)
    const ageDays = effectiveDueDate
      ? Math.floor((asOfDate.getTime() - effectiveDueDate.getTime()) / (1000 * 60 * 60 * 24))
      : 0

    if (ageDays <= 30) {
      result.d0_30 += outstanding
    } else if (ageDays <= 60) {
      result.d31_60 += outstanding
    } else if (ageDays <= 90) {
      result.d61_90 += outstanding
    } else {
      result.d90plus += outstanding
    }
  }

  return result
}
