import type { Holding, PortfolioSummary } from '@/lib/types'; function asFiniteNumber(value: string | number | null | undefined) { if (value === null || value === undefined) { return 0; } const parsed = typeof value === 'number' ? value : Number(value); return Number.isFinite(parsed) ? parsed : 0; } function toDecimalString(value: number, digits = 4) { return value.toFixed(digits); } export function recalculateHolding(base: Holding): Holding { const shares = asFiniteNumber(base.shares); const avgCost = asFiniteNumber(base.avg_cost); const price = base.current_price === null ? avgCost : asFiniteNumber(base.current_price); const marketValue = shares * price; const costBasis = shares * avgCost; const gainLoss = marketValue - costBasis; const gainLossPct = costBasis > 0 ? (gainLoss / costBasis) * 100 : 0; return { ...base, shares: toDecimalString(shares, 6), avg_cost: toDecimalString(avgCost, 6), current_price: toDecimalString(price, 6), market_value: toDecimalString(marketValue, 2), gain_loss: toDecimalString(gainLoss, 2), gain_loss_pct: toDecimalString(gainLossPct, 2) }; } export function buildPortfolioSummary(holdings: Holding[]): PortfolioSummary { const positions = holdings.length; const totals = holdings.reduce( (acc, holding) => { const shares = asFiniteNumber(holding.shares); const avgCost = asFiniteNumber(holding.avg_cost); const marketValue = asFiniteNumber(holding.market_value); const gainLoss = asFiniteNumber(holding.gain_loss); acc.totalValue += marketValue; acc.totalGainLoss += gainLoss; acc.totalCostBasis += shares * avgCost; return acc; }, { totalValue: 0, totalGainLoss: 0, totalCostBasis: 0 } ); const avgReturnPct = totals.totalCostBasis > 0 ? (totals.totalGainLoss / totals.totalCostBasis) * 100 : 0; return { positions, total_value: toDecimalString(totals.totalValue, 2), total_gain_loss: toDecimalString(totals.totalGainLoss, 2), total_cost_basis: toDecimalString(totals.totalCostBasis, 2), avg_return_pct: toDecimalString(avgReturnPct, 2) }; }