/* components.jsx — shared UI primitives + helpers. Exports to window. */
const { useState, useEffect, useRef, useMemo } = React;

// ---- helpers ----
function fmtPrice(n, cur) {
  const sym = cur || '€';
  const v = n.toFixed(2).replace('.', ',');
  return `${sym} ${v}`;
}
function makeT(lang) {
  const dict = I18N[lang] || I18N.en;
  return (k) => dict[k] || I18N.en[k] || k;
}
function loc(v, lang) {
  if (v && typeof v === 'object') return v[lang] || v.en;
  return v;
}

// ---- minimal line icons (only simple UI glyphs) ----
function Icon({ name, size = 22, stroke = 2 }) {
  const p = {
    close: 'M6 6l12 12M18 6L6 18',
    chev: 'M9 6l6 6-6 6',
    chevL: 'M15 6l-6 6 6 6',
    chevDown: 'M6 9l6 6 6-6',
    help: 'M9 9a3 3 0 1 1 4 2.8c-.9.5-1 1-1 2M12 17h.01',
    globe: 'M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18M3 12h18M12 3c2.5 2.4 2.5 15.6 0 18M12 3C9.5 5.4 9.5 18.6 12 21',
    camera: 'M3 8a2 2 0 0 1 2-2h2l1.5-2h7L19 6h0a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z',
    lock: 'M7 10V8a5 5 0 0 1 10 0v2M5 10h14v9a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1z',
    check: 'M4 12l5 5L20 6',
    refresh: 'M4 12a8 8 0 0 1 13.7-5.6L20 8M20 4v4h-4M20 12a8 8 0 0 1-13.7 5.6L4 16M4 20v-4h4',
    power: 'M12 4v8M7 7a7 7 0 1 0 10 0',
    light: 'M9 18h6M10 21h4M12 3a6 6 0 0 0-4 10.5c.6.6 1 1.4 1 2.5h6c0-1.1.4-1.9 1-2.5A6 6 0 0 0 12 3z',
    grid: 'M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z',
    cog: 'M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6M19 12a7 7 0 0 0-.1-1l2-1.5-2-3.4-2.3 1a7 7 0 0 0-1.7-1l-.3-2.6h-4l-.3 2.6a7 7 0 0 0-1.7 1l-2.3-1-2 3.4 2 1.5a7 7 0 0 0 0 2l-2 1.5 2 3.4 2.3-1a7 7 0 0 0 1.7 1l.3 2.6h4l.3-2.6a7 7 0 0 0 1.7-1l2.3 1 2-3.4-2-1.5c.1-.3.1-.6.1-1z',
    home: 'M4 11l8-7 8 7M6 10v9h12v-9',
    card: 'M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zM3 10h18',
    qr: 'M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h3v3h-3zM19 14v6M14 19h6',
    info: 'M12 8h.01M11 12h1v5h1',
    arrowR: 'M5 12h14M13 6l6 6-6 6',
    plus: 'M12 5v14M5 12h14',
    wifi: 'M2 8.5a16 16 0 0 1 20 0M5 12a11 11 0 0 1 14 0M8.5 15.5a6 6 0 0 1 7 0M12 19h.01',
  }[name] || '';
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round">
      <path d={p} />
    </svg>
  );
}

// ---- wifi bars ----
function WifiBars({ level = 3 }) {
  return (
    <span className="wifi">
      {[1, 2, 3, 4].map((i) => <i key={i} className={i <= level ? 'on' : ''} />)}
    </span>
  );
}

// ---- deterministic QR-like placeholder ----
function QR({ cells = 25 }) {
  const grid = useMemo(() => {
    let s = 1337; const rnd = () => { s = (s * 1103515245 + 12345) & 0x7fffffff; return (s / 0x7fffffff); };
    const g = [];
    for (let y = 0; y < cells; y++) { const row = []; for (let x = 0; x < cells; x++) row.push(rnd() > 0.5); g.push(row); }
    // finder patterns
    const stamp = (ox, oy) => { for (let y = 0; y < 7; y++) for (let x = 0; x < 7; x++) {
      const edge = x === 0 || y === 0 || x === 6 || y === 6; const core = x >= 2 && x <= 4 && y >= 2 && y <= 4;
      g[oy + y][ox + x] = edge || core;
    } };
    const clear = (ox, oy) => { for (let y = -1; y < 8; y++) for (let x = -1; x < 8; x++) { const yy = oy + y, xx = ox + x; if (g[yy] && g[yy][xx] !== undefined && (x < 0 || y < 0 || x > 6 || y > 6)) g[yy][xx] = false; } };
    [[0, 0], [cells - 7, 0], [0, cells - 7]].forEach(([x, y]) => { clear(x, y); stamp(x, y); });
    return g;
  }, [cells]);
  return (
    <svg viewBox={`0 0 ${cells} ${cells}`} shapeRendering="crispEdges">
      {grid.map((row, y) => row.map((on, x) => on ? <rect key={x + '-' + y} x={x} y={y} width={1.04} height={1.04} fill="#0a0a0a" /> : null))}
    </svg>
  );
}

// ---- product image placeholder ----
function ProductImg({ label, className }) {
  return (
    <div className={'imgph ' + (className || '')}>
      {label ? <span>{label}</span> : null}
    </div>
  );
}

// ---- top bar ----
function TopBar({ ctx, onLogo, onHelp, onLang, showSession, sessionLeft, right }) {
  const { t, lang } = ctx;
  const curLang = LANGS.find((l) => l.code === lang) || LANGS[0];
  return (
    <div className="topbar">
      <button className="brand" onClick={onLogo} aria-label="brand">
        <div className="brand-mark">V</div>
        <div className="brand-name">VAPR<span className="thin">.go</span></div>
      </button>
      <div className="topbar-spacer" />
      {right}
      {showSession && (
        <span className="session">{t('session_end')} <b>{sessionLeft}s</b></span>
      )}
      <div className="statchip"><span className="dot" /><WifiBars level={4} /></div>
      {onLang && (
        <button className="iconbtn" onClick={onLang} aria-label="language" title={t('langname')}>
          <span style={{ fontSize: 18 }}>{curLang.flag}</span>
        </button>
      )}
      {onHelp && <button className="iconbtn" onClick={onHelp} aria-label="help"><Icon name="help" /></button>}
    </div>
  );
}

// ---- step dots ----
function StepDots({ total, current }) {
  return (
    <div className="steps">
      {Array.from({ length: total }).map((_, i) => (
        <div key={i} className={'s ' + (i < current ? 'done' : i === current ? 'active' : '')} />
      ))}
    </div>
  );
}

// ---- dialog ----
function Dialog({ title, onClose, children, footer }) {
  return (
    <div className="overlay" onClick={onClose}>
      <div className="dialog" onClick={(e) => e.stopPropagation()}>
        <div className="dhead">
          <h3>{title}</h3>
          <button className="iconbtn" onClick={onClose}><Icon name="close" size={20} /></button>
        </div>
        <div className="dbody">{children}</div>
        {footer && <div className="dbody" style={{ paddingTop: 0 }}>{footer}</div>}
      </div>
    </div>
  );
}

// ---- language dialog ----
function LangDialog({ ctx, onPick, onClose }) {
  const { t, lang } = ctx;
  return (
    <Dialog title={t('langname')} onClose={onClose}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        {LANGS.map((l) => (
          <button key={l.code} className={'choice'} style={{ padding: '16px 18px', borderColor: l.code === lang ? 'var(--accent)' : undefined }} onClick={() => onPick(l.code)}>
            <span style={{ fontSize: 28 }}>{l.flag}</span>
            <span className="ct">{l.label}</span>
            {l.code === lang && <span className="chev" style={{ color: 'var(--accent)' }}><Icon name="check" size={20} /></span>}
          </button>
        ))}
      </div>
    </Dialog>
  );
}

// ---- help dialog ----
function HelpDialog({ ctx, onClose }) {
  const { t } = ctx;
  return (
    <Dialog title={t('help_title')} onClose={onClose}>
      <div className="row" style={{ alignItems: 'flex-start', gap: 22 }}>
        <div style={{ flex: 1 }}>
          <p className="muted" style={{ fontSize: 15, lineHeight: 1.6 }}>{t('help_body')}</p>
          <div style={{ marginTop: 18 }}>
            <div className="eyebrow">{t('device_id')}</div>
            <div className="mono" style={{ fontSize: 15, marginTop: 6 }}>VND-ESPA-0427-7731</div>
          </div>
          <div style={{ marginTop: 16 }}>
            <div className="eyebrow">SUPPORT</div>
            <div className="mono" style={{ fontSize: 18, marginTop: 6 }}>+34 900 802 113</div>
          </div>
        </div>
        <div className="qr-box" style={{ width: 130, height: 130, padding: 12 }}><QR cells={21} /></div>
      </div>
    </Dialog>
  );
}

// ---- hardware guide: mirrors the device's bottom panel (PUSH flap + camera/card window) ----
function HardwareGuide({ active, label, opening }) {
  return (
    <div className="hwguide">
      {label && <div className="hwg-cap">{label}</div>}
      <div className="hwpanel">
        <div className={'hw-push' + (active === 'push' ? ' on' : '') + (opening ? ' opening' : '')}>
          {active === 'push' && <span className="hw-arrow">↓</span>}
          <span className="hw-door"><span className="hw-pushtxt">PUSH</span></span>
        </div>
        <div className="hw-window">
          <div className={'hw-cam' + (active === 'camera' ? ' on' : '')}>
            {active === 'camera' && <span className="hw-arrow">↓</span>}
            <span className="hw-lens" />
          </div>
          <div className={'hw-card' + (active === 'card' ? ' on' : '')}>
            {active === 'card' && <span className="hw-arrow">↓</span>}
            <svg className="hw-nfc" viewBox="0 0 48 48" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round">
              <path d="M17 15a15 15 0 0 1 0 18" /><path d="M24 10a24 24 0 0 1 0 28" /><path d="M31 6a32 32 0 0 1 0 36" />
            </svg>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  fmtPrice, makeT, loc, Icon, WifiBars, QR, ProductImg, TopBar, StepDots, Dialog, LangDialog, HelpDialog, HardwareGuide,
});
