/* ===========================================================
   App — slide state machine + transitions
   =========================================================== */
const { useState, useEffect, useCallback } = React;

function renderSlide(slide) {
  switch (slide.type) {
    case "cover": return React.createElement(CoverSlide, { slide });
    case "biz-process-chain": return React.createElement(BizProcessChainSlide, { slide });
    case "invoice-flood": return React.createElement(InvoiceFloodSlide, { slide });
    case "text-list": return React.createElement(ListSlide, { slide, variant: "number" });
    case "share-link": return React.createElement(ShareLinkSlide, { slide });
    case "payment-journey": return React.createElement(PaymentJourneySlide, { slide });
    case "online-order": return React.createElement(OnlineOrderSlide, { slide });
    case "process-compare": return React.createElement(ProcessCompareSlide, { slide });
    case "bento-audience": return React.createElement(BentoAudienceSlide, { slide });
    case "ecosystem": return React.createElement(EcosystemSlide, { slide });
    case "steps": return React.createElement(StepsSlide, { slide });
    case "demo": return React.createElement(DemoSlide, { slide });
    case "vflow": return React.createElement(VFlowSlide, { slide });
    case "groups": return React.createElement(GroupsSlide, { slide });
    case "payment-hub": return React.createElement(PaymentHubSlide, { slide });
    case "online-order-showcase": return React.createElement(OnlineOrderShowcaseSlide, { slide });
    case "bento-benefits": return React.createElement(BentoBenefitsSlide, { slide });
    case "contacts": return React.createElement(ContactsSlide, { slide });
    case "raif-consult": return React.createElement(RaifConsultSlide, { slide });
    case "b2b-req": return React.createElement(B2BReqSlide, { slide });
    default: return null;
  }
}

const slideTransition = {
  animate: { opacity: 1, scale: 1, filter: "blur(0px)", transition: { type: "spring", stiffness: 88, damping: 18, mass: 0.9 } },
  exit: { opacity: 0, scale: 1.18, filter: "blur(18px)", transition: { duration: 0.42, ease: [0.6, 0, 0.85, 0.2] } },
};

function App() {
  const slides = window.SLIDES;
  const total = slides.length;

  const getInitial = () => {
    const h = parseInt(window.location.hash.replace("#", ""), 10);
    if (!isNaN(h) && h >= 1 && h <= total) return h - 1;
    return 0;
  };
  const [index, setIndex] = useState(getInitial);

  /* ---- Theme toggle ---- */
  const [isDark, setIsDark] = useState(true);
  const toggleTheme = useCallback(() => setIsDark(d => !d), []);
  useEffect(() => {
    const theme = isDark ? "dark" : "light";
    document.documentElement.setAttribute("data-theme", theme);
    document.body.setAttribute("data-theme", theme);
    window.__isDark = isDark;
  }, [isDark]);

  const goto = useCallback((i) => {
    setIndex((prev) => {
      const next = Math.max(0, Math.min(total - 1, i));
      return next;
    });
  }, [total]);

  const next = useCallback(() => goto(indexRef.current + 1), [goto]);
  const prev = useCallback(() => goto(indexRef.current - 1), [goto]);

  // keep a ref so key handler always sees current index
  const indexRef = React.useRef(index);
  useEffect(() => { indexRef.current = index; window.location.hash = String(index + 1); }, [index]);

  // If the doc loaded hidden (no animation), replay once it becomes visible
  const [replay, setReplay] = useState(0);
  useEffect(() => {
    if (window.__animOK) return;
    const onVis = () => {
      if (!document.hidden && !window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
        window.__animOK = true;
        setReplay((r) => r + 1);
      }
    };
    document.addEventListener("visibilitychange", onVis);
    return () => document.removeEventListener("visibilitychange", onVis);
  }, []);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "ArrowRight" || e.key === " " || e.key === "PageDown" || e.key === "ArrowDown") {
        e.preventDefault(); goto(indexRef.current + 1);
      } else if (e.key === "ArrowLeft" || e.key === "PageUp" || e.key === "ArrowUp") {
        e.preventDefault(); goto(indexRef.current - 1);
      } else if (e.key === "Home") { goto(0); }
      else if (e.key === "End") { goto(total - 1); }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [goto, total]);

  const slide = slides[index];
  const content = React.createElement(SlideFitter, { fitKey: slide.id + "-" + replay }, renderSlide(slide));

  const animated = React.createElement(
    AnimatePresence,
    { mode: "wait" },
    React.createElement(
      motion.div,
      {
        key: slide.id + "-" + replay,
        style: { position: "absolute", inset: 0, zIndex: 10, transformOrigin: "50% 50%" },
        initial: { opacity: 0, scale: 0.82, filter: "blur(16px)" },
        ...slideTransition,
      },
      content
    )
  );

  // When animation can't run (hidden tab, reduced motion, print) AnimatePresence
  // mode="wait" would stall on the paused exit animation — render a plain,
  // instant swap instead so navigation always works and content is visible.
  const staticSwap = React.createElement(
    "div",
    { key: slide.id, style: { position: "absolute", inset: 0, zIndex: 10 } },
    content
  );

  return React.createElement(
    React.Fragment,
    null,
    React.createElement(Background, null),
    window.__animOK ? animated : staticSwap,
    React.createElement(Chrome, {
      index, total,
      onPrev: prev, onNext: next, onGoto: goto,
      isDark, onToggleTheme: toggleTheme,
    })
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(App));