/* global React, Nav, Hero, About, Challenges, Strengths, Services, Practice, Cases, Results, Lawyers, Column, FAQ, Footer */
/* global TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakColor, TweakSelect */

const { useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#C84A5F",
  "headlineFont": "shippori",
  "enFont": "grotesk"
}/*EDITMODE-END*/;

function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    const root = document.documentElement;
    // accent
    root.style.setProperty("--accent", tweaks.accent);
    // headline font
    const fonts = {
      shippori: '"Shippori Mincho", "Noto Serif JP", serif',
      noto: '"Noto Serif JP", "Shippori Mincho", serif',
      sans: '"Shippori Mincho", "Noto Serif JP", serif',
    };
    root.style.setProperty("--serif-jp", fonts[tweaks.headlineFont] || fonts.shippori);
    // english display font (tech accent)
    const enFonts = {
      grotesk: '"Space Grotesk", "Inter", system-ui, sans-serif',
      mono: '"JetBrains Mono", "SF Mono", Menlo, monospace',
      inter: '"Inter", system-ui, sans-serif',
    };
    root.style.setProperty("--serif-en-display", enFonts[tweaks.enFont] || enFonts.grotesk);
    // theme — flip starting section
    document.body.dataset.theme = tweaks.theme;
  }, [tweaks]);

  // scroll reveal — supports both .reveal and [data-reveal*]
  useEffect(() => {
    const els = document.querySelectorAll(".reveal, [data-reveal], [data-reveal-stagger], .img-reveal, .num-flicker, .split-word");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add("is-visible");
          io.unobserve(e.target);
        }
      });
    }, { rootMargin: "0px 0px -8% 0px", threshold: 0.05 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  // spotlight + tilt mouse tracking
  useEffect(() => {
    const onMove = (e) => {
      // spotlight
      document.querySelectorAll(".spotlight").forEach((el) => {
        const r = el.getBoundingClientRect();
        if (e.clientX < r.left - 80 || e.clientX > r.right + 80 ||
            e.clientY < r.top - 80 || e.clientY > r.bottom + 80) return;
        const x = ((e.clientX - r.left) / r.width) * 100;
        const y = ((e.clientY - r.top) / r.height) * 100;
        el.style.setProperty("--mx", x + "%");
        el.style.setProperty("--my", y + "%");
      });
      // tilt
      document.querySelectorAll(".tilt").forEach((el) => {
        const r = el.getBoundingClientRect();
        if (e.clientX < r.left || e.clientX > r.right ||
            e.clientY < r.top || e.clientY > r.bottom) {
          el.style.setProperty("--rx", "0deg");
          el.style.setProperty("--ry", "0deg");
          return;
        }
        const cx = (e.clientX - r.left) / r.width - 0.5;
        const cy = (e.clientY - r.top) / r.height - 0.5;
        el.style.setProperty("--ry", (cx * 8) + "deg");
        el.style.setProperty("--rx", (-cy * 8) + "deg");
      });
    };
    window.addEventListener("mousemove", onMove, { passive: true });
    return () => window.removeEventListener("mousemove", onMove);
  }, []);

  // parallax (set --py based on scroll)
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        document.querySelectorAll("[data-parallax]").forEach((el) => {
          const speed = parseFloat(el.dataset.parallax) || 0.15;
          const r = el.getBoundingClientRect();
          const center = r.top + r.height / 2 - window.innerHeight / 2;
          el.style.setProperty("--py", (-center * speed) + "px");
        });
        raf = 0;
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // counter animation (count up to data-target)
  useEffect(() => {
    const els = document.querySelectorAll("[data-count-to]");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (!e.isIntersecting) return;
        const el = e.target;
        const target = parseFloat(el.dataset.countTo);
        const decimals = parseInt(el.dataset.countDecimals || "0", 10);
        const suffix = el.dataset.countSuffix || "";
        const prefix = el.dataset.countPrefix || "";
        const dur = parseInt(el.dataset.countDuration || "1600", 10);
        const start = performance.now();
        const tick = (now) => {
          const t = Math.min(1, (now - start) / dur);
          const ease = 1 - Math.pow(1 - t, 3);
          const v = (target * ease).toFixed(decimals);
          el.textContent = prefix + v + suffix;
          if (t < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
        io.unobserve(el);
      });
    }, { threshold: 0.4 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  // cursor dot
  useEffect(() => {
    const dot = document.createElement("div");
    dot.className = "cursor-dot";
    document.body.appendChild(dot);
    const onMove = (e) => {
      dot.style.setProperty("--x", e.clientX + "px");
      dot.style.setProperty("--y", e.clientY + "px");
      dot.classList.add("is-active");
    };
    const onOver = (e) => {
      const target = e.target.closest("a, button, .lift, .spotlight, .tilt");
      dot.classList.toggle("is-hover", !!target);
    };
    window.addEventListener("mousemove", onMove, { passive: true });
    window.addEventListener("mouseover", onOver, { passive: true });
    return () => {
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseover", onOver);
      dot.remove();
    };
  }, []);

  return (
    <React.Fragment>
      <Nav />
      <Hero />
      <Clients />
      <About />
      <Services />
      <Challenges />
      <Strengths />
      <Practice />
      <Cases />
      <Results />
      <Lawyers />
      <AIAgentPromo />
      <Column />
      <FAQ />
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection title="Theme">
          <TweakRadio
            label="アクセントカラー"
            value={tweaks.accent}
            onChange={(v) => setTweak("accent", v)}
            options={[
              { value: "#1F4D3F", label: "Emerald" },
              { value: "#163B30", label: "Forest" },
              { value: "#C84A5F", label: "Brand Red" },
              { value: "#6E7A8E", label: "Slate" },
            ]}
          />
        </TweakSection>
        <TweakSection title="Typography">
          <TweakRadio
            label="見出しフォント"
            value={tweaks.headlineFont}
            onChange={(v) => setTweak("headlineFont", v)}
            options={[
              { value: "shippori", label: "Shippori 明朝" },
              { value: "noto", label: "Noto Serif" },
              { value: "sans", label: "Noto Sans" },
            ]}
          />
          <TweakRadio
            label="英字フォント"
            value={tweaks.enFont}
            onChange={(v) => setTweak("enFont", v)}
            options={[
              { value: "grotesk", label: "Grotesk" },
              { value: "mono", label: "Mono" },
              { value: "inter", label: "Inter" },
            ]}
          />
        </TweakSection>
        <TweakSection title="カスタム">
          <TweakColor label="アクセント (任意)" value={tweaks.accent} onChange={(v) => setTweak("accent", v)} />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
