// Shared components: wordmark, nav, buttons, schematic, countdown

function Wordmark({ size = 22 }) {
  // Original "V" with a diagonal inner notch — not a lightning bolt
  const h = size;
  const w = size * 0.92;
  return (
    <span className="inline-flex items-center gap-[0.4em] wordmark" style={{ fontSize: size }}>
      <svg viewBox="0 0 32 32" width={w} height={h} aria-hidden="true" style={{ display: 'block' }}>
        {/* V with an angled inner cut — top-right terminal is trimmed flat, suggests a bus-bar connector */}
        <path
          d="M 3 4 L 9 4 L 16 22.5 L 23 4 L 29 4 L 26.8 4 L 19 26 L 13 26 L 5.2 4 Z"
          fill="currentColor"
        />
        {/* inner accent slot — the 'terminal cut' on the V's right arm */}
        <rect x="20.2" y="8.5" width="4.6" height="1.6" fill="var(--bg)" />
      </svg>
      <span style={{ letterSpacing: '-0.035em' }}>
        <span>V</span><span>o</span><span>l</span><span>t</span><span style={{ letterSpacing: '-0.04em' }}>a</span><span>n</span>
      </span>
    </span>
  );
}

function Kicker({ children, className = "" }) {
  return (
    <div className={`mono text-[11px] uppercase tracking-[0.18em] flex items-center gap-2 ${className}`}
         style={{ color: 'var(--accent)' }}>
      <span className="inline-block w-5 h-px" style={{ background: 'var(--accent)' }} />
      {children}
    </div>
  );
}

function Pillar({ n, labelKey, lang }) {
  const L = window.COPY.hero.pillars[labelKey];
  return (
    <div className="flex items-center gap-2">
      <span className="mono text-[10px]" style={{ color: 'var(--fg-mute)' }}>{n}</span>
      <span className="text-sm" style={{ color: 'var(--fg)' }}>{window.t(L, lang)}</span>
    </div>
  );
}

function Btn({ variant = "primary", children, onClick, href, className = "" }) {
  const base = "inline-flex items-center justify-center px-5 h-11 text-sm font-medium transition";
  const cls = variant === "primary"
    ? `${base} btn-primary rounded-[2px]`
    : `${base} border hairline-strong rounded-[2px] hover:bg-white/[0.04]`;
  const style = variant === "secondary" ? { color: 'var(--fg)' } : undefined;
  if (href) return <a href={href} onClick={onClick} className={`${cls} ${className}`} style={style}>{children}</a>;
  return <button onClick={onClick} className={`${cls} ${className}`} style={style}>{children}</button>;
}

// Animated DER schematic: solar → battery → gateway → grid
function SchematicDER() {
  const a = 'var(--accent)';
  const line = 'var(--line-strong)';
  const fg = 'var(--fg-dim)';
  return (
    <svg viewBox="0 0 520 300" className="w-full h-full" aria-hidden="true">
      {/* grid backdrop */}
      <defs>
        <pattern id="vgrid" width="26" height="26" patternUnits="userSpaceOnUse">
          <path d="M 26 0 L 0 0 0 26" fill="none" stroke="var(--grid)" strokeWidth="1" />
        </pattern>
        <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
          <path d="M 0 0 L 10 5 L 0 10 z" fill={a} />
        </marker>
      </defs>
      <rect width="520" height="300" fill="url(#vgrid)" />

      {/* flow lines */}
      <g fill="none" stroke={a} strokeWidth="1.25">
        <line className="flow-line" x1="100" y1="90"  x2="210" y2="150" markerEnd="url(#arrow)" />
        <line className="flow-line" x1="100" y1="210" x2="210" y2="150" markerEnd="url(#arrow)" />
        <line className="flow-line" x1="262" y1="150" x2="360" y2="150" markerEnd="url(#arrow)" />
        <line className="flow-line" x1="412" y1="150" x2="490" y2="150" markerEnd="url(#arrow)" />
      </g>

      {/* Solar node */}
      <g>
        <rect x="40" y="60" width="60" height="60" fill="none" stroke={line} />
        <g stroke={fg} strokeWidth="1">
          <line x1="50" y1="75"  x2="90" y2="75" />
          <line x1="50" y1="90"  x2="90" y2="90" />
          <line x1="50" y1="105" x2="90" y2="105" />
          <line x1="63" y1="65"  x2="63" y2="115" />
          <line x1="77" y1="65"  x2="77" y2="115" />
        </g>
        <text x="40" y="52" fill={fg} fontSize="10" className="mono" style={{ fontFamily: 'JetBrains Mono' }}>PV · 8.2 kW</text>
      </g>

      {/* Battery node */}
      <g>
        <rect x="40" y="180" width="60" height="60" fill="none" stroke={line} />
        <rect x="50" y="195" width="40" height="30" fill="none" stroke={fg} />
        <rect x="52" y="198" width="10" height="24" fill={a} opacity="0.85" />
        <rect x="64" y="198" width="10" height="24" fill={a} opacity="0.55" />
        <rect x="76" y="198" width="10" height="24" fill={a} opacity="0.25" />
        <rect x="88" y="203" width="3"  height="14" fill={fg} />
        <text x="40" y="172" fill={fg} fontSize="10" className="mono" style={{ fontFamily: 'JetBrains Mono' }}>BESS · 13.5 kWh</text>
      </g>

      {/* Gateway node — the Voltan layer */}
      <g>
        <rect x="210" y="118" width="52" height="64" fill="var(--panel)" stroke={a} />
        <rect x="210" y="118" width="52" height="14" fill={a} />
        <text x="215" y="128" fill="var(--accent-ink)" fontSize="9" className="mono" style={{ fontFamily: 'JetBrains Mono', fontWeight: 600 }}>CSIP-AUS</text>
        <g stroke={fg} strokeWidth="1">
          <circle cx="222" cy="146" r="1.6" fill={fg} />
          <circle cx="230" cy="146" r="1.6" fill={fg} />
          <circle cx="238" cy="146" r="1.6" fill={fg} />
          <circle cx="246" cy="146" r="1.6" fill={a}  />
          <circle cx="254" cy="146" r="1.6" fill={fg} />
          <line x1="218" y1="156" x2="254" y2="156" />
          <line x1="218" y1="164" x2="244" y2="164" />
          <line x1="218" y1="172" x2="250" y2="172" />
        </g>
        <text x="210" y="196" fill={fg} fontSize="10" className="mono" style={{ fontFamily: 'JetBrains Mono' }}>gateway · mTLS</text>
      </g>

      {/* Voltan aggregator node */}
      <g>
        <rect x="360" y="118" width="52" height="64" fill="var(--panel)" stroke={line} />
        <g stroke={a} strokeWidth="1" fill="none">
          <path d="M 370 135 L 386 150 L 402 135" />
          <path d="M 370 150 L 386 165 L 402 150" />
        </g>
        <text x="360" y="196" fill={fg} fontSize="10" className="mono" style={{ fontFamily: 'JetBrains Mono' }}>VPP · aggregator</text>
        {/* pulse */}
        <circle cx="386" cy="150" r="4" fill={a} />
        <circle cx="386" cy="150" r="4" fill={a} opacity="0.4" className="pulse-ring" />
      </g>

      {/* Grid node */}
      <g>
        <g stroke={fg} strokeWidth="1" fill="none" transform="translate(460 118)">
          <path d="M 15 0 L 0 30 L 30 30 Z" />
          <path d="M 15 0 L 15 -6" />
          <line x1="5"  y1="40" x2="25" y2="40" />
          <line x1="15" y1="30" x2="15" y2="58" />
        </g>
        <text x="452" y="196" fill={fg} fontSize="10" className="mono" style={{ fontFamily: 'JetBrains Mono' }}>AEMO grid</text>
      </g>

      {/* telemetry readout */}
      <g className="mono" fontSize="9.5" style={{ fontFamily: 'JetBrains Mono' }}>
        <text x="40"  y="268" fill={fg}>tx  </text><text x="62"  y="268" fill="var(--fg)">4.12 kW</text>
        <text x="130" y="268" fill={fg}>soc </text><text x="152" y="268" fill="var(--fg)">68%</text>
        <text x="200" y="268" fill={fg}>rtt </text><text x="222" y="268" fill="var(--fg)">84 ms</text>
        <text x="280" y="268" fill={fg}>sess</text><text x="305" y="268" fill="var(--fg)">OK</text>
        <text x="340" y="268" fill={fg}>dispatch</text><text x="388" y="268" fill={a}>ARMED</text>
        <text x="440" y="268" fill={fg}>AEMO</text><text x="472" y="268" fill="var(--fg)">5MIN</text>
      </g>
    </svg>
  );
}

// Countdown to July 1, 2026 UTC — CSIP-AUS v1.2 mandate
function useCountdown(targetISO) {
  const [now, setNow] = React.useState(() => Date.now());
  React.useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, []);
  const target = new Date(targetISO).getTime();
  let diff = Math.max(0, target - now);
  const days = Math.floor(diff / 86400000); diff -= days * 86400000;
  const hrs  = Math.floor(diff / 3600000);  diff -= hrs * 3600000;
  const min  = Math.floor(diff / 60000);    diff -= min * 60000;
  const sec  = Math.floor(diff / 1000);
  return { days, hrs, min, sec };
}

function Countdown({ lang }) {
  const c = useCountdown('2026-07-01T00:00:00+10:00');
  const U = window.COPY.hero.countdownUnits;
  const L = window.COPY.hero.countdownLabel;
  const pad = (n, w = 2) => String(n).padStart(w, '0');
  const cell = (val, unit) => (
    <div className="flex items-baseline gap-1">
      <span className="mono text-base tabular-nums" style={{ color: 'var(--fg)' }}>{val}</span>
      <span className="mono text-[10px]" style={{ color: 'var(--fg-mute)' }}>{window.t(unit, lang)}</span>
    </div>
  );
  return (
    <div className="inline-flex items-center gap-4 border hairline px-4 py-2.5 rounded-[2px]"
         style={{ background: 'var(--panel)' }}>
      <span className="flex items-center gap-2">
        <span className="w-1.5 h-1.5 rounded-full blink" style={{ background: 'var(--accent)' }} />
        <span className="mono text-[10px] uppercase tracking-[0.18em]" style={{ color: 'var(--fg-dim)' }}>
          {window.t(L, lang)}
        </span>
      </span>
      <span className="w-px h-4" style={{ background: 'var(--line)' }} />
      {cell(pad(c.days, 3), U.days)}
      {cell(pad(c.hrs),  U.hrs)}
      {cell(pad(c.min),  U.min)}
      {cell(pad(c.sec),  U.sec)}
    </div>
  );
}

// Nav
function Nav({ lang, setLang, theme, setTheme }) {
  const N = window.COPY.nav;
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const items = [
    ['capabilities', '#capabilities'],
    ['technology',   '#technology'],
    ['whyNow',       '#why-now'],
    ['about',        '#about'],
    ['contact',      '#contact'],
  ];
  return (
    <header className={`fixed top-0 inset-x-0 z-40 transition-all ${scrolled ? 'backdrop-blur-md' : ''}`}
            style={{
              background: scrolled ? 'color-mix(in oklab, var(--bg) 82%, transparent)' : 'transparent',
              borderBottom: scrolled ? '1px solid var(--line)' : '1px solid transparent',
            }}>
      <div className="max-w-[1280px] mx-auto px-6 h-16 flex items-center justify-between">
        <a href="#top" className="flex items-center" style={{ color: 'var(--fg)' }}>
          <Wordmark size={20} />
        </a>
        <nav className="hidden md:flex items-center gap-7">
          {items.map(([k, href]) => (
            <a key={k} href={href} className="text-[13px] transition hover:opacity-100"
               style={{ color: 'var(--fg-dim)' }}
               onMouseEnter={e => e.currentTarget.style.color = 'var(--fg)'}
               onMouseLeave={e => e.currentTarget.style.color = 'var(--fg-dim)'}>
              {window.t(N[k], lang)}
            </a>
          ))}
        </nav>
        <div className="flex items-center gap-2">
          <LangToggle lang={lang} setLang={setLang} />
          <ThemeToggle theme={theme} setTheme={setTheme} />
          <a href="#contact"
             className="hidden sm:inline-flex items-center h-9 px-4 text-[13px] font-medium btn-primary rounded-[2px]">
            {window.t(N.book, lang)}
          </a>
        </div>
      </div>
    </header>
  );
}

function LangToggle({ lang, setLang }) {
  return (
    <div className="flex items-center border hairline rounded-[2px] h-9 overflow-hidden mono text-[11px]">
      {['en','zh'].map(k => (
        <button key={k}
          onClick={() => setLang(k)}
          className="px-2.5 h-full"
          style={{
            background: lang === k ? 'var(--fg)' : 'transparent',
            color: lang === k ? 'var(--bg)' : 'var(--fg-dim)',
          }}>
          {k === 'en' ? 'EN' : '中文'}
        </button>
      ))}
    </div>
  );
}

function ThemeToggle({ theme, setTheme }) {
  const dark = theme === 'dark';
  return (
    <button
      onClick={() => setTheme(dark ? 'light' : 'dark')}
      aria-label="Toggle theme"
      className="w-9 h-9 inline-flex items-center justify-center border hairline rounded-[2px]"
      style={{ color: 'var(--fg-dim)' }}>
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
        {dark
          ? <path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z" />
          : <g><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M2 12h2M20 12h2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" /></g>
        }
      </svg>
    </button>
  );
}

// Reveal on scroll
function Reveal({ children, className = "", delay = 0 }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          setTimeout(() => el.classList.add('in'), delay);
          io.unobserve(el);
        }
      });
    }, { threshold: 0.12 });
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return <div ref={ref} className={`reveal ${className}`}>{children}</div>;
}

// Animated number (tweens from 0 to value when in view)
function StatNum({ value, suffix = "", duration = 1200 }) {
  const [n, setN] = React.useState(0);
  const [started, setStarted] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((es) => {
      es.forEach(e => { if (e.isIntersecting) setStarted(true); });
    }, { threshold: 0.5 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  React.useEffect(() => {
    if (!started) return;
    if (typeof value !== 'number') { setN(value); return; }
    let raf; const t0 = performance.now();
    const tick = (t) => {
      const p = Math.min(1, (t - t0) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(value * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [started, value, duration]);
  return <span ref={ref} className="tabular-nums">{typeof value === 'number' ? n.toLocaleString() : value}{suffix}</span>;
}

Object.assign(window, { Wordmark, Kicker, Pillar, Btn, SchematicDER, Countdown, Nav, Reveal, StatNum });
