/* Vooice — shared visual primitives.
   Style language: bone paper, ink line-art, signal-orange, sage-connected.
   Metaphor: the call as a physical object. Type as architecture.
*/

const VC_TOKENS = {
  paper: '#F4EFE6',
  paper2: '#ECE5D6',
  paper3: '#E2D9C5',
  ink: '#0E0E0F',
  ink2: '#2A2724',
  ink3: '#6A655C',
  line: '#1B1A18',
  lineSoft: 'rgba(14,14,15,0.10)',
  signal: '#F04E23',
  signalSoft: '#FCE3D8',
  sage: '#7A8A6E',
  sageSoft: '#DDE3D2',
  butter: '#E8C36A',
};

// ── VLogo ─ logo mark with variants (controlled by Tweak: logoMark) ──────────
function VLogo({ size = 22, color = '#0E0E0F', dot = '#F04E23', variant }) {
  const v = variant || (window.__vcLogoMark || 'halfdisc');
  if (v === 'wordmark') return null; // wordmark-only mode: no glyph
  if (v === 'phone') {
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" style={{ display:'inline-block', verticalAlign:'middle' }}>
        <circle cx="12" cy="12" r="10.5" fill={color} />
        <path d="M8.2 8.2c0-.7.55-1.2 1.2-1.2h1.5c.5 0 .96.36 1.06.86l.34 1.7c.08.4-.1.8-.5 1.04l-.7.42c.6 1.3 1.6 2.3 2.9 2.9l.42-.7c.24-.4.64-.58 1.04-.5l1.7.34c.5.1.86.56.86 1.06v1.5c0 .65-.5 1.2-1.2 1.2-4.6.05-9.4-4.75-9.62-9.62Z" fill={dot}/>
      </svg>
    );
  }
  if (v === 'sound') {
    // concentric arcs — a sound emanating
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" style={{ display:'inline-block', verticalAlign:'middle' }}>
        <circle cx="9" cy="12" r="2.4" fill={dot}/>
        <path d="M13 8.5a4.5 4.5 0 010 7" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round"/>
        <path d="M16 5.5a8 8 0 010 13" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round"/>
        <path d="M19 2.5a11.5 11.5 0 010 19" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" opacity="0.4"/>
      </svg>
    );
  }
  if (v === 'aperture') {
    // V-as-aperture: triangle nesting circle, dot bottom
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" style={{ display:'inline-block', verticalAlign:'middle' }}>
        <circle cx="12" cy="12" r="10.5" fill="none" stroke={color} strokeWidth="1.5"/>
        <path d="M4 6 L20 6 L12 20 Z" fill={color}/>
        <circle cx="12" cy="14.5" r="2" fill={dot}/>
      </svg>
    );
  }
  // default — halfdisc
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" style={{ display:'inline-block', verticalAlign:'middle' }}>
      <circle cx="12" cy="12" r="10.5" fill="none" stroke={color} strokeWidth="1.5" />
      <path d="M 12 1.5 A 10.5 10.5 0 0 0 12 22.5 Z" fill={color} />
      <circle cx="12" cy="12" r="2.2" fill={dot} />
    </svg>
  );
}

// ── Wordmark with mark ────────────────────────────────────────────────────────
function VWordmark({ size = 16, color = '#0E0E0F', dot = '#F04E23' }) {
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: size * 0.4,
      fontFamily: "'Inter Tight', sans-serif",
      fontWeight: 700, fontSize: size, letterSpacing: '-0.03em', color,
    }}>
      <VLogo size={size * 1.15} color={color} dot={dot} />
      <span>vooice</span>
    </span>
  );
}

// ── Mono label / system text ─────────────────────────────────────────────────
function Mono({ children, color, size = 10, weight = 500, style = {}, upper = true, className }) {
  return (
    <span className={className} style={{
      fontFamily: "'JetBrains Mono', monospace",
      fontSize: size, fontWeight: weight,
      letterSpacing: '0.08em',
      textTransform: upper ? 'uppercase' : 'none',
      color: color || VC_TOKENS.ink3,
      ...style,
    }}>{children}</span>
  );
}

// ── Tag / pill ───────────────────────────────────────────────────────────────
function Tag({ children, tone = 'ink', style = {}, className }) {
  const tones = {
    ink:    { bg: 'transparent', fg: VC_TOKENS.ink, bd: VC_TOKENS.ink },
    paper:  { bg: VC_TOKENS.paper2, fg: VC_TOKENS.ink, bd: 'transparent' },
    signal: { bg: VC_TOKENS.signal, fg: VC_TOKENS.paper, bd: 'transparent' },
    signalSoft: { bg: VC_TOKENS.signalSoft, fg: VC_TOKENS.signal, bd: 'transparent' },
    sage:   { bg: VC_TOKENS.sage, fg: VC_TOKENS.paper, bd: 'transparent' },
    sageSoft: { bg: VC_TOKENS.sageSoft, fg: '#3F4E33', bd: 'transparent' },
    butter: { bg: VC_TOKENS.butter, fg: VC_TOKENS.ink, bd: 'transparent' },
    ghost:  { bg: 'transparent', fg: VC_TOKENS.ink3, bd: VC_TOKENS.lineSoft },
  };
  const t = tones[tone] || tones.ink;
  return (
    <span className={className} style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      fontFamily: "'JetBrains Mono', monospace",
      fontSize: 10, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase',
      padding: '4px 8px', borderRadius: 2,
      background: t.bg, color: t.fg,
      border: `1px solid ${t.bd}`,
      ...style,
    }}>{children}</span>
  );
}

// ── Live waveform — physical "voice as architecture" ─────────────────────────
// renders a series of vertical bars whose heights breathe according to phase + a seeded amplitude.
function Waveform({
  bars = 64, height = 80, color = VC_TOKENS.ink, accent = VC_TOKENS.signal,
  active = true, speaker = 'vooice', // 'vooice' | 'callee' | 'silent'
  width = '100%', barWidth = 3, gap = 2, seed = 1,
}) {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    if (!active) return;
    let raf;
    const tick = () => { setT(p => p + 0.06); raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [active]);

  const total = bars;
  const items = [];
  for (let i = 0; i < total; i++) {
    // pseudo-random per-bar amplitude + phase, modulated by speaker
    const r = Math.abs(Math.sin((i + 1) * 12.9898 * seed) * 43758.5453) % 1;
    const phase = i * 0.18 + r * 6.28;
    let amp = (Math.sin(t + phase) + 1) / 2;        // 0..1
    amp = amp * (0.5 + r * 0.6);
    if (speaker === 'silent') amp *= 0.05;
    if (speaker === 'callee') amp *= 0.55;
    const h = Math.max(2, amp * height);
    const isAccent = speaker === 'vooice' && (i % 7 === 0);
    items.push(
      <div key={i} style={{
        width: barWidth, height: h, borderRadius: barWidth/2,
        background: isAccent ? accent : color,
        opacity: speaker === 'silent' ? 0.25 : 1,
        transition: 'height 60ms linear',
      }} />
    );
  }
  return (
    <div style={{
      width, height, display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      gap,
    }}>
      {items}
    </div>
  );
}

// ── Concentric ring — "ringing" indicator ────────────────────────────────────
function RingingRing({ size = 24, color = '#F04E23' }) {
  return (
    <span style={{
      position: 'relative', width: size, height: size, display: 'inline-block',
    }}>
      <span style={{
        position: 'absolute', inset: 0, borderRadius: '50%',
        border: `1.5px solid ${color}`,
        animation: 'vc-ping 1.6s cubic-bezier(0,0,.2,1) infinite',
      }} />
      <span style={{
        position: 'absolute', inset: '30%', borderRadius: '50%',
        background: color,
      }} />
      <style>{`
        @keyframes vc-ping {
          0%   { transform: scale(0.4); opacity: 1;   }
          80%  { transform: scale(1.4); opacity: 0;   }
          100% { transform: scale(1.4); opacity: 0;   }
        }
        @keyframes vc-blink { 0%, 60% { opacity: 1; } 80%, 100% { opacity: 0; } }
        @keyframes vc-cursor { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }
      `}</style>
    </span>
  );
}

// ── Stamp — letterpress-style accent box ─────────────────────────────────────
function Stamp({ children, color = '#F04E23', style = {} }) {
  return (
    <span style={{
      display: 'inline-block', padding: '6px 10px',
      border: `1.5px solid ${color}`, color,
      fontFamily: "'JetBrains Mono', monospace",
      fontSize: 10, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase',
      transform: 'rotate(-1.5deg)',
      ...style,
    }}>{children}</span>
  );
}

// ── Hairline label row — "FIELD · value" key-value, used a lot ───────────────
function FieldRow({ label, children, align = 'space-between' }) {
  return (
    <div style={{
      display: 'flex', justifyContent: align, alignItems: 'baseline',
      padding: '10px 0', borderBottom: `1px solid ${VC_TOKENS.lineSoft}`,
      gap: 16,
    }}>
      <Mono>{label}</Mono>
      <span style={{ fontSize: 14, color: VC_TOKENS.ink, fontWeight: 500 }}>{children}</span>
    </div>
  );
}

// ── Tape strip — used as data ribbons / call timeline ────────────────────────
function TapeStrip({ ticks = 40, color = VC_TOKENS.ink, height = 28, label }) {
  return (
    <div style={{
      display:'flex', alignItems:'center', gap: 10,
      borderTop: `1px solid ${color}`, borderBottom: `1px solid ${color}`,
      padding: '4px 0', height,
    }}>
      {label && <Mono color={color} style={{ paddingLeft: 8 }}>{label}</Mono>}
      <div style={{ flex: 1, display:'flex', justifyContent:'space-between' }}>
        {Array.from({length: ticks}).map((_,i) => (
          <div key={i} style={{
            width: 1, height: i % 5 === 0 ? height - 12 : height - 18,
            background: color, opacity: i % 5 === 0 ? 1 : 0.5,
          }} />
        ))}
      </div>
    </div>
  );
}

// ── Card surface — universal panel ───────────────────────────────────────────
function Surface({ children, padding = 24, bg = VC_TOKENS.paper, bordered = true, style = {} }) {
  return (
    <div style={{
      background: bg,
      border: bordered ? `1px solid ${VC_TOKENS.line}` : 'none',
      padding,
      ...style,
    }}>{children}</div>
  );
}

// ── Section header ───────────────────────────────────────────────────────────
function SectionHead({ eyebrow, title, action }) {
  return (
    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-end', marginBottom: 16 }}>
      <div>
        {eyebrow && <Mono color={VC_TOKENS.ink}>{eyebrow}</Mono>}
        <div style={{
          fontFamily: "'Inter Tight', sans-serif",
          fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em',
          marginTop: 4,
        }}>{title}</div>
      </div>
      {action}
    </div>
  );
}

// ── Avatar — typographic, no images ──────────────────────────────────────────
function Avatar({ name, size = 36, bg = VC_TOKENS.ink, fg = VC_TOKENS.paper }) {
  const initials = (name || '?').split(' ').slice(0,2).map(w => w[0]).join('').toUpperCase();
  return (
    <span style={{
      width: size, height: size, borderRadius: '50%',
      background: bg, color: fg, display:'inline-flex',
      alignItems:'center', justifyContent:'center',
      fontFamily: "'Inter Tight', sans-serif", fontWeight: 700,
      fontSize: size * 0.36, letterSpacing: '0.02em',
      flexShrink: 0,
    }}>{initials}</span>
  );
}

// ── Big number metric ────────────────────────────────────────────────────────
function Metric({ value, unit, label }) {
  return (
    <div>
      <div style={{ display:'flex', alignItems:'baseline', gap: 4 }}>
        <span style={{
          fontFamily: "'Inter Tight', sans-serif",
          fontSize: 44, fontWeight: 700, letterSpacing: '-0.04em', lineHeight: 1,
        }}>{value}</span>
        {unit && <Mono color={VC_TOKENS.ink3} size={11}>{unit}</Mono>}
      </div>
      <Mono color={VC_TOKENS.ink3} style={{ marginTop: 8, display:'inline-block' }}>{label}</Mono>
    </div>
  );
}

// ── Phone glyph (thin line-art only — no emoji, no glowing icons) ────────────
function PhoneGlyph({ size = 14, color = 'currentColor', strokeWidth = 1.5 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 3.5C3 2.67 3.67 2 4.5 2h1.7c.6 0 1.13.42 1.27 1L8 5.2c.1.5-.13 1-.6 1.3l-.9.55c.74 1.6 2 2.86 3.6 3.6l.55-.9c.3-.47.8-.7 1.3-.6l2.2.53c.58.14 1 .67 1 1.27v1.7c0 .83-.67 1.5-1.5 1.5C7.6 14.15 1.85 8.4 3 3.5Z"/>
    </svg>
  );
}

function ArrowGlyph({ size = 14, dir = 'right', color = 'currentColor' }) {
  const rot = { right: 0, left: 180, up: -90, down: 90 }[dir] || 0;
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" style={{ transform: `rotate(${rot}deg)` }} fill="none" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 8h10M9 4l4 4-4 4"/>
    </svg>
  );
}

// ── Striped placeholder for imagery (we don't have any) ──────────────────────
function StripedPlaceholder({ width = '100%', height = 200, label, color = VC_TOKENS.ink, bg = VC_TOKENS.paper2 }) {
  const stripe = `repeating-linear-gradient(135deg, ${bg} 0 12px, ${VC_TOKENS.paper3} 12px 13px)`;
  return (
    <div style={{
      width, height, background: stripe,
      border: `1px solid ${color}`,
      display:'flex', alignItems:'center', justifyContent:'center',
      position:'relative',
    }}>
      <Mono color={color}>{label}</Mono>
    </div>
  );
}

// Expose to other Babel scripts
// ── AppHeader ──────────────────────────────────────────────────────────────
// Unified top nav for in-app screens. Use across Dashboard, OutboundCall,
// CallDetail, ContactsMemory, Reminders, AuditLog, Pricing.
// `current` highlights the active route key. `dark` flips palette for dark
// canvases (Reminders).
const APP_NAV = [
  { l: 'Home',      k: 'home' },
  { l: 'Calls',     k: 'outbound-call' },
  { l: 'Reminders', k: 'reminders' },
  { l: 'Memory',    k: 'contacts-memory' },
  { l: 'Audit',     k: 'audit' },
];
const APP_SUBNAV = [
  { l: 'Pricing',  k: 'pricing' },
  { l: 'Landing',  k: 'marketing-hero' },
];

function AppHeader({ onNavigate, current, crumbs = [], dark = false, status }) {
  const fg = dark ? VC_TOKENS.paper : VC_TOKENS.ink;
  const fgMute = dark ? '#807a72' : VC_TOKENS.ink3;
  const bg = dark ? VC_TOKENS.ink : VC_TOKENS.paper;
  const lineCol = dark ? '#2a2724' : VC_TOKENS.line;
  const lineSoft = dark ? '#2a2724' : VC_TOKENS.lineSoft;

  // Hide the inline nav and collapse it under a hamburger on phone-sized
  // viewports. Using matchMedia keeps the header self-contained — no need to
  // thread vw through every screen.
  const [isMobile, setIsMobile] = React.useState(
    typeof window !== 'undefined' && window.matchMedia('(max-width: 720px)').matches
  );
  const [open, setOpen] = React.useState(false);
  React.useEffect(() => {
    const mq = window.matchMedia('(max-width: 720px)');
    const update = () => setIsMobile(mq.matches);
    if (mq.addEventListener) mq.addEventListener('change', update);
    else mq.addListener(update);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', update);
      else mq.removeListener(update);
    };
  }, []);
  React.useEffect(() => { if (!isMobile) setOpen(false); }, [isMobile]);

  const go = (k) => { setOpen(false); onNavigate && onNavigate(k); };

  return (
    <div style={{ gridColumn: '1 / -1', position: 'relative' }}>
      <div className="vc-appheader" style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '0 28px', gap: 16, flexWrap: 'wrap',
        borderBottom: `1px solid ${lineCol}`, background: bg, color: fg,
        minHeight: 64,
      }}>
        <div style={{ display:'flex', alignItems:'center', gap: 14, flexWrap: 'wrap' }}>
          <span onClick={() => go('home')} style={{ cursor:'pointer' }}>
            <VWordmark size={15} color={fg} />
          </span>
          {!isMobile && (
            <>
              <span style={{ width:1, height:16, background: lineSoft }} />
              <nav className="vc-appnav" style={{ display:'flex', alignItems:'center', gap: 14, flexWrap: 'wrap' }}>
                {APP_NAV.map(it => {
                  const active = it.k === current;
                  return (
                    <span key={it.k} onClick={() => go(it.k)} style={{ cursor:'pointer' }}>
                      <Mono color={active ? fg : fgMute}>{it.l.toUpperCase()}</Mono>
                    </span>
                  );
                })}
              </nav>
              {crumbs.length > 0 && (
                <>
                  <span style={{ width:1, height:16, background: lineSoft }} className="vc-hide-mobile" />
                  <div className="vc-hide-mobile" style={{ display:'flex', alignItems:'center', gap: 6 }}>
                    {crumbs.map((c, i) => {
                      const last = i === crumbs.length - 1;
                      const item = typeof c === 'string' ? { label: c } : c;
                      return (
                        <React.Fragment key={i}>
                          <span
                            onClick={() => item.k && go(item.k)}
                            style={{ cursor: item.k ? 'pointer' : 'default' }}
                          >
                            <Mono color={last ? fg : fgMute}>{item.label}</Mono>
                          </span>
                          {!last && <Mono color={fgMute}>/</Mono>}
                        </React.Fragment>
                      );
                    })}
                  </div>
                </>
              )}
            </>
          )}
        </div>
        <div style={{ display:'flex', alignItems:'center', gap: 14, flexWrap:'wrap' }}>
          {!isMobile && (
            <>
              <div className="vc-hide-mobile" style={{ display:'flex', gap: 14 }}>
                {APP_SUBNAV.map(it => (
                  <span key={it.k} onClick={() => go(it.k)} style={{ cursor:'pointer' }}>
                    <Mono color={fgMute}>{it.l.toUpperCase()}</Mono>
                  </span>
                ))}
              </div>
              <span className="vc-hide-mobile" style={{ width:1, height:16, background: lineSoft }} />
              {status && (
                <Tag tone={dark ? 'sage' : 'sageSoft'} className="vc-hide-mobile">{status}</Tag>
              )}
              <Mono color={fgMute} className="vc-hide-mobile">+1 (415) 555‑0188</Mono>
            </>
          )}
          <Avatar name="Jordan Reyes" size={28} bg={dark ? VC_TOKENS.paper : VC_TOKENS.ink} fg={dark ? VC_TOKENS.ink : VC_TOKENS.paper} />
          {isMobile && (
            <button
              onClick={() => setOpen(o => !o)}
              aria-label={open ? 'Close menu' : 'Open menu'}
              aria-expanded={open}
              style={{
                background: 'transparent', border: `1px solid ${lineCol}`, color: fg,
                width: 36, height: 36, padding: 0, cursor: 'pointer',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 16, lineHeight: 1, fontFamily: 'inherit',
              }}
            >{open ? '✕' : '☰'}</button>
          )}
        </div>
      </div>
      {isMobile && open && (
        <div role="menu" style={{
          position: 'absolute', top: '100%', left: 0, right: 0,
          background: bg, color: fg,
          borderBottom: `1px solid ${lineCol}`,
          zIndex: 30, padding: '4px 28px 16px',
          boxShadow: '0 14px 28px rgba(0,0,0,0.18)',
        }}>
          {[...APP_NAV, ...APP_SUBNAV].map(it => {
            const active = it.k === current;
            return (
              <div key={it.k} onClick={() => go(it.k)} role="menuitem" style={{
                padding: '14px 0', borderBottom: `1px solid ${lineSoft}`,
                cursor: 'pointer', display: 'flex',
                justifyContent: 'space-between', alignItems: 'center',
              }}>
                <Mono color={active ? fg : fgMute}>{it.l.toUpperCase()}</Mono>
                {active && <span style={{
                  width: 6, height: 6, borderRadius: '50%', background: VC_TOKENS.signal,
                }} />}
              </div>
            );
          })}
          {crumbs.length > 0 && (
            <div style={{
              marginTop: 14, paddingTop: 14, borderTop: `1px solid ${lineSoft}`,
              display: 'flex', flexWrap: 'wrap', gap: 6,
            }}>
              {crumbs.map((c, i) => {
                const last = i === crumbs.length - 1;
                const item = typeof c === 'string' ? { label: c } : c;
                return (
                  <React.Fragment key={i}>
                    <span onClick={() => item.k && go(item.k)} style={{ cursor: item.k ? 'pointer' : 'default' }}>
                      <Mono color={last ? fg : fgMute}>{item.label}</Mono>
                    </span>
                    {!last && <Mono color={fgMute}>/</Mono>}
                  </React.Fragment>
                );
              })}
            </div>
          )}
          {status && <div style={{ marginTop: 14 }}><Tag tone={dark ? 'sage' : 'sageSoft'}>{status}</Tag></div>}
        </div>
      )}
    </div>
  );
}

// Expose to other Babel scripts
Object.assign(window, {
  VC_TOKENS, VLogo, VWordmark, Mono, Tag, Waveform, RingingRing, Stamp,
  FieldRow, TapeStrip, Surface, SectionHead, Avatar, Metric, PhoneGlyph, ArrowGlyph,
  StripedPlaceholder, AppHeader,
});
