// nudges.jsx — Slimme nudges based on patterns in state
// Returns an array of nudge objects sorted by priority.
// Each nudge: { id, icon, text, kind: 'info'|'warn'|'celebrate'|'tip', action?: {label, onClick} }

function generateNudges(state, money, today = TODAY) {
  const out = [];

  // ─── 1. Bills due soon ───────────────────────────────────────
  const dayOfMonth = today.getDate();
  const cycleEnd = (typeof cycleEndFor === 'function')
    ? cycleEndFor(today, state.cycleResetDay || 23)
    : null;
  const soonBills = state.bills.filter(b => {
    if (b.paid) return false;
    // simple: bill day in next 3 days within current month
    const diff = b.day - dayOfMonth;
    return diff >= 0 && diff <= 3;
  });
  if (soonBills.length > 0) {
    const totalSoon = soonBills.reduce((s, b) => s + b.amount, 0);
    out.push({
      id: 'bills-soon',
      icon: '🪙',
      kind: 'warn',
      text: soonBills.length === 1
        ? `${soonBills[0].name} (${fmtEurShort(soonBills[0].amount)}) komt eraan — ${soonBills[0].day - dayOfMonth === 0 ? 'vandaag' : `over ${soonBills[0].day - dayOfMonth}d`}`
        : `${soonBills.length} rekeningen komen er aan — ${fmtEurShort(totalSoon)} totaal`,
      priority: 95,
    });
  }

  // ─── 2. Cycle approaching reset (3 days before) ──────────────
  if (cycleEnd) {
    const daysToReset = Math.ceil((cycleEnd - today) / 86400000);
    if (daysToReset <= 3 && daysToReset > 0) {
      out.push({
        id: 'cycle-soon',
        icon: '💰',
        kind: 'info',
        text: `Nog ${daysToReset} dag${daysToReset === 1 ? '' : 'en'} tot je salaris — ${fmtEurShort(money.safeToSpend)} over`,
        priority: 70,
      });
    }
    if (daysToReset === 0) {
      out.push({
        id: 'cycle-now',
        icon: '✨',
        kind: 'celebrate',
        text: `Nieuwe maand begint vandaag — fris starten`,
        priority: 90,
      });
    }
  }

  // ─── 3. Spending compared to last cycle ──────────────────────
  if (state.lastCycleSnapshot) {
    const cycProg = (typeof cycleProgress === 'function') ? cycleProgress(state, today) : 0.5;
    state.budgets.forEach(b => {
      const lastSpent = state.lastCycleSnapshot.perCategory?.find(c => c.cat === b.cat)?.spent || 0;
      const thisSpent = state.expenses.filter(e => e.cat === b.cat).reduce((s, e) => s + e.amount, 0);
      // Project this cycle's full-month spend based on cycle progress
      const projected = cycProg > 0.1 ? thisSpent / cycProg : thisSpent;
      if (lastSpent > 10 && projected > lastSpent * 1.3) {
        out.push({
          id: 'overspend-' + b.cat,
          icon: b.icon,
          kind: 'warn',
          text: `${b.label}: op ${Math.round(projected)} koers vs ${Math.round(lastSpent)} vorige maand`,
          priority: 60,
        });
      }
      if (thisSpent > b.limit) {
        out.push({
          id: 'overlimit-' + b.cat,
          icon: b.icon,
          kind: 'warn',
          text: `${b.label} potje is op (${fmtEurShort(thisSpent)} van ${fmtEurShort(b.limit)})`,
          priority: 80,
        });
      }
    });
  }

  // ─── 4. Streak milestones (celebrate 3/7/14/30/60/100 days) ──
  const milestones = [3, 7, 14, 30, 60, 100, 365];
  state.reminders.forEach(r => {
    if (r.doneToday && milestones.includes(r.streak)) {
      out.push({
        id: 'streak-' + r.id,
        icon: '🔥',
        kind: 'celebrate',
        text: `${r.streak} dagen op rij ${r.label.toLowerCase()} — onbreekbaar`,
        priority: 65,
      });
    }
  });

  // ─── 5. Top 3 open in the afternoon ──────────────────────────
  const hour = today.getHours();
  const openTop3 = state.top3.filter(t => !t.done);
  if (hour >= 14 && hour < 21 && openTop3.length > 0) {
    out.push({
      id: 'top3-open',
      icon: '✦',
      kind: 'tip',
      text: openTop3.length === 3
        ? 'Nog niks van je top 3 gedaan — pak één klein stukje'
        : `Nog ${openTop3.length} top-3 open — ${openTop3[0].text}`,
      priority: 55,
    });
  }

  // ─── 6. Savings goal close (>=80%) ───────────────────────────
  state.savings.forEach(g => {
    const pct = g.current / g.target;
    if (pct >= 0.8 && pct < 1) {
      out.push({
        id: 'savings-close-' + g.id,
        icon: '🎯',
        kind: 'tip',
        text: `${g.name} bijna vol — nog ${fmtEurShort(g.target - g.current)}`,
        priority: 50,
      });
    }
  });

  // ─── 7. Mood not logged in a few days ────────────────────────
  // (stub — moodLog logic could check last entry vs today)

  // ─── 8. Routines not done for X days ─────────────────────────
  // Simplified: if a daily reminder has streak 0 AND not done today, suggest
  state.reminders.forEach(r => {
    if (r.recur === 'dagelijks' && !r.doneToday && r.streak === 0) {
      out.push({
        id: 'routine-' + r.id,
        icon: '·',
        kind: 'tip',
        text: `${r.label} — pak 'm vandaag terug op`,
        priority: 40,
      });
    }
  });

  // Sort by priority descending, return top 4
  out.sort((a, b) => b.priority - a.priority);
  return out.slice(0, 4);
}

// Tone colors per nudge kind
function nudgeTone(kind) {
  const map = {
    warn:      { bg: '#FCE7E1', border: '#F4C4B8', text: '#7A2A1A', icon: '#C44A3A' },
    info:      { bg: '#E6EFEA', border: '#C9DBD0', text: '#1C2A24', icon: '#5E7C6B' },
    celebrate: { bg: '#FFF3D9', border: '#F1DDA6', text: '#5A3F0F', icon: '#C68A1E' },
    tip:       { bg: '#F2EFE5', border: '#E1DCCB', text: '#3A332B', icon: '#7B6C58' },
  };
  return map[kind] || map.info;
}

function NudgeCard({ nudge, onDismiss }) {
  const tone = nudgeTone(nudge.kind);
  return (
    <div style={{
      padding: '12px 14px', borderRadius: 14, marginBottom: 8,
      background: tone.bg, border: `1px solid ${tone.border}`,
      display: 'flex', gap: 10, alignItems: 'flex-start',
    }}>
      <span style={{ fontSize: 18, color: tone.icon, lineHeight: 1.2 }}>{nudge.icon}</span>
      <span style={{ fontSize: 13, color: tone.text, lineHeight: 1.45, flex: 1 }}>{nudge.text}</span>
      {onDismiss && (
        <button onClick={onDismiss} style={{
          background: 'transparent', border: 'none', color: tone.text, opacity: 0.4,
          cursor: 'pointer', fontSize: 16, padding: 0, lineHeight: 1, fontFamily: 'inherit',
        }} aria-label="Sluit">×</button>
      )}
    </div>
  );
}

Object.assign(window, { generateNudges, nudgeTone, NudgeCard });
