/* ============================================================
 * components.jsx — VideoBackground, SplitText, Icons, Navbar
 * ============================================================ */

/* ---- VideoBackground
   Lazily attaches its src when the element scrolls into view. Pass eager
   to load immediately (used by the hero so it plays on first paint). ---- */
function VideoBackground({ src, flip = false, opacity = 1, className = "", eager = false }) {
  const wrapRef = React.useRef(null);
  const [shouldLoad, setShouldLoad] = React.useState(eager);

  React.useEffect(() => {
    if (shouldLoad) return;
    if (!wrapRef.current) return;
    if (typeof IntersectionObserver === 'undefined') { setShouldLoad(true); return; }
    const el = wrapRef.current;
    const io = new IntersectionObserver((entries) => {
      if (entries.some((e) => e.isIntersecting)) {
        setShouldLoad(true);
        io.disconnect();
      }
    }, { rootMargin: '400px' });
    io.observe(el);
    // Safety net in case IO doesn't fire (some iframes / older WebKit)
    const fallback = setTimeout(() => setShouldLoad(true), 1500);
    return () => { io.disconnect(); clearTimeout(fallback); };
  }, [shouldLoad]);

  return (
    <div ref={wrapRef} className={`absolute inset-0 ${className}`}>
      {shouldLoad && (
        <video
          autoPlay
          muted
          loop
          playsInline
          preload="auto"
          className="absolute inset-0 w-full h-full object-cover"
          style={{
            transform: flip ? 'scaleX(-1)' : undefined,
            opacity,
          }}
        >
          <source src={src} type="video/mp4" />
        </video>
      )}
    </div>
  );
}

/* ---- SplitText (GSAP-driven char-by-char fade up)
   Accepts a flat array of: strings, <br/>, and inline elements like <em>.
   Inline elements contribute their text content but tag those chars so the
   parent's style (e.g. italic) survives the per-char split. ---- */
function SplitText({ children, className = "", delay = 0, style }) {
  const ref = React.useRef(null);

  // Recursively pull plain text from any React node — strings, arrays,
  // and elements (some runtimes wrap text in helper components, so
  // c.props.children may itself be an element).
  const extractText = React.useCallback((n) => {
    if (n == null || n === false) return '';
    if (typeof n === 'string' || typeof n === 'number') return String(n);
    if (Array.isArray(n)) return n.map(extractText).join('');
    if (n && n.props) return extractText(n.props.children);
    return '';
  }, []);

  // Build an array of lines, where each line is an array of
  // { text, style } segments. <br/> ends a line; <em>/other elements
  // become a segment with their inline style.
  const lines = React.useMemo(() => {
    const list = Array.isArray(children) ? children : [children];
    const out = [];
    let cur = [];
    list.forEach((c) => {
      if (c == null || c === false) return;
      if (typeof c === 'string' || typeof c === 'number') {
        cur.push({ text: String(c), style: null });
      } else if (c && c.type === 'br') {
        out.push(cur);
        cur = [];
      } else if (c && c.props) {
        cur.push({
          text: extractText(c.props.children),
          style: c.props.style || null,
          tag: c.type,
        });
      }
    });
    out.push(cur);
    return out;
  }, [children, extractText]);

  React.useEffect(() => {
    if (!ref.current || !window.gsap) return;
    const chars = ref.current.querySelectorAll('.st-char');
    window.gsap.set(chars, { yPercent: 110, opacity: 0 });
    window.gsap.to(chars, {
      yPercent: 0,
      opacity: 1,
      duration: 1.1,
      ease: 'expo.out',
      stagger: 0.022,
      delay,
    });
  }, [delay, lines]);

  return (
    <h1 ref={ref} className={className} style={style}>
      {lines.map((segments, li) => (
        <span key={li} style={{ display: 'block', overflow: 'hidden', paddingBottom: '0.08em' }}>
          {segments.map((seg, si) => {
            const Tag = seg.tag === 'em' ? 'em' : 'span';
            return (
              <Tag key={si} style={seg.style || undefined}>
                {[...seg.text].map((ch, ci) => (
                  <span
                    key={ci}
                    className="st-char"
                    style={{ display: 'inline-block', whiteSpace: 'pre' }}
                  >
                    {ch}
                  </span>
                ))}
              </Tag>
            );
          })}
        </span>
      ))}
    </h1>
  );
}

/* ---- Inline icon set (mimics lucide-react names) ---- */
const Icon = {
  Sparkles: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M12 3l1.9 4.6L18.5 9.5l-4.6 1.9L12 16l-1.9-4.6L5.5 9.5l4.6-1.9z" />
      <path d="M19 14l.7 1.7L21.5 16.5l-1.7.7L19 19l-.7-1.7L16.5 16.5l1.7-.7z" />
      <path d="M5 16l.6 1.4 1.4.6-1.4.6L5 20l-.6-1.4L3 18l1.4-.6z" />
    </svg>
  ),
  Code: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polyline points="16 18 22 12 16 6" />
      <polyline points="8 6 2 12 8 18" />
      <line x1="14" y1="4" x2="10" y2="20" />
    </svg>
  ),
  Server: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <rect x="3" y="3" width="18" height="7" rx="1.5" />
      <rect x="3" y="14" width="18" height="7" rx="1.5" />
      <line x1="7" y1="6.5" x2="7.01" y2="6.5" />
      <line x1="7" y1="17.5" x2="7.01" y2="17.5" />
    </svg>
  ),
  Palette: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <circle cx="13.5" cy="6.5" r=".7" />
      <circle cx="17.5" cy="10.5" r=".7" />
      <circle cx="8.5" cy="7.5" r=".7" />
      <circle cx="6.5" cy="12.5" r=".7" />
      <path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c1.4 0 2.5-1.1 2.5-2.5 0-.7-.3-1.3-.7-1.7-.4-.4-.7-1-.7-1.7 0-1.4 1.1-2.5 2.5-2.5H17c2.8 0 5-2.2 5-5 0-4.4-4.5-8-10-8z" />
    </svg>
  ),
  Zap: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
    </svg>
  ),
  Cloud: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M17 18.5A4.5 4.5 0 0 0 17 9.5h-.5A6 6 0 0 0 5 11a4 4 0 1 0 0 7.5z" />
    </svg>
  ),
  Layers: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polygon points="12 2 22 8 12 14 2 8 12 2" />
      <polyline points="2 14 12 20 22 14" />
      <polyline points="2 19 12 25 22 19" transform="translate(0 -4)"/>
    </svg>
  ),
  Cpu: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <rect x="4" y="4" width="16" height="16" rx="2" />
      <rect x="9" y="9" width="6" height="6" />
      <line x1="9" y1="2" x2="9" y2="4" />
      <line x1="15" y1="2" x2="15" y2="4" />
      <line x1="9" y1="20" x2="9" y2="22" />
      <line x1="15" y1="20" x2="15" y2="22" />
      <line x1="2" y1="9" x2="4" y2="9" />
      <line x1="2" y1="15" x2="4" y2="15" />
      <line x1="20" y1="9" x2="22" y2="9" />
      <line x1="20" y1="15" x2="22" y2="15" />
    </svg>
  ),
  Check: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <polyline points="20 6 9 17 4 12" />
    </svg>
  ),
  Arrow: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <line x1="5" y1="12" x2="19" y2="12" />
      <polyline points="12 5 19 12 12 19" />
    </svg>
  ),
  Github: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M12 .5A11.5 11.5 0 0 0 .5 12a11.5 11.5 0 0 0 7.86 10.92c.58.1.78-.25.78-.55 0-.27-.01-1.16-.02-2.1-3.2.7-3.88-1.36-3.88-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.2 1.77 1.2 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.27-5.24-5.66 0-1.25.45-2.27 1.18-3.07-.12-.29-.51-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.78 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.8 1.18 1.82 1.18 3.07 0 4.4-2.69 5.36-5.26 5.65.41.36.77 1.06.77 2.14 0 1.54-.01 2.78-.01 3.16 0 .3.2.66.79.55A11.5 11.5 0 0 0 23.5 12 11.5 11.5 0 0 0 12 .5z" />
    </svg>
  ),
  Twitter: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
    </svg>
  ),
  Mail: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <rect x="2" y="4" width="20" height="16" rx="2" />
      <polyline points="22 6 12 13 2 6" />
    </svg>
  ),
  Dot: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <circle cx="12" cy="12" r="4" />
    </svg>
  ),
};

/* ---- Navbar ---- */
function Navbar({ dark = false }) {
  // dark = true → dark text/elements for use over a LIGHT background
  const txt = dark ? 'text-black' : 'text-white';
  const logoFill = dark ? 'black' : 'white';
  const sub = dark ? 'text-black/40' : 'text-white/40';
  const link = dark ? 'text-black/70 hover:text-black' : 'text-white/75 hover:text-white';

  return (
    <nav className="absolute top-0 left-0 right-0 z-50 px-5 sm:px-8 py-4 sm:py-5">
      <div className="max-w-[1280px] mx-auto flex items-center justify-between">
        {/* Left: logo + wordmark */}
        <a href="#" className={`flex items-center gap-2.5 min-w-0 ${txt}`}>
          <svg width="22" height="22" viewBox="0 0 256 256" className="flex-shrink-0">
            <path
              d="M 256 256 L 128 256 L 0 128 L 128 128 Z M 256 128 L 128 128 L 0 0 L 128 0 Z"
              fill={logoFill}
            />
          </svg>
          <span className="text-[16px] sm:text-[17px] tracking-[-0.02em]" style={{ fontWeight: 500, fontFamily: 'var(--font-heading)' }}>Capsulepoint</span>
          <span className={`hidden sm:inline text-[12px] tracking-[0.18em] uppercase ml-1.5 ${sub}`} style={{ fontWeight: 300 }}>
            個人開発者
          </span>
        </a>

        {/* Center: links */}
        <div className={`hidden md:flex items-center gap-7 text-[14px] ${link}`}>
          <a href="#work" className="transition-colors">Works</a>
          <a href="#contact" className="transition-colors">Contact</a>
        </div>

        {/* Right: CTA */}
        <a
          href="#contact"
          className={`rounded-full px-4 sm:px-5 py-2.5 text-[13px] inline-flex items-center gap-2 flex-shrink-0 transition-colors ${
            dark
              ? 'border border-black/20 text-black hover:bg-black hover:text-white'
              : 'liquid-glass text-white'
          }`}
          style={{ fontWeight: 400 }}
        >
          <span className="relative z-10">Say hello</span>
          <Icon.Arrow width="14" height="14" className="relative z-10" />
        </a>
      </div>
    </nav>
  );
}

/* Expose globals */
Object.assign(window, { VideoBackground, SplitText, Icon, Navbar });
