// app-shared.jsx — small UI primitives used by web + mobile

const Avatar = ({ who, size = 26, ring = false, style }) => {
  const p = window.PEOPLE[who];
  if (!p) return null;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      width: size, height: size, borderRadius: '50%',
      background: p.color, color: '#fbfaf7',
      fontFamily: 'Inter, system-ui', fontWeight: 600,
      fontSize: size * 0.42, letterSpacing: '0.02em',
      boxShadow: ring ? `0 0 0 2px #fbfaf7, 0 0 0 3.5px ${p.color}` : 'none',
      flexShrink: 0,
      ...style,
    }}>{p.initial}</span>
  );
};

const AvatarPair = ({ size = 22 }) => (
  <span style={{ display: 'inline-flex', alignItems: 'center' }}>
    <Avatar who="B" size={size} />
    <Avatar who="C" size={size} style={{ marginLeft: -size * 0.3 }} />
  </span>
);

const Pill = ({ children, color = '#2b3a55', bg, sm, style }) => (
  <span style={{
    display: 'inline-flex', alignItems: 'center', gap: 4,
    padding: sm ? '2px 7px' : '3px 9px',
    borderRadius: 999,
    background: bg || 'rgba(43,58,85,0.07)',
    color, fontSize: sm ? 10 : 11, fontWeight: 500,
    letterSpacing: '0.01em', whiteSpace: 'nowrap',
    ...style,
  }}>{children}</span>
);

const Bar = ({ pct, color, bg = '#ece8de', height = 6, over = false }) => (
  <div style={{ position: 'relative', width: '100%', height, background: bg, borderRadius: height, overflow: 'hidden' }}>
    <div style={{
      width: Math.min(100, pct) + '%', height: '100%',
      background: over ? '#c97a4a' : (color || '#7a9b7e'),
      transition: 'width .4s ease',
    }} />
    {pct > 100 && (
      <div style={{
        position: 'absolute', right: 0, top: 0, bottom: 0,
        width: Math.min(20, pct - 100) + '%',
        background: 'repeating-linear-gradient(45deg, #c97a4a 0 4px, #b06a3e 4px 8px)',
      }} />
    )}
  </div>
);

const Sparkline = ({ data, w = 80, h = 24, color = '#2b3a55', fill }) => {
  if (!data || !data.length) return null;
  const min = Math.min(...data), max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((v - min) / range) * (h - 2) - 1;
    return [x, y];
  });
  const d = pts.map((p, i) => (i === 0 ? 'M' : 'L') + p[0].toFixed(1) + ',' + p[1].toFixed(1)).join(' ');
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
      {fill && <path d={d + ` L ${w},${h} L 0,${h} Z`} fill={fill} opacity="0.25" />}
      <path d={d} fill="none" stroke={color} strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
};

// A donut for category breakdown
const Donut = ({ segments, size = 110, thickness = 14, label, sub }) => {
  const r = (size - thickness) / 2;
  const c = 2 * Math.PI * r;
  const total = segments.reduce((s, x) => s + x.value, 0) || 1;
  let offset = 0;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="#ece8de" strokeWidth={thickness} />
        {segments.map((s, i) => {
          const len = (s.value / total) * c;
          const dash = `${len} ${c - len}`;
          const el = (
            <circle key={i} cx={size/2} cy={size/2} r={r} fill="none"
              stroke={s.color} strokeWidth={thickness}
              strokeDasharray={dash} strokeDashoffset={-offset}
              strokeLinecap="butt" />
          );
          offset += len;
          return el;
        })}
      </svg>
      {(label || sub) && (
        <div style={{
          position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center', textAlign: 'center', lineHeight: 1.1,
        }}>
          <div style={{ fontFamily: 'Newsreader, serif', fontSize: size * 0.21, color: '#2b3a55', fontWeight: 500 }}>{label}</div>
          {sub && <div style={{ fontSize: 10, color: '#7a766c', marginTop: 2, letterSpacing: '0.04em', textTransform: 'uppercase' }}>{sub}</div>}
        </div>
      )}
    </div>
  );
};

// Connect-bank logos
const BankBadge = ({ bank, size = 22 }) => {
  const map = {
    Chase: { bg: '#0f5fb4', label: 'CH' },
    Ally:  { bg: '#621a87', label: 'AL' },
    Wells: { bg: '#b21f1f', label: 'WF' },
    Fid:   { bg: '#1c8141', label: 'FI' },
  };
  const m = map[bank] || { bg: '#7a766c', label: '$' };
  return (
    <span style={{
      width: size, height: size, borderRadius: 6, background: m.bg,
      color: '#fff', fontSize: size * 0.4, fontWeight: 700,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      letterSpacing: '0.03em', flexShrink: 0,
    }}>{m.label}</span>
  );
};

// Card frame
const Card = ({ children, pad = 20, style, density = 'cozy', accent }) => {
  const padding = density === 'compact' ? 14 : pad;
  return (
    <div style={{
      background: '#fdfcf9',
      border: '1px solid #ece8de',
      borderRadius: 14,
      padding,
      position: 'relative',
      ...style,
    }}>
      {accent && (
        <div style={{ position: 'absolute', left: 0, top: 16, bottom: 16, width: 3, background: accent, borderRadius: 2 }} />
      )}
      {children}
    </div>
  );
};

// Section heading
const SectionTitle = ({ eyebrow, title, action, density = 'cozy' }) => (
  <div style={{
    display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
    marginBottom: density === 'compact' ? 10 : 14,
  }}>
    <div>
      {eyebrow && (
        <div style={{ fontSize: 10.5, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#7a766c', marginBottom: 4 }}>
          {eyebrow}
        </div>
      )}
      <h2 style={{
        margin: 0, fontFamily: 'Newsreader, serif', fontWeight: 500,
        fontSize: density === 'compact' ? 20 : 24, letterSpacing: '-0.01em', color: '#1d2638',
      }}>{title}</h2>
    </div>
    {action}
  </div>
);

Object.assign(window, { Avatar, AvatarPair, Pill, Bar, Sparkline, Donut, BankBadge, Card, SectionTitle });
