// kit.jsx — PocketPolyglot shared design kit
// Theme tokens, waveform hero, play control, folk-accent, small primitives.
// Exports to window. Theme-aware: every component takes (dark, t) where t = tweaks.

// ── Theme ────────────────────────────────────────────────────────────────
// Accent presets (primary blue family + a carmine nod to the Baltic brief)
const PP_ACCENTS = {
  nordic:  { light: '#2C5E8C', dark: '#6EA8DA' },
  steel:   { light: '#3A6B7E', dark: '#74B6C6' },
  ink:     { light: '#26456A', dark: '#7FA8D6' },
  carmine: { light: '#9E2B3A', dark: '#E0748A' },
};

function ppTheme(dark, t = {}) {
  const acc = PP_ACCENTS[t.accent || 'nordic'] || PP_ACCENTS.nordic;
  const primary = dark ? acc.dark : acc.light;
  if (dark) {
    return {
      dark: true,
      bg: '#0E1318',
      surface: '#171E27',
      surface2: '#1F2934',
      sunken: '#0A0E12',
      ink: '#EAF1F8',
      sub: 'rgba(234,241,248,0.60)',
      faint: 'rgba(234,241,248,0.34)',
      hair: 'rgba(255,255,255,0.09)',
      line: 'rgba(255,255,255,0.07)',
      primary,
      primarySoft: hexA(primary, 0.18),
      primaryFaint: hexA(primary, 0.10),
      onPrimary: '#0B1117',
      wavePlayed: primary,
      waveRest: 'rgba(234,241,248,0.20)',
      good: '#5DBE96',
      goodSoft: 'rgba(93,190,150,0.16)',
      shadow: '0 1px 2px rgba(0,0,0,0.5)',
      shadowCard: '0 2px 10px rgba(0,0,0,0.35)',
    };
  }
  return {
    dark: false,
    bg: '#F4F2ED',
    surface: '#FFFFFF',
    surface2: '#FBFAF6',
    sunken: '#ECEAE3',
    ink: '#1A2733',
    sub: 'rgba(26,39,51,0.58)',
    faint: 'rgba(26,39,51,0.34)',
    hair: 'rgba(26,39,51,0.09)',
    line: 'rgba(26,39,51,0.07)',
    primary,
    primarySoft: hexA(primary, 0.10),
    primaryFaint: hexA(primary, 0.055),
    onPrimary: '#FFFFFF',
    wavePlayed: primary,
    waveRest: 'rgba(26,39,51,0.18)',
    good: '#2E7D5B',
    goodSoft: 'rgba(46,125,91,0.10)',
    shadow: '0 1px 2px rgba(26,39,51,0.06)',
    shadowCard: '0 6px 22px rgba(26,39,51,0.07)',
  };
}

function hexA(hex, a) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0, 2), 16), g = parseInt(h.slice(2, 4), 16), b = parseInt(h.slice(4, 6), 16);
  return `rgba(${r},${g},${b},${a})`;
}

// Headline font from tweak
function ppHeadFont(t = {}) {
  const f = t.headFont || 'spectral';
  if (f === 'newsreader') return '"Newsreader", Georgia, serif';
  if (f === 'sf') return '-apple-system, "SF Pro Display", system-ui, sans-serif';
  return '"Spectral", Georgia, serif';
}
const PP_UI = '-apple-system, "SF Pro Text", system-ui, sans-serif';

// ── Seeded speech-like waveform data ─────────────────────────────────────
function ppSeed(str) {
  let h = 2166136261;
  for (let i = 0; i < str.length; i++) { h ^= str.charCodeAt(i); h = Math.imul(h, 16777619); }
  return h >>> 0;
}
function ppBars(seed, n) {
  let s = seed || 1;
  const rnd = () => { s = (Math.imul(s, 1103515245) + 12345) & 0x7fffffff; return s / 0x7fffffff; };
  const out = [];
  // a couple of soft "syllable" envelopes so it reads like speech, not noise
  const peaks = 2 + Math.floor(rnd() * 3);
  const centers = Array.from({ length: peaks }, () => 0.1 + rnd() * 0.8);
  const wid = Array.from({ length: peaks }, () => 0.10 + rnd() * 0.16);
  for (let i = 0; i < n; i++) {
    const x = i / (n - 1);
    let env = 0;
    for (let p = 0; p < peaks; p++) {
      const d = (x - centers[p]) / wid[p];
      env = Math.max(env, Math.exp(-d * d));
    }
    const jitter = 0.45 + rnd() * 0.55;
    out.push(Math.max(0.08, env * jitter));
  }
  return out;
}

// ── Waveform hero ────────────────────────────────────────────────────────
// style: 'bars' | 'line' | 'dots'
function Waveform({
  seed = 'x', played = 0, height = 60, count = 46, gap = 3, barW = 3,
  theme, playedColor, restColor, style = 'bars', radius = 3,
}) {
  const T = theme;
  const pc = playedColor || (T ? T.wavePlayed : '#2C5E8C');
  const rc = restColor || (T ? T.waveRest : 'rgba(0,0,0,0.18)');
  const data = React.useMemo(() => ppBars(typeof seed === 'string' ? ppSeed(seed) : seed, count), [seed, count]);
  const playIdx = played * count;

  if (style === 'line') {
    const W = 300, H = height, mid = H / 2;
    const pts = data.map((v, i) => [ (i / (count - 1)) * W, v ]);
    const top = pts.map(([x, v]) => `${x.toFixed(1)},${(mid - v * mid * 0.92).toFixed(1)}`).join(' ');
    const bot = pts.slice().reverse().map(([x, v]) => `${x.toFixed(1)},${(mid + v * mid * 0.92).toFixed(1)}`).join(' ');
    const clipW = (played * W).toFixed(1);
    const gid = 'wl' + Math.abs(typeof seed === 'string' ? ppSeed(seed) : seed);
    return (
      <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ display: 'block', overflow: 'visible' }}>
        <defs><clipPath id={gid}><rect x="0" y="0" width={clipW} height={H} /></clipPath></defs>
        <polygon points={`${top} ${bot}`} fill={rc} />
        <polygon points={`${top} ${bot}`} fill={pc} clipPath={`url(#${gid})`} />
      </svg>
    );
  }

  return (
    <div style={{ display: 'flex', alignItems: 'center', gap, height, width: '100%' }}>
      {data.map((v, i) => {
        const on = i < playIdx;
        const cur = Math.abs(i - playIdx) < 0.6;
        if (style === 'dots') {
          return <div key={i} style={{
            flex: 1, height: barW * 1.6, borderRadius: 99,
            background: on ? pc : rc, transition: 'background .12s',
          }} />;
        }
        return (
          <div key={i} style={{
            flex: 1, minWidth: 0, height: `${Math.round(v * height)}px`,
            borderRadius: radius, background: cur ? pc : (on ? pc : rc),
            opacity: cur ? 1 : 1, transition: 'background .12s, height .2s',
          }} />
        );
      })}
    </div>
  );
}

// ── Circular voice animation (radial equalizer + pulse rings) ────────────
if (typeof document !== 'undefined' && !document.getElementById('pp-voice-kf')) {
  const s = document.createElement('style');
  s.id = 'pp-voice-kf';
  s.textContent = `
    @keyframes ppVoiceBar { 0%,100% { transform: scaleY(0.32); } 50% { transform: scaleY(1); } }
    @keyframes ppVoiceRing { 0% { transform: scale(0.78); opacity: 0.45; } 100% { transform: scale(1.55); opacity: 0; } }
    /* tap/press feedback — iOS-style squish with springy release */
    .pp-screen button { transition: transform .26s cubic-bezier(.34,1.56,.64,1), filter .22s ease, background .2s ease, border-color .2s ease; will-change: transform; }
    .pp-screen button:active:not(:disabled) { transform: scale(0.96); filter: brightness(0.93); transition: transform .06s ease-out, filter .06s ease-out; }
    .pp-screen button.pp-orb:active:not(:disabled) { transform: scale(0.86); filter: brightness(0.95); }
    .pp-screen button:disabled { transform: none; filter: none; }
    @media (prefers-reduced-motion: reduce) {
      .pp-voice-bar, .pp-voice-ring { animation: none !important; }
      .pp-screen button { transition: none; }
      .pp-screen button:active:not(:disabled) { transform: none; filter: brightness(0.93); }
    }`;
  document.head.appendChild(s);
}

function VoiceOrb({ theme, size = 168, playing = true, onClick, bars = 40 }) {
  const T = theme;
  const core = size * 0.42;           // central play button
  const ringMax = size;               // pulse ring max box
  const barMax = size * 0.13;         // tick length
  const radius = core / 2 + size * 0.06;
  const ticks = Array.from({ length: bars });
  return (
    <div style={{ position: 'relative', width: size, height: size, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
      {/* pulse rings */}
      {[0, 1, 2].map(i => (
        <div key={i} className="pp-voice-ring" style={{
          position: 'absolute', width: ringMax * 0.62, height: ringMax * 0.62, borderRadius: '50%',
          border: `1.5px solid ${T.primary}`,
          animation: playing ? `ppVoiceRing 2.8s ease-out ${i * 0.93}s infinite` : 'none',
          opacity: playing ? undefined : 0,
        }} />
      ))}
      {/* radial equalizer */}
      {ticks.map((_, i) => {
        const angle = (360 / bars) * i;
        const delay = (Math.sin(i * 1.7) * 0.5 + 0.5) * 0.9;
        return (
          <div key={i} style={{ position: 'absolute', inset: 0, transform: `rotate(${angle}deg)`, pointerEvents: 'none' }}>
            <div className="pp-voice-bar" style={{
              position: 'absolute', left: '50%', top: size / 2 - radius - barMax, marginLeft: -1.25,
              width: 2.5, height: barMax, borderRadius: 2,
              background: T.primary, opacity: T.dark ? 0.85 : 0.7,
              transformOrigin: 'center bottom',
              animation: playing ? `ppVoiceBar ${1.1 + (i % 5) * 0.12}s ease-in-out ${delay}s infinite` : 'none',
              transform: playing ? undefined : 'scaleY(0.4)',
            }} />
          </div>
        );
      })}
      {/* soft halo */}
      <div style={{ position: 'absolute', width: core * 1.7, height: core * 1.7, borderRadius: '50%', background: T.primarySoft }} />
      {/* central play button */}
      <button className="pp-orb" onClick={onClick} aria-label={playing ? 'Pause' : 'Play'} style={{
        position: 'relative', width: core, height: core, borderRadius: '50%', border: 'none', cursor: 'pointer',
        background: T.primary, boxShadow: `0 8px 24px ${hexA(T.primary, T.dark ? 0.45 : 0.32)}`,
        display: 'flex', alignItems: 'center', justifyContent: 'center', WebkitTapHighlightColor: 'transparent',
      }}>
        {playing ? (
          <svg width={core * 0.32} height={core * 0.32} viewBox="0 0 24 24" fill={T.onPrimary}><rect x="5" y="3.5" width="5" height="17" rx="1.6" /><rect x="14" y="3.5" width="5" height="17" rx="1.6" /></svg>
        ) : (
          <svg width={core * 0.34} height={core * 0.34} viewBox="0 0 24 24" fill={T.onPrimary} style={{ marginLeft: core * 0.04 }}><path d="M6 4.5v15a1 1 0 0 0 1.5.87l12-7.5a1 1 0 0 0 0-1.74l-12-7.5A1 1 0 0 0 6 4.5z" /></svg>
        )}
      </button>
    </div>
  );
}

// ── Circular play control ────────────────────────────────────────────────
function PlayOrb({ theme, size = 76, playing = false, onClick, label, filled = true }) {
  const T = theme;
  const s = Math.round(size * 1.15); // audio is the hero — keep the play control generous
  return (
    <button className="pp-orb" onClick={onClick} style={{
      width: s, height: s, borderRadius: '50%', border: 'none', cursor: 'pointer',
      background: filled ? T.primary : 'transparent',
      boxShadow: filled ? `0 8px 22px ${hexA(T.primary, T.dark ? 0.4 : 0.28)}` : 'none',
      outline: filled ? 'none' : `1.5px solid ${T.primary}`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      flexShrink: 0,
      WebkitTapHighlightColor: 'transparent',
    }} aria-label={label || 'Play'}>
      {playing ? (
        <svg width={s * 0.34} height={s * 0.34} viewBox="0 0 24 24" fill={filled ? T.onPrimary : T.primary}>
          <rect x="5" y="3.5" width="5" height="17" rx="1.6" /><rect x="14" y="3.5" width="5" height="17" rx="1.6" />
        </svg>
      ) : (
        <svg width={s * 0.36} height={s * 0.36} viewBox="0 0 24 24" fill={filled ? T.onPrimary : T.primary} style={{ marginLeft: s * 0.04 }}>
          <path d="M6 4.5v15a1 1 0 0 0 1.5.87l12-7.5a1 1 0 0 0 0-1.74l-12-7.5A1 1 0 0 0 6 4.5z" />
        </svg>
      )}
    </button>
  );
}

// ── Mic record orb — the "audio out" control of the core loop ───────────
function MicOrb({ theme, size = 76, rec = false, onClick }) {
  const T = theme;
  const REC = '#C0485A';
  return (
    <button className="pp-orb" onClick={onClick} aria-label={rec ? 'Stop recording' : 'Record'} style={{
      position: 'relative', width: size, height: size, borderRadius: '50%', cursor: 'pointer',
      background: rec ? (T.dark ? 'rgba(224,116,138,0.14)' : 'rgba(158,43,58,0.07)') : 'transparent',
      border: `1.5px solid ${rec ? hexA(REC, 0.55) : T.hair}`,
      display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      WebkitTapHighlightColor: 'transparent',
    }}>
      {rec && [0, 1].map(i => (
        <div key={i} className="pp-voice-ring" style={{
          position: 'absolute', width: size, height: size, borderRadius: '50%',
          border: `1.5px solid ${REC}`, animation: `ppVoiceRing 2.4s ease-out ${i * 1.2}s infinite`,
        }} />
      ))}
      {rec
        ? <span style={{ width: Math.round(size * 0.3), height: Math.round(size * 0.3), borderRadius: Math.round(size * 0.11), background: REC }} />
        : <Icon name="mic" size={Math.round(size * 0.36)} color={T.sub} sw={1.8} />}
    </button>
  );
}

// ── Small icon set (stroke) ──────────────────────────────────────────────
function Icon({ name, size = 24, color = 'currentColor', sw = 1.7 }) {
  const p = { fill: 'none', stroke: color, strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const paths = {
    today: <><rect x="3.5" y="4.5" width="17" height="16" rx="3.5" {...p} /><path d="M3.5 9h17M8 2.5v4M16 2.5v4" {...p} /></>,
    listen: <><path d="M4 9v6M8 5.5v13M12 3v18M16 6.5v11M20 9.5v5" {...p} /></>,
    progress: <><path d="M4 20V10M10 20V4M16 20v-8M22 20" {...p} /><path d="M4 20V11M10 20V5M16 20v-7" {...p} /></>,
    mic: <><rect x="9" y="2.5" width="6" height="12" rx="3" {...p} /><path d="M5.5 11.5a6.5 6.5 0 0 0 13 0M12 18v3" {...p} /></>,
    close: <path d="M6 6l12 12M18 6L6 18" {...p} />,
    chevR: <path d="M9 5l7 7-7 7" {...p} />,
    chevD: <path d="M5 9l7 7 7-7" {...p} />,
    text: <><path d="M5 6h14M5 11h14M5 16h9" {...p} /></>,
    check: <path d="M5 12.5l4.5 4.5L19 6.5" {...p} strokeWidth={sw + 0.3} />,
    replay: <><path d="M4 12a8 8 0 1 1 2.3 5.6" {...p} /><path d="M4 20v-5h5" {...p} /></>,
    speaker: <><path d="M4 9.5v5h3.5L13 19V5L7.5 9.5H4z" {...p} /><path d="M16.5 9a4 4 0 0 1 0 6" {...p} /></>,
    ear: <path d="M7 18c-1.5-1.5-2-3-2-6a7 7 0 0 1 14 0c0 2.5-1 3.5-3 4.5s-2.5 1.5-2.5 3a2.5 2.5 0 0 1-4.5 1.5" {...p} />,
    settings: <><circle cx="12" cy="12" r="3" {...p} /><path d="M12 2.5v3M12 18.5v3M21.5 12h-3M5.5 12h-3M18.5 5.5l-2 2M7.5 16.5l-2 2M18.5 18.5l-2-2M7.5 7.5l-2-2" {...p} /></>,
    lock: <><rect x="5.5" y="10.5" width="13" height="9.5" rx="2.8" {...p} /><path d="M8.5 10.5V7.5a3.5 3.5 0 0 1 7 0v3" {...p} /></>,
    unlock: <><rect x="5.5" y="10.5" width="13" height="9.5" rx="2.8" {...p} /><path d="M8.5 10.5V7.5a3.5 3.5 0 0 1 6.8-1.4" {...p} /></>,
    slow: <><path d="M4 16.5a8.5 8.5 0 0 1 16 0" {...p} /><path d="M12 16.5L8 13.5" {...p} /><circle cx="12" cy="16.5" r="1.2" fill={color} stroke="none" /></>,
  };
  return <svg width={size} height={size} viewBox="0 0 24 24" style={{ display: 'block', flexShrink: 0 }}>{paths[name]}</svg>;
}

// ── Speech-speed chip — slow down only, never above 1× ──────────────────
// Cycles 1× → 0.75× → 0.5× → 1×. Tints when slowed so the state is legible.
function SpeedChip({ theme, value = 1, onChange, size = 'md' }) {
  const T = theme;
  const steps = [1, 0.75, 0.5];
  const idx = steps.indexOf(value);
  const next = steps[(idx + 1) % steps.length];
  const slowed = value < 1;
  const sm = size === 'sm';
  return (
    <button onClick={() => onChange && onChange(next)} aria-label={`Speech speed ${value}×, tap to change`} style={{
      display: 'flex', alignItems: 'center', gap: sm ? 5 : 7,
      padding: sm ? '5px 10px' : '8px 14px', borderRadius: 99, cursor: 'pointer',
      background: slowed ? T.primarySoft : 'transparent',
      border: `1.5px solid ${slowed ? hexA(T.primary, 0.45) : T.hair}`,
      color: slowed ? T.primary : T.faint,
      fontFamily: PP_UI, fontSize: sm ? 12 : 13, fontWeight: 600,
      fontVariantNumeric: 'tabular-nums', WebkitTapHighlightColor: 'transparent',
      transition: 'background .2s, border-color .2s, color .2s',
    }}>
      <Icon name="slow" size={sm ? 13 : 15} color={slowed ? T.primary : T.faint} sw={1.8} />
      {value === 1 ? '1×' : value === 0.75 ? '0.75×' : '0.5×'}
    </button>
  );
}

// ── Lielvārde-style folk seam (subtle, optional) ─────────────────────────
function FolkSeam({ color, w = 220, h = 14, opacity = 0.5 }) {
  // a quiet geometric Baltic band — diamonds + verticals, drawn as detail
  const unit = 16; const n = Math.ceil(w / unit);
  return (
    <svg width={w} height={h} viewBox={`0 0 ${n * unit} 16`} style={{ opacity, display: 'block' }} preserveAspectRatio="xMidYMid meet">
      {Array.from({ length: n }).map((_, i) => {
        const x = i * unit + unit / 2;
        return (
          <g key={i} stroke={color} strokeWidth="1.1" fill="none">
            <path d={`M${x - 5} 8 L${x} 3 L${x + 5} 8 L${x} 13 Z`} />
            <path d={`M${x} 1 V3 M${x} 13 V15`} />
          </g>
        );
      })}
    </svg>
  );
}

// ── Quiet glass tab bar (Today / Listen / Progress) ──────────────────────
function TabBar({ theme, active = 'today' }) {
  const T = theme;
  const tabs = [
    { id: 'today', label: 'Today', icon: 'today' },
    { id: 'listen', label: 'Listen', icon: 'listen' },
    { id: 'progress', label: 'Progress', icon: 'progress' },
  ];
  return (
    <div style={{
      position: 'absolute', left: 0, right: 0, bottom: 0, paddingBottom: 22, paddingTop: 10,
      display: 'flex', justifyContent: 'center', gap: 4, zIndex: 30,
      background: `linear-gradient(to top, ${T.bg} 58%, ${hexA(T.dark ? '#0E1318' : '#F4F2ED', 0)})`,
    }}>
      {tabs.map(tb => {
        const on = tb.id === active;
        return (
          <div key={tb.id} style={{
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
            padding: '4px 22px', color: on ? T.primary : T.faint,
          }}>
            <Icon name={tb.icon} size={24} color={on ? T.primary : T.faint} sw={on ? 1.9 : 1.6} />
            <span style={{ fontFamily: PP_UI, fontSize: 10.5, fontWeight: on ? 600 : 500, letterSpacing: 0.1 }}>{tb.label}</span>
          </div>
        );
      })}
    </div>
  );
}

// ── Screen scaffold: fills the 402×874 device content area ───────────────
function Screen({ theme, children, pad = 24, style = {} }) {
  const T = theme;
  return (
    <div className="pp-screen" style={{
      position: 'absolute', inset: 0, background: T.bg, color: T.ink,
      fontFamily: PP_UI, overflow: 'hidden', display: 'flex', flexDirection: 'column',
      ...style,
    }}>
      <div style={{ flex: 1, minHeight: 0, padding: `0 ${pad}px`, display: 'flex', flexDirection: 'column' }}>
        {children}
      </div>
    </div>
  );
}

// Session top bar: close + progress dots (for immersive in-session screens)
function SessionTop({ theme, step = 1, total = 12, onClose }) {
  const T = theme;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingTop: 66, paddingBottom: 6 }}>
      <button onClick={onClose} style={{
        width: 32, height: 32, borderRadius: '50%', border: 'none', cursor: 'pointer',
        background: T.dark ? 'rgba(255,255,255,0.06)' : 'rgba(26,39,51,0.05)',
        display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      }}><Icon name="close" size={17} color={T.sub} /></button>
      <div style={{ flex: 1, height: 4, borderRadius: 99, background: T.dark ? 'rgba(255,255,255,0.09)' : 'rgba(26,39,51,0.08)', overflow: 'hidden' }}>
        <div style={{ width: `${(step / total) * 100}%`, height: '100%', background: T.primary, borderRadius: 99, transition: 'width .3s' }} />
      </div>
      <span style={{ fontFamily: PP_UI, fontSize: 13, fontWeight: 600, color: T.faint, minWidth: 38, textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>{step}/{total}</span>
    </div>
  );
}

Object.assign(window, {
  PP_ACCENTS, ppTheme, hexA, ppHeadFont, PP_UI, ppSeed, ppBars,
  Waveform, VoiceOrb, PlayOrb, MicOrb, SpeedChip, Icon, FolkSeam, TabBar, Screen, SessionTop,
});
