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

// ---------- Router (hash-based) ----------
const RouterCtx = createContext({ path: "/", go: () => {} });

function RouterProvider({ children }) {
  const [path, setPath] = useState(() => (window.location.hash || "#/").replace(/^#/, "") || "/");
  useEffect(() => {
    const onHash = () => {
      const next = (window.location.hash || "#/").replace(/^#/, "") || "/";
      setPath(next);
      window.scrollTo({ top: 0, behavior: "instant" });
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  const go = useCallback((to) => {
    if (to.startsWith("#")) to = to.slice(1);
    window.location.hash = "#" + to;
  }, []);
  return <RouterCtx.Provider value={{ path, go }}>{children}</RouterCtx.Provider>;
}
const useRouter = () => useContext(RouterCtx);

function Link({ to, className, children, onClick, ...rest }) {
  const { go } = useRouter();
  return (
    <a
      href={"#" + to}
      className={className}
      onClick={(e) => { e.preventDefault(); onClick && onClick(e); go(to); }}
      {...rest}
    >{children}</a>
  );
}

// ---------- Booking context ----------
const BookingCtx = createContext({ open: () => {}, close: () => {}, isOpen: false });
const useBooking = () => useContext(BookingCtx);

// ---------- IntersectionObserver hook ----------
function useInView(opts = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setInView(true);
            if (opts.once !== false) io.unobserve(e.target);
          } else if (opts.once === false) {
            setInView(false);
          }
        });
      },
      { threshold: opts.threshold ?? 0.18, rootMargin: opts.rootMargin ?? "0px 0px -8% 0px" }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [opts.once, opts.threshold, opts.rootMargin]);
  return [ref, inView];
}

// ---------- Reveal wrapper ----------
function Reveal({ as: Tag = "div", kind = "reveal", className = "", style, children, delay = 0, ...rest }) {
  const [ref, inView] = useInView({ threshold: 0.18 });
  const cls = [kind, inView ? "in" : "", className].filter(Boolean).join(" ");
  const st = { ...(style || {}), transitionDelay: delay ? `${delay}ms` : undefined };
  return <Tag ref={ref} className={cls} style={st} {...rest}>{children}</Tag>;
}

// ---------- Word mask reveal — splits text by word ----------
function WordReveal({ text, className = "", as: Tag = "span", baseDelay = 0, perWord = 60, style }) {
  const [ref, inView] = useInView({ threshold: 0.2 });
  const words = useMemo(() => text.split(/(\s+)/), [text]); // keep whitespace
  return (
    <Tag ref={ref} className={[inView ? "in" : "", className].join(" ")} style={style}>
      {words.map((w, i) =>
        /^\s+$/.test(w) ? (
          <span key={i}>{w}</span>
        ) : (
          <span key={i} className="word-mask">
            <span style={{ "--d": `${baseDelay + i * perWord}ms` }}>{w}</span>
          </span>
        )
      )}
    </Tag>
  );
}

// ---------- Magnetic button wrapper ----------
function Magnetic({ children, strength = 0.35, className = "", ...rest }) {
  const ref = useRef(null);
  const innerRef = useRef(null);
  useEffect(() => {
    const el = ref.current;
    const inner = innerRef.current;
    if (!el || !inner) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const x = e.clientX - r.left - r.width / 2;
      const y = e.clientY - r.top - r.height / 2;
      el.style.transform = `translate(${x * strength}px, ${y * strength}px)`;
      inner.style.transform = `translate(${x * strength * 0.45}px, ${y * strength * 0.45}px)`;
    };
    const onLeave = () => {
      el.style.transform = "";
      inner.style.transform = "";
    };
    const parent = el.parentElement;
    parent.addEventListener("mousemove", onMove);
    parent.addEventListener("mouseleave", onLeave);
    return () => {
      parent.removeEventListener("mousemove", onMove);
      parent.removeEventListener("mouseleave", onLeave);
    };
  }, [strength]);
  return (
    <span ref={ref} className={["magnetic", className].join(" ")} {...rest}>
      <span ref={innerRef} className="magnetic-inner">{children}</span>
    </span>
  );
}

// ---------- Cursor follower ----------
function CursorFollower() {
  const ref = useRef(null);
  useEffect(() => {
    const dot = ref.current;
    if (!dot) return;
    let raf = 0;
    let tx = 0, ty = 0, x = 0, y = 0;
    const move = (e) => {
      tx = e.clientX; ty = e.clientY;
      dot.classList.add("active");
      const t = e.target;
      const hovering = t.closest && t.closest("[data-magnetic], button, a, .btn-coral, .btn-ghost");
      dot.classList.toggle("hover", !!hovering);
    };
    const tick = () => {
      x += (tx - x) * 0.18;
      y += (ty - y) * 0.18;
      dot.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    const leave = () => dot.classList.remove("active");
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseleave", leave);
    raf = requestAnimationFrame(tick);
    return () => {
      window.removeEventListener("mousemove", move);
      window.removeEventListener("mouseleave", leave);
      cancelAnimationFrame(raf);
    };
  }, []);
  return <div ref={ref} className="cursor-dot" />;
}

// ---------- Arrow icon ----------
function Arrow({ size = 14, style }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={style} aria-hidden>
      <path d="M2 7h10M8 3l4 4-4 4" />
    </svg>
  );
}

// ---------- Spike mark (brand glyph) ----------
function SpikeMark({ size = 18, style, color }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" style={style} aria-hidden>
      <g fill={color || "currentColor"}>
        <path d="M11.2 2 h1.6 v9.2 h-1.6 z"/>
        <path d="M11.2 12.8 h1.6 v9.2 h-1.6 z"/>
        <path d="M2 11.2 h9.2 v1.6 h-9.2 z"/>
        <path d="M12.8 11.2 h9.2 v1.6 h-9.2 z"/>
        <path d="M5.05 4.05 l6.5 6.5 -1.13 1.13 -6.5 -6.5 z"/>
        <path d="M13.58 12.58 l6.5 6.5 -1.13 1.13 -6.5 -6.5 z"/>
        <path d="M18.95 4.05 l1.13 1.13 -6.5 6.5 -1.13 -1.13 z"/>
        <path d="M10.42 12.58 l1.13 1.13 -6.5 6.5 -1.13 -1.13 z"/>
      </g>
    </svg>
  );
}

// ---------- Service icon set (line, 1.5px stroke) ----------
const ServiceIcon = ({ name, size = 28 }) => {
  const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true };
  switch (name) {
    case "consulting": return (<svg {...props}><path d="M4 19V8l8-5 8 5v11"/><path d="M9 19v-6h6v6"/><circle cx="12" cy="11" r="1"/></svg>);
    case "agile": return (<svg {...props}><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg>);
    case "appdev": return (<svg {...props}><rect x="3" y="4" width="18" height="14" rx="2"/><path d="M8 9l-3 3 3 3"/><path d="M16 9l3 3-3 3"/><path d="M14 8l-4 8"/></svg>);
    case "cloud": return (<svg {...props}><path d="M7 18a5 5 0 0 1-1-9.9 6 6 0 0 1 11.5 1.4A4 4 0 0 1 17 18z"/><path d="M12 12v5M9.5 14.5L12 12l2.5 2.5"/></svg>);
    case "security": return (<svg {...props}><path d="M12 3l8 3v5c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z"/><path d="M9 12l2 2 4-4"/></svg>);
    case "managed": return (<svg {...props}><circle cx="12" cy="12" r="3"/><path d="M19 12a7 7 0 0 0-.1-1.2l2-1.5-2-3.4-2.3.9a7 7 0 0 0-2-1.2L14 3h-4l-.6 2.6a7 7 0 0 0-2 1.2L5.1 6 3.1 9.4l2 1.5A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.5 2 3.4 2.3-.9a7 7 0 0 0 2 1.2L10 21h4l.6-2.6a7 7 0 0 0 2-1.2l2.3.9 2-3.4-2-1.5c.1-.4.1-.8.1-1.2z"/></svg>);
    case "bfsi": return (<svg {...props}><path d="M3 10l9-6 9 6"/><path d="M5 10v8M9 10v8M15 10v8M19 10v8"/><path d="M3 20h18"/></svg>);
    case "health": return (<svg {...props}><path d="M3 12h4l2-5 4 10 2-5h6"/></svg>);
    case "retail": return (<svg {...props}><path d="M3 8h18l-1.5 11a2 2 0 0 1-2 1.7H6.5a2 2 0 0 1-2-1.7z"/><path d="M8 8V6a4 4 0 0 1 8 0v2"/></svg>);
    case "manufact": return (<svg {...props}><path d="M3 21V11l5 3V11l5 3V11l5 3v7z"/><path d="M3 21h18"/></svg>);
    case "startup": return (<svg {...props}><path d="M5 19c2-6 7-11 13-13-2 6-7 11-13 13z"/><circle cx="14" cy="10" r="2"/><path d="M5 19c1.5-1.5 1.5-3.5 0-5"/></svg>);
    case "enterprise": return (<svg {...props}><rect x="3" y="9" width="7" height="12"/><rect x="14" y="3" width="7" height="18"/><path d="M5 13h3M5 17h3M16 7h3M16 11h3M16 15h3M16 19h3"/></svg>);
    case "arrow-ne": return (<svg {...props}><path d="M7 17L17 7M9 7h8v8"/></svg>);
    case "play": return (<svg {...props}><polygon points="6 4 20 12 6 20 6 4" fill="currentColor"/></svg>);
    case "check": return (<svg {...props}><path d="M5 12l4 4 10-10"/></svg>);
    case "plus": return (<svg {...props}><path d="M12 5v14M5 12h14"/></svg>);
    default: return null;
  }
};

// ---------- Section wrapper ----------
function Section({ id, dark, tight, className = "", children, style }) {
  return (
    <section
      id={id}
      data-screen-label={id}
      className={[dark ? "dark" : "", tight ? "section-tight" : "section", className].filter(Boolean).join(" ")}
      style={style}
    >
      <div className="container">{children}</div>
    </section>
  );
}

// ---------- Page transition curtain ----------
function PageCurtain({ keyId }) {
  return <div className="page-curtain" key={keyId} />;
}

Object.assign(window, {
  RouterProvider, useRouter, Link, BookingCtx, useBooking,
  useInView, Reveal, WordReveal, Magnetic, CursorFollower,
  Arrow, SpikeMark, ServiceIcon, Section, PageCurtain
});
