// shared.jsx — Helpers, Icons, statische Geo-Hilfsmaps.
// Datenhaltung lebt in data-provider.jsx (window.UKProviders).

// ── Standard-Rubriken (Fallback, falls noch kein Sync gelaufen ist) ──
const CATS = [
  { id: 'lebensmittel',  label: 'Lebensmittel',    emoji: '🛒', color: '#7c9b5e' },
  { id: 'essen',         label: 'Essen & Trinken', emoji: '🍽️', color: '#d4823a' },
  { id: 'stellplatz',    label: 'Stellplatz',      emoji: '🏕️', color: '#8b6f47' },
  { id: 'sprit',         label: 'Sprit',           emoji: '⛽', color: '#c9534a' },
  { id: 'transport',     label: 'Transport',       emoji: '🚗', color: '#5e7b9b' },
  { id: 'aktivitaet',    label: 'Aktivität',       emoji: '🎢', color: '#b8588f' },
  { id: 'souvenir',      label: 'Souvenirs',       emoji: '🛍️', color: '#a87cb8' },
  { id: 'eintritt',      label: 'Eintritt',        emoji: '🎟️', color: '#3a8a8b' },
  { id: 'bargeld',       label: 'Bargeld',         emoji: '💶', color: '#6b6b6b' },
  { id: 'trinkgeld',     label: 'Trinkgeld',       emoji: '💰', color: '#c9a13a' },
  { id: 'sonstiges',     label: 'Sonstiges',       emoji: '📦', color: '#9c9c9c' },
];
const CAT_BY_ID = Object.fromEntries(CATS.map(c => [c.id, c]));

// ── Formatter ─────────────────────────────────────────────────
const fmtEUR = (n, opts) => {
  opts = opts || {};
  const sign = opts.sign === true;
  const decimals = opts.decimals != null ? opts.decimals : 2;
  const v = Math.abs(n).toLocaleString('de-DE', {
    minimumFractionDigits: decimals, maximumFractionDigits: decimals,
  });
  return (sign && n < 0 ? '−' : '') + v + ' €';
};
const fmtEURshort = (n) => Math.round(n).toLocaleString('de-DE') + ' €';

const fmtDate = (iso, opts = {}) => {
  const d = new Date(iso + 'T00:00:00');
  return d.toLocaleDateString('de-DE', Object.assign({ day: '2-digit', month: 'short' }, opts));
};
const fmtDateLong = (iso) => {
  const d = new Date(iso + 'T00:00:00');
  return d.toLocaleDateString('de-DE', { weekday: 'long', day: 'numeric', month: 'long' });
};
const fmtWeekday = (iso) => {
  const d = new Date(iso + 'T00:00:00');
  return d.toLocaleDateString('de-DE', { weekday: 'short' });
};

// ── Accessor-Helfer: akzeptieren sowohl Mock-Shape (e.amt, e.d, …) als auch Backend-Shape ──
const expDate = (e) => e.date != null ? e.date : e.d;
const expTime = (e) => e.time != null ? e.time : e.t;
const expCat  = (e) => e.category_id != null ? e.category_id : e.cat;
const expDesc = (e) => e.description != null ? e.description : e.desc;
const expLoc  = (e) => e.location != null ? e.location : e.loc;
const expAmt  = (e) => e.amount_cents != null ? (e.amount_cents / 100) : (e.amt || 0);

const tripStart  = (t) => t.start_date != null ? t.start_date : t.start;
const tripEnd    = (t) => t.end_date   != null ? t.end_date   : t.end;
const tripBudget = (t) => t.budget_cents != null ? (t.budget_cents / 100) : (t.budget || 0);
const tripFlag   = (t) => t.flag || '🌍';

// ── Trip-bezogene Helpers (parametrisch) ─────────────────────
const sumAmt = (arr) => arr.reduce((s, e) => s + expAmt(e), 0);
const dayTotal = (iso, exps) => sumAmt(exps.filter(e => expDate(e) === iso));

const tripDays = (trip) => {
  const out = [];
  if (!trip) return out;
  const s = new Date(tripStart(trip) + 'T00:00:00');
  const e = new Date(tripEnd(trip) + 'T00:00:00');
  for (let d = new Date(s); d <= e; d.setDate(d.getDate() + 1)) {
    out.push(d.toISOString().slice(0, 10));
  }
  return out;
};

const tripDayNum = (iso, trip) => {
  if (!trip) return 1;
  const s = new Date(tripStart(trip) + 'T00:00:00');
  const d = new Date(iso + 'T00:00:00');
  return Math.round((d - s) / 86400000) + 1;
};
const tripLength = (trip) => tripDays(trip).length;

const tripWeeks = (trip) => {
  const days = tripDays(trip);
  const weeks = [];
  for (let i = 0; i < days.length; i += 7) weeks.push(days.slice(i, i + 7));
  return weeks;
};

const tripSpent     = (exps) => sumAmt(exps);
const tripRemaining = (trip, exps) => tripBudget(trip) - tripSpent(exps);

const todayISO = () => new Date().toISOString().slice(0, 10);

const daysPassed = (trip, today) => {
  if (!trip) return 1;
  const t = today || todayISO();
  return Math.max(1, Math.min(tripLength(trip), tripDayNum(t, trip)));
};
const daysLeft   = (trip, today) => Math.max(0, tripLength(trip) - daysPassed(trip, today));
const avgPerDay  = (trip, exps, today) => tripSpent(exps) / Math.max(1, daysPassed(trip, today));
const recommendedPerDay = (trip, exps, today) => tripRemaining(trip, exps) / Math.max(1, daysLeft(trip, today) || 1);

const catTotals = (cats, exps) => {
  const totals = {};
  for (const e of exps) {
    const k = expCat(e);
    if (!k) continue;
    totals[k] = (totals[k] || 0) + expAmt(e);
  }
  return cats
    .map(c => ({ ...c, total: totals[c.id] || 0 }))
    .filter(c => c.total > 0)
    .sort((a, b) => b.total - a.total);
};

const uniqueLocs = (exps) => {
  const seen = new Map();
  for (const e of exps) {
    const loc = expLoc(e);
    if (loc && !seen.has(loc)) seen.set(loc, expDate(e) + (expTime(e) || ''));
  }
  return [...seen.keys()];
};

// ── Tiny inline icons ─────────────────────────────────────────
const Icon = {
  plus: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  back: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M15 18l-6-6 6-6"/></svg>,
  search: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>,
  filter: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M3 6h18M6 12h12M10 18h4"/></svg>,
  chev: (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 6l6 6-6 6"/></svg>,
  pin: (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22s-7-7-7-12a7 7 0 1114 0c0 5-7 12-7 12z"/><circle cx="12" cy="10" r="2.5"/></svg>,
  home: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 11l9-8 9 8M5 10v10h14V10"/></svg>,
  list: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...p}><path d="M4 6h16M4 12h16M4 18h16"/></svg>,
  chart: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 20V10M10 20V4M16 20v-7M22 20H2"/></svg>,
  cal: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 10h18"/></svg>,
  globe: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3 3 15 0 18M12 3c-3 3-3 15 0 18"/></svg>,
  camper: (p={}) => <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M2 17V8h13l4 4h3v5"/><circle cx="7" cy="17" r="2"/><circle cx="17" cy="17" r="2"/><path d="M2 17h3M9 17h6M20 17h2M6 8v4h8"/></svg>,
  loc: (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 22s-7-7-7-12a7 7 0 1114 0c0 5-7 12-7 12z"/><circle cx="12" cy="10" r="2.5"/></svg>,
  close: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" {...p}><path d="M6 6l12 12M18 6L6 18"/></svg>,
  moon: (p={}) => <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z"/></svg>,
  trend: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 17l6-6 4 4 8-8M14 7h7v7"/></svg>,
  gear: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.4 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.4 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.8.4l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.4-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1A1.7 1.7 0 004.6 9a1.7 1.7 0 00-.4-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.4H9a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.8-.4l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.4 1.8V9a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z"/></svg>,
  map: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M1 6v15l7-3 8 3 7-3V3l-7 3-8-3-7 3z"/><path d="M8 3v15M16 6v15"/></svg>,
  cam: (p={}) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 7h3l2-3h8l2 3h3v13H3z"/><circle cx="12" cy="13" r="4"/></svg>,
  euro: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 5a8 8 0 100 14M4 10h8M4 14h7"/></svg>,
  cloud: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M18 17a4 4 0 000-8 6 6 0 00-11.7 1.5A4 4 0 006 17h12z"/></svg>,
  cloudOff: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M18 17a4 4 0 002-7.5M9 5a6 6 0 015.8 4.5M6 17a4 4 0 010-8 5 5 0 01.4-1.7M3 3l18 18"/></svg>,
  sync: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 12a9 9 0 01-15 6.7L3 16M3 12a9 9 0 0115-6.7L21 8M21 3v5h-5M3 21v-5h5"/></svg>,
  layers: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2L2 8l10 6 10-6-10-6zM2 15l10 6 10-6M2 11l10 6 10-6"/></svg>,
  trash: (p={}) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 6h18M8 6V4h8v2M6 6l1 14h10l1-14"/></svg>,
};

Object.assign(window, {
  CATS, CAT_BY_ID,
  fmtEUR, fmtEURshort, fmtDate, fmtDateLong, fmtWeekday,
  expDate, expTime, expCat, expDesc, expLoc, expAmt,
  tripStart, tripEnd, tripBudget, tripFlag,
  sumAmt, dayTotal,
  tripDays, tripDayNum, tripLength, tripWeeks,
  tripSpent, tripRemaining,
  todayISO, daysPassed, daysLeft, avgPerDay, recommendedPerDay,
  catTotals, uniqueLocs,
  Icon,
});
