// Utility helpers — currency formatting, date helpers, ID generation, math.

const fmtZAR = (n, opts = {}) => {
  const { cents = true, sign = false } = opts;
  const num = Number.isFinite(n) ? n : 0;
  const abs = Math.abs(num);
  const fixed = cents ? abs.toFixed(2) : Math.round(abs).toString();
  const [intPart, decPart] = fixed.split('.');
  // Space thousands separator (SA standard)
  const spaced = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
  const body = decPart ? `${spaced}.${decPart}` : spaced;
  const prefix = sign ? (num < 0 ? '−' : '+') : (num < 0 ? '−' : '');
  return `${prefix}R ${body}`;
};

const fmtZARShort = (n) => {
  const abs = Math.abs(n);
  if (abs >= 1_000_000) return `R ${(n / 1_000_000).toFixed(1).replace(/\.0$/, '')}m`;
  if (abs >= 1_000) return `R ${(n / 1_000).toFixed(1).replace(/\.0$/, '')}k`;
  return `R ${Math.round(n)}`;
};

const uid = () => Math.random().toString(36).slice(2, 10);

const monthNames = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const dayNames = ['M','T','W','T','F','S','S'];

const today = () => new Date(2026, 3, 28); // pin to project "current date" for stable demo
const fmtDate = (d) => `${d.getDate()} ${monthNames[d.getMonth()]}`;

// Smooth interpolate between two numbers — used by useCountUp.
const useCountUp = (target, duration = 800) => {
  const [v, setV] = React.useState(target);
  const fromRef = React.useRef(target);
  React.useEffect(() => {
    const from = fromRef.current;
    const to = target;
    if (from === to) return;
    const start = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      const ease = 1 - Math.pow(1 - p, 3);
      setV(from + (to - from) * ease);
      if (p < 1) raf = requestAnimationFrame(tick);
      else fromRef.current = to;
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, duration]);
  return v;
};

// Category palette — also used by Sankey, donut, transactions list.
const CATEGORIES = [
  { id: 'groceries', label: 'Groceries', color: 'mint', cssVar: '--mint' },
  { id: 'rent', label: 'Rent / Bond', color: 'sky', cssVar: '--sky' },
  { id: 'utilities', label: 'Utilities', color: 'amber', cssVar: '--amber' },
  { id: 'transport', label: 'Transport / Fuel', color: 'violet', cssVar: '--violet' },
  { id: 'eating-out', label: 'Eating out', color: 'coral', cssVar: '--coral' },
  { id: 'entertainment', label: 'Entertainment', color: 'pink', cssVar: '--pink' },
  { id: 'medical', label: 'Medical', color: 'sky', cssVar: '--sky' },
  { id: 'subscriptions', label: 'Subscriptions', color: 'violet', cssVar: '--violet' },
  { id: 'other', label: 'Other', color: 'amber', cssVar: '--amber' },
];

const categoryById = (id) => CATEGORIES.find(c => c.id === id) || CATEGORIES[CATEGORIES.length - 1];

const INCOME_SOURCES = [
  { id: 'salary', label: 'Salary' },
  { id: 'freelance', label: 'Freelance / Side hustle' },
  { id: 'rental', label: 'Rental income' },
  { id: 'interest', label: 'Interest / Dividends' },
  { id: 'other', label: 'Other' },
];

// Avatar palette for household members
const AVATAR_COLORS = [
  'oklch(0.55 0.13 165)', // mint deep
  'oklch(0.55 0.15 30)',  // coral
  'oklch(0.50 0.13 290)', // violet
  'oklch(0.50 0.10 230)', // sky
  'oklch(0.55 0.13 80)',  // amber
  'oklch(0.50 0.10 350)', // pink
];

Object.assign(window, {
  fmtZAR, fmtZARShort, uid, monthNames, dayNames, today, fmtDate,
  useCountUp, CATEGORIES, categoryById, INCOME_SOURCES, AVATAR_COLORS,
});
