// Tirelire.ch — reusable UI components

// ────────────────────────────────────────────────────────────
// Formatting helpers
// ────────────────────────────────────────────────────────────
const fmtCHF = (n) => {
  const v = Math.abs(n);
  const s = v.toFixed(2)
    .replace('.', '.')
    .replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
  return (n < 0 ? '-' : '') + s;
};
const fmtCHFnoDec = (n) => Math.round(Math.abs(n)).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');

// ────────────────────────────────────────────────────────────
// Button
// ────────────────────────────────────────────────────────────
function Button({ children, variant = 'primary', size = 'md', full = false, onClick, type, disabled, style = {}, icon }) {
  const base = {
    fontFamily: 'var(--sans)',
    fontWeight: 600,
    borderRadius: 8,
    border: 0,
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: 8,
    cursor: disabled ? 'not-allowed' : 'pointer',
    transition: 'all 160ms ease',
    width: full ? '100%' : undefined,
    opacity: disabled ? 0.55 : 1,
    letterSpacing: '-0.005em',
  };
  const sizes = {
    sm: { fontSize: 13, padding: '8px 14px', height: 34 },
    md: { fontSize: 15, padding: '0 18px', height: 46 },
    lg: { fontSize: 16, padding: '0 22px', height: 54 },
  };
  const variants = {
    primary: { background: 'var(--green)', color: '#fff' },
    secondary: { background: 'var(--surface-2)', color: 'var(--ink)' },
    ghost: { background: 'transparent', color: 'var(--ink)' },
    danger: { background: 'var(--coral)', color: '#fff' },
    outline: { background: 'transparent', color: 'var(--ink)', boxShadow: 'inset 0 0 0 1px var(--border-strong)' },
  };
  return (
    <button type={type} onClick={onClick} disabled={disabled}
      style={{ ...base, ...sizes[size], ...variants[variant], ...style }}>
      {icon}{children}
    </button>
  );
}

// ────────────────────────────────────────────────────────────
// Input
// ────────────────────────────────────────────────────────────
function Input({ label, value, onChange, type = 'text', placeholder, suffix, big = false, autoFocus, id }) {
  return (
    <label htmlFor={id} style={{ display: 'block', width: '100%' }}>
      {label && (
        <div style={{
          fontSize: 12, fontWeight: 600, color: 'var(--muted)',
          letterSpacing: '0.02em', textTransform: 'uppercase', marginBottom: 8,
        }}>{label}</div>
      )}
      <div style={{
        position: 'relative',
        background: 'var(--surface)',
        borderRadius: 8,
        boxShadow: 'inset 0 0 0 1px var(--border)',
        transition: 'box-shadow 160ms ease',
      }}>
        <input id={id} autoFocus={autoFocus}
          type={type} value={value} placeholder={placeholder}
          onChange={(e) => onChange && onChange(e.target.value)}
          style={{
            width: '100%', border: 0, outline: 0, background: 'transparent',
            padding: big ? '14px 14px' : '13px 14px',
            fontFamily: big ? 'var(--mono)' : 'var(--sans)',
            fontSize: big ? 28 : 15,
            fontWeight: big ? 500 : 500,
            color: 'var(--ink)',
            borderRadius: 8,
            paddingRight: suffix ? 56 : 14,
          }} />
        {suffix && (
          <div style={{
            position: 'absolute', right: 14, top: '50%', transform: 'translateY(-50%)',
            color: 'var(--muted)', fontFamily: 'var(--mono)', fontSize: big ? 18 : 13,
            fontWeight: 500,
          }}>{suffix}</div>
        )}
      </div>
    </label>
  );
}

// ────────────────────────────────────────────────────────────
// Card
// ────────────────────────────────────────────────────────────
function Card({ children, style = {}, padding = 20, onClick }) {
  return (
    <div onClick={onClick} style={{
      background: 'var(--surface)',
      borderRadius: 12,
      padding,
      boxShadow: 'var(--shadow-md)',
      border: '1px solid var(--border)',
      ...style,
    }}>
      {children}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// SectionLabel — Swiss editorial section number
// ────────────────────────────────────────────────────────────
function SectionLabel({ num, title, action }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
      padding: '0 4px 10px', gap: 12,
    }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, minWidth: 0 }}>
        <h3 style={{
          margin: 0, fontSize: 15, fontWeight: 600, color: 'var(--ink)',
          letterSpacing: '-0.01em', whiteSpace: 'nowrap',
          overflow: 'hidden', textOverflow: 'ellipsis',
        }}>{title}</h3>
      </div>
      {action && <div style={{ flexShrink: 0 }}>{action}</div>}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// MetricTile
// ────────────────────────────────────────────────────────────
function MetricTile({ label, amount, tone = 'neutral', big = false }) {
  const color = tone === 'positive' ? 'var(--green)'
    : tone === 'negative' ? 'var(--coral)'
    : 'var(--ink)';
  return (
    <div style={{ flex: 1, minWidth: 0 }}>
      <div style={{
        fontSize: 11, fontWeight: 600, color: 'var(--muted)',
        textTransform: 'uppercase', letterSpacing: '0.04em', marginBottom: 6,
      }}>{label}</div>
      <div style={{
        fontFamily: big ? 'var(--serif)' : 'var(--mono)',
        fontStyle: big ? 'italic' : 'normal',
        fontSize: big ? 38 : 19,
        fontWeight: big ? 400 : 600,
        color, letterSpacing: big ? '-0.02em' : '-0.01em',
        lineHeight: 1.05, whiteSpace: 'nowrap',
      }}>
        {tone === 'positive' && !big ? '+' : ''}{fmtCHF(amount)}
        <span style={{
          fontFamily: 'var(--mono)', fontStyle: 'normal',
          fontSize: big ? 14 : 11, color: 'var(--muted)', marginLeft: 6,
          fontWeight: 500,
        }}>CHF</span>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// CategoryPill
// ────────────────────────────────────────────────────────────
function CategoryPill({ category, selected, onClick, size = 'md' }) {
  const small = size === 'sm';
  return (
    <button onClick={onClick} style={{
      display: 'inline-flex', alignItems: 'center', gap: 7,
      padding: small ? '6px 11px' : '9px 14px',
      borderRadius: 999,
      background: selected ? 'var(--ink)' : 'var(--surface)',
      color: selected ? 'var(--bg)' : 'var(--ink)',
      border: selected ? '1px solid var(--ink)' : '1px solid var(--border)',
      fontSize: small ? 12 : 13,
      fontWeight: 500,
      cursor: 'pointer',
      transition: 'all 140ms ease',
      whiteSpace: 'nowrap',
    }}>
      <span style={{ fontSize: small ? 13 : 14 }}>{category.emoji}</span>
      {category.label}
    </button>
  );
}

// ────────────────────────────────────────────────────────────
// TransactionRow
// ────────────────────────────────────────────────────────────
function TransactionRow({ tx, categories, onClick }) {
  const cat = categories.find(c => c.id === tx.categoryId) || categories[0];
  const isIncome = tx.amount > 0;
  return (
    <div onClick={onClick} style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '12px 4px',
      cursor: onClick ? 'pointer' : 'default',
      borderBottom: '1px solid var(--border)',
    }}>
      <div style={{
        width: 36, height: 36, borderRadius: 10,
        background: 'var(--surface-2)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: 17, flexShrink: 0,
      }}>{cat.emoji}</div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 14, fontWeight: 600, color: 'var(--ink)',
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          letterSpacing: '-0.005em',
        }}>{tx.description || cat.label}</div>
        <div style={{
          fontSize: 12, color: 'var(--muted)', marginTop: 2,
          display: 'flex', alignItems: 'center', gap: 6,
        }}>
          <span>{cat.label}</span>
          <span style={{ width: 3, height: 3, borderRadius: 999, background: 'var(--muted-2)' }} />
          <span>{tx.dateLabel}</span>
        </div>
      </div>
      <div style={{
        fontFamily: 'var(--mono)', fontSize: 14, fontWeight: 600,
        color: isIncome ? 'var(--green)' : 'var(--ink)',
        whiteSpace: 'nowrap',
      }}>
        {isIncome ? '+' : '−'}{fmtCHF(Math.abs(tx.amount))}
        <span style={{ color: 'var(--muted)', marginLeft: 4, fontSize: 11 }}>CHF</span>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Wordmark
// ────────────────────────────────────────────────────────────
function Wordmark({ size = 28 }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'baseline', gap: 0,
      fontFamily: 'var(--sans)', fontWeight: 700,
      fontSize: size, color: 'var(--ink)',
      letterSpacing: '-0.03em', lineHeight: 1,
    }}>
      <span style={{ position: 'relative' }}>
        Tirelire
        <span style={{
          position: 'absolute', left: 0, right: 0, bottom: -2,
          height: 3, background: 'var(--yellow)', borderRadius: 2,
        }} />
      </span>
      <span style={{ color: 'var(--green)', fontWeight: 700 }}>.ch</span>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Logo mark (small piggy bank glyph using simple geometry)
// ────────────────────────────────────────────────────────────
function LogoMark({ size = 44 }) {
  return (
    <img src="logo.png" alt="Tirelire.ch"
      style={{ width: size, height: size, borderRadius: 10, objectFit: 'contain' }} />
  );
}

// ────────────────────────────────────────────────────────────
// Toggle / Segmented control
// ────────────────────────────────────────────────────────────
function Segmented({ options, value, onChange, danger = false }) {
  return (
    <div style={{
      display: 'flex', padding: 4,
      background: 'var(--surface-2)', borderRadius: 999,
      position: 'relative',
    }}>
      {options.map(opt => {
        const active = value === opt.value;
        const accent = opt.tone === 'expense' ? 'var(--coral)'
          : opt.tone === 'income' ? 'var(--green)' : 'var(--ink)';
        return (
          <button key={opt.value} onClick={() => onChange(opt.value)}
            style={{
              flex: 1, padding: '9px 14px',
              border: 0, borderRadius: 999,
              background: active ? accent : 'transparent',
              color: active ? '#fff' : 'var(--muted)',
              fontWeight: 600, fontSize: 13,
              cursor: 'pointer', transition: 'all 180ms ease',
            }}>{opt.label}</button>
        );
      })}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Stacked horizontal bar (for category split)
// ────────────────────────────────────────────────────────────
function StackedBar({ segments, total, height = 10 }) {
  return (
    <div style={{
      display: 'flex', height, borderRadius: 999, overflow: 'hidden',
      background: 'var(--surface-2)', gap: 2,
    }}>
      {segments.map((s, i) => (
        <div key={i} title={`${s.label}: ${fmtCHF(s.value)} CHF`}
          style={{
            width: `${(s.value / total) * 100}%`,
            background: s.color,
            transition: 'width 400ms ease',
            minWidth: s.value > 0 ? 4 : 0,
          }} />
      ))}
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// 50/30/20 rule bars
// ────────────────────────────────────────────────────────────
function RuleBar({ label, used, target, color }) {
  const pct = Math.min(100, (used / target) * 100);
  const over = used > target;
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink)' }}>{label}</div>
        <div style={{ fontFamily: 'var(--mono)', fontSize: 11, color: over ? 'var(--coral)' : 'var(--muted)' }}>
          {fmtCHFnoDec(used)} / {fmtCHFnoDec(target)} CHF
        </div>
      </div>
      <div style={{
        height: 6, background: 'var(--surface-2)', borderRadius: 999,
        overflow: 'hidden', position: 'relative',
      }}>
        <div style={{
          width: `${pct}%`, height: '100%',
          background: over ? 'var(--coral)' : color,
          transition: 'width 500ms cubic-bezier(.2,.8,.2,1)',
          borderRadius: 999,
        }} />
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────
// Icons (inline SVG, hairline)
// ────────────────────────────────────────────────────────────
const Icon = {
  plus: (s=20) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>,
  chevronLeft: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>,
  chevronRight: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18l6-6-6-6"/></svg>,
  arrowRight: (s=16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>,
  close: (s=22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>,
  home: (s=22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 11l9-8 9 8M5 10v10h14V10"/></svg>,
  list: (s=22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>,
  settings: (s=22) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.3 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.3 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.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.3-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.3H9a1.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-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.3 1.8V9a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z"/></svg>,
  lock: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 118 0v4"/></svg>,
  check: (s=16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 7"/></svg>,
  shield: (s=14) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l8 3v6c0 5-3.5 8.5-8 9-4.5-.5-8-4-8-9V6l8-3z"/></svg>,
  bank: (s=14) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 10l9-5 9 5M5 10v8M19 10v8M9 10v8M15 10v8M3 21h18"/></svg>,
  sun: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>,
  moon: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M21 12.8A9 9 0 1111.2 3a7 7 0 009.8 9.8z"/></svg>,
  trash: (s=16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6M10 11v6M14 11v6M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2"/></svg>,
  barChart: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><rect x="18" y="3" width="4" height="18"/><rect x="10" y="8" width="4" height="13"/><rect x="2" y="13" width="4" height="8"/></svg>,
  umbrella: (s=18) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M23 12a11 11 0 00-22 0"/><path d="M12 12v6a2 2 0 004 0"/></svg>,
  bug: (s=16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M8 2l1.5 1.5M16 2l-1.5 1.5M9 9h6M9 12h6M9 15h6"/><rect x="7" y="7" width="10" height="12" rx="3"/><path d="M4 10h3M17 10h3M4 14h3M17 14h3M7 19l-3 2M17 19l3 2"/></svg>,
  idea: (s=16) => <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M9 21h6M12 3a6 6 0 016 6c0 2.5-1.5 4.5-3 6H9c-1.5-1.5-3-3.5-3-6a6 6 0 016-6z"/><path d="M9 17h6"/></svg>,
};

Object.assign(window, {
  fmtCHF, fmtCHFnoDec,
  Button, Input, Card, SectionLabel, MetricTile,
  CategoryPill, TransactionRow, Wordmark, LogoMark,
  Segmented, StackedBar, RuleBar, Icon,
});
