/* global React */
// EUROSTAR — atoms & primitives (forked for the one-page site)
const { useEffect: useFx, useRef: useR, useState: useSt } = React;

const REDUCED = typeof window !== 'undefined' && window.matchMedia
  ? window.matchMedia('(prefers-reduced-motion: reduce)').matches : false;

// ---- useReveal: IntersectionObserver -> becomes true once the node scrolls
// into view, then stays. The journey backbone — every block fades + rises in.
function useReveal({ threshold = 0.18, margin = '0px 0px -12% 0px', once = true } = {}) {
  const ref = useR(null);
  const [shown, setShown] = useSt(REDUCED);
  useFx(() => {
    if (REDUCED) { setShown(true); return; }
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { setShown(true); if (once) io.unobserve(e.target); }
        else if (!once) setShown(false);
      });
    }, { threshold, rootMargin: margin });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, shown];
}

// ---- Reveal: wraps children in a block that rises + fades when scrolled into
// view. `as` lets it stand in for any element; `y` / `delay` tune the motion.
function Reveal({ children, as = 'div', y = 28, delay = 0, dur = 820, blur = false, style = {}, ...rest }) {
  const [ref, shown] = useReveal();
  const Tag = as;
  return (
    <Tag ref={ref} style={{
      opacity: shown ? 1 : 0,
      transform: shown ? 'translateY(0)' : `translateY(${y}px)`,
      filter: blur ? (shown ? 'blur(0)' : 'blur(8px)') : 'none',
      transition: `opacity ${dur}ms var(--ease-out) ${delay}ms, transform ${dur}ms var(--ease-out) ${delay}ms, filter ${dur}ms var(--ease-out) ${delay}ms`,
      willChange: 'opacity, transform',
      ...style,
    }} {...rest}>{children}</Tag>
  );
}

// ---- useCountUp: animates a number from 0 -> target once `run` is true.
// Preserves a non-numeric suffix (the "+" in "150+").
function useCountUp(raw, run, dur = 1400) {
  const num = parseFloat(String(raw).replace(/[^0-9.]/g, '')) || 0;
  const suffix = String(raw).replace(/[0-9.,\s]/g, '');
  const [val, setVal] = useSt(REDUCED ? num : 0);
  useFx(() => {
    if (!run || REDUCED) { if (REDUCED) setVal(num); return; }
    let frame; const start = performance.now();
    const tick = (now) => {
      const p = Math.min(1, (now - start) / dur);
      const eased = 1 - Math.pow(1 - p, 3);
      setVal(num * eased);
      if (p < 1) frame = requestAnimationFrame(tick);
      else setVal(num);
    };
    frame = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(frame);
  }, [run]);
  const display = Number.isInteger(num) ? Math.round(val).toString() : val.toFixed(0);
  return display + suffix;
}

// Lucide icon. Renders a span lucide replaces with an inline SVG.
function Icon({ name, size = 20, stroke = 1.75, className = '', style = {} }) {
  const ref = useR(null);
  useFx(() => {
    if (window.lucide && ref.current) {
      ref.current.innerHTML = '';
      const i = document.createElement('i');
      i.setAttribute('data-lucide', name);
      ref.current.appendChild(i);
      window.lucide.createIcons({ attrs: { width: size, height: size, 'stroke-width': stroke }, nameAttr: 'data-lucide' });
    }
  });
  return <span ref={ref} className={className} style={{ display: 'inline-flex', lineHeight: 0, ...style }} aria-hidden="true" />;
}

const STUDIO = 'EUROSTAR';

// Logo lockup: brand mark glyph + typeset wordmark.
function Logo({ height = 28, theme = 'dark', descriptor = 'MEDIA NETWORK' }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: height * 0.42 }}>
      <img src="assets/eurostar-mark.png" alt="" style={{ height: height * 1.18, width: 'auto', display: 'block' }} />
      <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', lineHeight: 1 }}>
        <span style={{ fontFamily: 'var(--font-display)', fontWeight: 900, textTransform: 'uppercase', letterSpacing: '0.02em', fontSize: height * 0.64, color: 'var(--fg1)' }}>{STUDIO}</span>
        {descriptor && <span style={{ fontFamily: 'var(--font-mono)', fontSize: Math.max(8, height * 0.2), letterSpacing: '0.24em', textTransform: 'uppercase', color: 'var(--fg3)', marginTop: height * 0.16 }}>{descriptor}</span>}
      </div>
    </div>
  );
}

function Mark({ size = 28, style = {} }) {
  return <img src="assets/eurostar-mark.png" alt="" style={{ width: size, height: 'auto', display: 'block', ...style }} />;
}

function Button({ children, variant = 'primary', icon, iconRight, onClick, href, style = {}, className = '' }) {
  const base = {
    fontFamily: 'var(--font-display)', fontWeight: 700, textTransform: 'uppercase',
    letterSpacing: '0.12em', fontSize: 13, padding: '14px 26px', borderRadius: 'var(--r-md)',
    border: '1px solid transparent', cursor: 'pointer', display: 'inline-flex', alignItems: 'center',
    justifyContent: 'center', gap: 10, transition: 'all var(--dur-base) var(--ease-out)',
    textDecoration: 'none', whiteSpace: 'nowrap', ...style,
  };
  const variants = {
    primary: { background: 'var(--accent)', color: 'var(--accent-contrast)' },
    secondary: { background: 'transparent', borderColor: 'var(--hairline-strong)', color: 'var(--fg1)' },
    ghost: { background: 'transparent', color: 'var(--fg2)', paddingLeft: 12, paddingRight: 12 },
  };
  const cls = `es-btn es-btn-${variant} ${className}`.trim();
  const inner = <>{icon && <Icon name={icon} size={17} />}{children}{iconRight && <Icon name={iconRight} size={17} />}</>;
  if (href) return <a className={cls} style={{ ...base, ...variants[variant] }} href={href} onClick={onClick}>{inner}</a>;
  return <button className={cls} style={{ ...base, ...variants[variant] }} onClick={onClick}>{inner}</button>;
}

function Tag({ children, tone = 'outline', style = {} }) {
  const tones = {
    solid: { background: 'var(--accent)', color: 'var(--accent-contrast)' },
    outline: { border: '1px solid var(--hairline-strong)', color: 'var(--fg2)' },
    dark: { background: 'rgba(0,0,0,0.5)', color: 'var(--off-white)', backdropFilter: 'blur(6px)' },
  };
  return (
    <span style={{
      fontFamily: 'var(--font-display)', fontWeight: 700, textTransform: 'uppercase',
      letterSpacing: '0.12em', fontSize: 10, padding: '5px 10px', borderRadius: 999, ...tones[tone], ...style,
    }}>{children}</span>
  );
}

// thin hairline + tracked label, the EUROSTAR eyebrow signature
function Eyebrow({ children, style = {} }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, ...style }}>
      <span style={{ width: 34, height: 1, background: 'var(--accent)', flex: '0 0 auto' }} />
      <span className="es-eyebrow" style={{ color: 'var(--accent-ink)' }}>{children}</span>
    </div>
  );
}

Object.assign(window, { Icon, Logo, Mark, Button, Tag, Eyebrow, STUDIO, useReveal, Reveal, useCountUp, REDUCED });
