/* global React, ReactDOM */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ---------- WordsPullUp ---------- */
function WordsPullUp({ text, className = "", showAsterisk = false }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);

  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setInView(true);
            obs.disconnect();
          }
        });
      },
      { threshold: 0.15 }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);

  const words = text.split(" ");
  return (
    <h1 ref={ref} className={`hero-title ${inView ? "in" : ""} ${className}`}>
      {words.map((w, i) => (
        <span className="word" key={i}>
          <span>
            {w}
            {showAsterisk && i === words.length - 1 ? (
              <sup className="ast">*</sup>
            ) : null}
          </span>
        </span>
      ))}
    </h1>
  );
}

/* ---------- WordsPullUpMultiStyle ---------- */
function WordsPullUpMultiStyle({ segments, className = "" }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);

  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setInView(true);
            obs.disconnect();
          }
        });
      },
      { threshold: 0.2 }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);

  let idx = 0;
  return (
    <h2 ref={ref} className={`section-title ${inView ? "in" : ""} ${className}`}>
      {segments.map((seg, si) =>
        seg.text.split(" ").map((w, wi) => {
          const i = idx++;
          return (
            <span
              className={`word ${seg.className || ""}`}
              key={`${si}-${wi}`}
              style={{ transitionDelay: `${i * 0.06}s` }}
            >
              <span>{w}</span>
            </span>
          );
        })
      )}
    </h2>
  );
}

/* ---------- AnimatedParagraph (scroll-linked char opacity) ---------- */
function AnimatedParagraph({ text }) {
  const ref = useRef(null);
  const [progress, setProgress] = useState(0);

  useEffect(() => {
    const onScroll = () => {
      if (!ref.current) return;
      const r = ref.current.getBoundingClientRect();
      const vh = window.innerHeight;
      const start = vh * 0.85;
      const end = vh * 0.2;
      const total = start - end;
      const val = (start - r.top) / total;
      setProgress(Math.max(0, Math.min(1, val)));
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);

  const chars = useMemo(() => text.split(""), [text]);
  const total = chars.length;

  return (
    <p ref={ref} className="about-paragraph">
      {chars.map((c, i) => {
        const cp = i / total;
        const lit = progress >= cp - 0.02;
        return (
          <span key={i} className={`ch ${lit ? "lit" : ""}`}>
            {c}
          </span>
        );
      })}
    </p>
  );
}

/* ---------- Section reveal hook ---------- */
function useInViewClass(threshold = 0.2) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setInView(true);
            obs.disconnect();
          }
        });
      },
      { threshold }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [threshold]);
  return [ref, inView];
}

/* ---------- Icons (inline SVG) ---------- */
const ArrowRightIcon = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
);
const CheckIcon = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
);
const SparkIcon = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2v4M12 18v4M2 12h4M18 12h4M5 5l3 3M16 16l3 3M19 5l-3 3M8 16l-3 3"/></svg>
);
const ShieldIcon = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="M9 12l2 2 4-4"/></svg>
);
const SearchIcon = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.3-4.3"/></svg>
);

window.IdeomBits = {
  WordsPullUp,
  WordsPullUpMultiStyle,
  AnimatedParagraph,
  useInViewClass,
  ArrowRightIcon,
  CheckIcon,
  SparkIcon,
  ShieldIcon,
  SearchIcon,
};
