/* global React */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ============================================================
   useScrollRevealAll — adds .in class to .reveal nodes
============================================================ */
function useScrollReveal() {
  useEffect(() => {
    const io = new IntersectionObserver(
      (entries) => {
        for (const e of entries) {
          if (e.isIntersecting) {
            e.target.classList.add("in");
            io.unobserve(e.target);
          }
        }
      },
      { threshold: 0.08, rootMargin: "0px 0px -4% 0px" }
    );
    const observeAll = () => {
      document
        .querySelectorAll(".reveal:not(.in), .text-reveal:not(.in)")
        .forEach((el) => io.observe(el));
    };
    observeAll();
    // Re-observe whenever new nodes appear (route changes)
    const mo = new MutationObserver(observeAll);
    mo.observe(document.body, { childList: true, subtree: true });

    // Defensive fallback: if anything is still hidden after 1.5s, reveal it.
    const fallback = setTimeout(() => {
      document
        .querySelectorAll(".reveal:not(.in), .text-reveal:not(.in)")
        .forEach((el) => el.classList.add("in"));
    }, 1500);

    return () => {
      io.disconnect();
      mo.disconnect();
      clearTimeout(fallback);
    };
  }, []);
}

/* ============================================================
   TextReveal — splits text into words for stagger animation
   Handles string, number, array, and nested React-element children.
============================================================ */
function extractText(node) {
  if (node == null || typeof node === "boolean") return "";
  if (typeof node === "string" || typeof node === "number") return String(node);
  if (Array.isArray(node)) return node.map(extractText).join("");
  if (node.props && node.props.children !== undefined) return extractText(node.props.children);
  return "";
}

function TextReveal({ children, as: Tag = "span", className = "", delay = 0 }) {
  const text = extractText(children);
  if (!text.trim()) {
    // No extractable text — fall back to a plain reveal wrapper
    return (
      <Tag className={`reveal ${className}`} data-delay={delay}>
        {children}
      </Tag>
    );
  }
  const words = text.split(/\s+/);
  return (
    <Tag className={`text-reveal reveal ${className}`} data-delay={delay}>
      {words.map((w, i) => (
        <React.Fragment key={i}>
          <span className="word" style={{ transitionDelay: `${i * 40}ms` }}>
            <span
              className="word-inner"
              style={{ transitionDelay: `${i * 40}ms` }}
            >
              {w}
            </span>
          </span>
          {i < words.length - 1 ? " " : ""}
        </React.Fragment>
      ))}
    </Tag>
  );
}

/* ============================================================
   Navbar
============================================================ */
function Navbar({ route, setRoute }) {
  const [scrolled, setScrolled] = useState(false);
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const f = () => setScrolled(window.scrollY > 24);
    f();
    window.addEventListener("scroll", f, { passive: true });
    return () => window.removeEventListener("scroll", f);
  }, []);

  const links = [
    { id: "home", label: "Home" },
    { id: "services", label: "Services" },
    { id: "vision", label: "Vision" },
    { id: "about", label: "About" },
    { id: "team", label: "Team" },
    { id: "careers", label: "Careers" },
    { id: "partners", label: "Partners" },
    { id: "faq", label: "FAQ" },
    { id: "contact", label: "Contact" },
  ];

  const go = (id) => {
    setRoute(id);
    setOpen(false);
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  return (
    <nav className={`nav ${scrolled ? "scrolled" : ""} ${open ? "open" : ""}`}>
      <a
        href="#"
        className="nav-brand"
        onClick={(e) => {
          e.preventDefault();
          go("home");
        }}
      >
        <img src="assets/logo.png" alt="PrintBala" style={{ height: 32, width: "auto", display: "block" }} />
      </a>
      <div className="nav-links">
        {links.map((l) => (
          <a
            key={l.id}
            href="#"
            className={`nav-link ${route === l.id ? "active" : ""}`}
            onClick={(e) => {
              e.preventDefault();
              go(l.id);
            }}
          >
            {l.label}
          </a>
        ))}
      </div>
      <div className="nav-cta">
        <a
          href="https://www.printbala.com/app/#/login"
          target="_blank"
          rel="noopener"
          className="btn btn-ghost"
        >
          Log in
        </a>
        <a
          href="https://www.printbala.com/app/#/registerpress"
          target="_blank"
          rel="noopener"
          className="btn btn-primary"
        >
          Join us
        </a>
      </div>
      <button
        className="nav-toggle"
        onClick={() => setOpen((v) => !v)}
        aria-label="menu"
      >
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          {open ? (
            <>
              <line x1="6" y1="6" x2="18" y2="18" />
              <line x1="18" y1="6" x2="6" y2="18" />
            </>
          ) : (
            <>
              <line x1="4" y1="7" x2="20" y2="7" />
              <line x1="4" y1="12" x2="20" y2="12" />
              <line x1="4" y1="17" x2="20" y2="17" />
            </>
          )}
        </svg>
      </button>
    </nav>
  );
}

/* ============================================================
   Marquee
============================================================ */
function Marquee({ items, dot = true }) {
  const group = (key) => (
    <div className="marquee-item" key={key}>
      {items.map((it, i) => (
        <React.Fragment key={i}>
          <span>{it}</span>
          {dot ? <span className="dot" /> : <span>·</span>}
        </React.Fragment>
      ))}
    </div>
  );
  return (
    <div className="marquee">
      <div className="marquee-track">
        {group("a")}
        {group("b")}
      </div>
    </div>
  );
}

/* ============================================================
   Placeholder image
============================================================ */
function Ph({ tag, kind = "" }) {
  return <div className={`ph ${kind}`}>{tag || "image"}</div>;
}

/* ============================================================
   Img — real photo with cover-fit, lazy loading
============================================================ */
function Img({ src, alt = "", style = {}, position = "center" }) {
  const [errored, setErrored] = React.useState(false);
  if (errored || !src) {
    return <div className="ph ph-accent" style={{ width: "100%", height: "100%" }}>{alt}</div>;
  }
  return (
    <img
      src={src}
      alt={alt}
      loading="lazy"
      onError={() => setErrored(true)}
      style={{
        width: "100%",
        height: "100%",
        objectFit: "cover",
        objectPosition: position,
        display: "block",
        ...style,
      }}
    />
  );
}

/* Curated photo bank — every key resolves to a distinct local file. */
const PHOTOS = {
  // === Product photos (12 + 2 misc, all distinct) ===
  cards:        "assets/products/gloss-card.png",
  idcard:       "assets/products/idcard.webp",
  envelope:     "assets/products/envelop.png",
  pamphlet:     "assets/products/pamplate.png",
  digitalpaper: "assets/products/digitalpaper.png",
  rollup:       "assets/products/rollup.jpg",
  canopy:       "assets/products/canopy.png",
  sunpack:      "assets/products/sunpack.webp",
  stickers:     "assets/products/stickers.webp",
  pen:          "assets/products/pen.png",
  medical:      "assets/products/medical.jpg",
  sample:       "assets/products/sample.jpg",
  hero:         "assets/hero-img-1.png",
  features:     "assets/features-1.png",

  // === Environment / category aliases ===
  // Each alias points to a DIFFERENT file than the others used in the same section.
  press:        "assets/hero-img-1.png",            // hero only
  pressFloor:   "assets/features-1.png",            // culture #1
  inkRollers:   "assets/products/sample.jpg",       // culture #2
  meeting:      "assets/team/Umesh.png",            // culture #3
  team:         "assets/team/Bhanu.png",            // culture #4

  colorSwatch:  "assets/products/sample.jpg",       // press kit #1
  paperStack:   "assets/products/digitalpaper.png", // press kit #2 (pressFloor reused here, but uniquely within kit)
  founder:      "assets/team/PratapSingh.png",      // press kit #5 + about-founder

  brochure:     "assets/products/medical.jpg",      // featured + catalog brochure
  packaging:    "assets/products/sunpack.webp",     // featured + catalog packaging
  poster:       "assets/features-1.png",            // catalog pamphlets

  // Unused — kept for safety
  warehouse:    "assets/products/canopy.png",
  delivery:     "assets/products/rollup.jpg",
  designer:     "assets/team/shivam.png",
  bookbinding:  "assets/products/idcard.webp",
};

/* ============================================================
   Counter (animates when in view)
============================================================ */
function Counter({ to, suffix = "", duration = 1400 }) {
  const ref = useRef(null);
  const [val, setVal] = useState(0);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf;
    const io = new IntersectionObserver((entries) => {
      for (const e of entries) {
        if (e.isIntersecting) {
          const start = performance.now();
          const step = (t) => {
            const p = Math.min(1, (t - start) / duration);
            const eased = 1 - Math.pow(1 - p, 3);
            setVal(Math.round(to * eased));
            if (p < 1) raf = requestAnimationFrame(step);
          };
          raf = requestAnimationFrame(step);
          io.unobserve(el);
        }
      }
    });
    io.observe(el);
    return () => {
      io.disconnect();
      cancelAnimationFrame(raf);
    };
  }, [to, duration]);
  return (
    <span ref={ref}>
      {val.toLocaleString("en-IN")}
      <small>{suffix}</small>
    </span>
  );
}

/* ============================================================
   Section head
============================================================ */
function SectionHead({ eyebrow, title, sub, align = "split" }) {
  if (align === "center") {
    return (
      <div style={{ textAlign: "center", marginBottom: 64 }} className="reveal">
        {eyebrow && <div className="eyebrow no-line" style={{ marginBottom: 16 }}>{eyebrow}</div>}
        <h2 style={{ fontSize: "clamp(36px,5vw,72px)", maxWidth: "16ch", margin: "0 auto" }}>{title}</h2>
        {sub && <p style={{ color: "var(--ink-3)", marginTop: 20, fontSize: 18, maxWidth: 600, marginInline: "auto" }}>{sub}</p>}
      </div>
    );
  }
  return (
    <div className="section-head">
      <div>
        {eyebrow && <div className="eyebrow reveal" style={{ marginBottom: 20 }}>{eyebrow}</div>}
        <TextReveal as="h2">{title}</TextReveal>
      </div>
      {sub && <p className="reveal" data-delay="2">{sub}</p>}
    </div>
  );
}

/* ============================================================
   Footer
============================================================ */
function Footer({ setRoute }) {
  const link = (id, label) => (
    <a href="#" onClick={(e) => { e.preventDefault(); setRoute(id); window.scrollTo({ top: 0, behavior: "smooth" }); }}>
      {label}
    </a>
  );
  return (
    <footer className="footer">
      <div className="container">
        <TextReveal as="h2">Let's print something extraordinary.</TextReveal>
        <div style={{ display: "flex", gap: 12, flexWrap: "wrap" }} className="reveal" data-delay="2">
          <a href="#" className="btn btn-accent" onClick={(e) => { e.preventDefault(); setRoute("contact"); window.scrollTo(0, 0); }}>
            Start your project
            <svg className="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
          </a>
          <a href="#" className="btn btn-ghost" style={{ borderColor: "rgba(255,255,255,0.2)", color: "#fff" }} onClick={(e) => { e.preventDefault(); setRoute("partners"); window.scrollTo(0, 0); }}>
            Become a partner
          </a>
        </div>

        <div className="footer-grid">
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 20 }}>
              <span style={{ width: 36, height: 36, borderRadius: 10, background: "var(--accent)", display: "grid", placeItems: "center", fontFamily: "var(--font-display)", fontWeight: 800, fontSize: 18, color: "var(--accent-ink)" }}>P</span>
              <span style={{ fontFamily: "var(--font-display)", fontWeight: 700, fontSize: 22, color: "#fff" }}>PrintBala</span>
            </div>
            <p style={{ color: "rgba(255,255,255,0.6)", maxWidth: 320, fontSize: 14 }}>
              Printbala Print World Pvt. Ltd. — a nationwide network of premium printers, serving businesses across India since 2018.
            </p>
            <div style={{ marginTop: 24, display: "flex", gap: 10 }}>
              <a href="https://www.facebook.com/profile.php?id=100090775575148&mibextid=ZbWKwL" target="_blank" rel="noopener" aria-label="Facebook" style={{ width: 36, height: 36, borderRadius: "50%", border: "1px solid rgba(255,255,255,0.15)", display: "grid", placeItems: "center", color: "rgba(255,255,255,0.85)" }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 22v-9h3l.5-4h-3.5V6.5c0-1.2.3-2 2-2H17V1.1c-.3 0-1.4-.1-2.7-.1-2.6 0-4.4 1.6-4.4 4.5V9H6.5v4H10v9h3.5z"/></svg>
              </a>
              <a href="https://www.youtube.com/@PRINTBALAPRINT" target="_blank" rel="noopener" aria-label="YouTube" style={{ width: 36, height: 36, borderRadius: "50%", border: "1px solid rgba(255,255,255,0.15)", display: "grid", placeItems: "center", color: "rgba(255,255,255,0.85)" }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M22.5 6.4c-.3-1-1-1.7-2-2C18.6 4 12 4 12 4s-6.6 0-8.5.4c-1 .3-1.7 1-2 2C1.1 8.3 1.1 12 1.1 12s0 3.7.4 5.6c.3 1 1 1.7 2 2 1.9.4 8.5.4 8.5.4s6.6 0 8.5-.4c1-.3 1.7-1 2-2 .4-1.9.4-5.6.4-5.6s0-3.7-.4-5.6zM9.8 15.6V8.4l5.7 3.6-5.7 3.6z"/></svg>
              </a>
              <a href="https://www.instagram.com/_printbala?igsh=MXR1aDQ1Mmc3bTVkag%3D%3D" target="_blank" rel="noopener" aria-label="Instagram" style={{ width: 36, height: 36, borderRadius: "50%", border: "1px solid rgba(255,255,255,0.15)", display: "grid", placeItems: "center", color: "rgba(255,255,255,0.85)" }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor"/></svg>
              </a>
            </div>
          </div>
          <div>
            <h5>Company</h5>
            <ul className="footer-links">
              <li>{link("about", "About")}</li>
              <li>{link("vision", "Our Vision")}</li>
              <li>{link("team", "Our Team")}</li>
              <li>{link("careers", "Careers")}</li>
              <li>{link("partners", "Press & partners")}</li>
            </ul>
          </div>
          <div>
            <h5>Account</h5>
            <ul className="footer-links">
              <li><a href="https://www.printbala.com/app/#/login" target="_blank" rel="noopener">Log in</a></li>
              <li><a href="https://www.printbala.com/app/#/registerpress" target="_blank" rel="noopener">Join as printing press</a></li>
              <li><a href="https://www.printbala.com/app/#/registerdist" target="_blank" rel="noopener">Join as distributor</a></li>
              <li>{link("partners", "Partner programmes")}</li>
            </ul>
          </div>
          <div>
            <h5>Support</h5>
            <ul className="footer-links">
              <li>{link("faq", "FAQ")}</li>
              <li>{link("contact", "Contact")}</li>
              <li><a href="tel:+918077996040">+91 80779 96040</a></li>
              <li><a href="mailto:contact@printbala.com">contact@printbala.com</a></li>
            </ul>
          </div>
        </div>

        <div className="footer-bottom">
          <span>© 2026 Printbala Print World Pvt. Ltd. · Etawah, Uttar Pradesh, India</span>
          <span className="mono">v3.0 · Print Engine</span>
        </div>
      </div>
    </footer>
  );
}

/* ============================================================
   Cursor blob effect
============================================================ */
function useCursorBlob() {
  useEffect(() => {
    const el = document.getElementById("cursor");
    if (!el) return;
    let x = 0, y = 0, tx = 0, ty = 0, raf;
    const move = (e) => {
      tx = e.clientX;
      ty = e.clientY;
      el.style.opacity = "0.85";
    };
    const leave = () => { el.style.opacity = "0"; };
    const enterLink = () => { el.style.width = "60px"; el.style.height = "60px"; };
    const leaveLink = () => { el.style.width = "28px"; el.style.height = "28px"; };
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseleave", leave);
    const links = () => document.querySelectorAll("a, button, .product-card, .service-card, .job, .team-card");
    const refresh = () => {
      links().forEach((l) => {
        l.addEventListener("mouseenter", enterLink);
        l.addEventListener("mouseleave", leaveLink);
      });
    };
    refresh();
    const mo = new MutationObserver(refresh);
    mo.observe(document.body, { childList: true, subtree: true });

    const loop = () => {
      x += (tx - x) * 0.18;
      y += (ty - y) * 0.18;
      el.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(loop);
    };
    loop();
    return () => {
      window.removeEventListener("mousemove", move);
      window.removeEventListener("mouseleave", leave);
      mo.disconnect();
      cancelAnimationFrame(raf);
    };
  }, []);
}

/* ============================================================
   Sticky scroll sequence
============================================================ */
function StickyScroll({ steps, render }) {
  const [active, setActive] = useState(0);
  const refs = useRef([]);

  useEffect(() => {
    const observers = refs.current.map((el, i) => {
      const io = new IntersectionObserver(
        (entries) => {
          for (const e of entries) {
            if (e.isIntersecting) setActive(i);
          }
        },
        { threshold: 0.6 }
      );
      if (el) io.observe(el);
      return io;
    });
    return () => observers.forEach((o) => o.disconnect());
  }, [steps]);

  return (
    <div className="sticky-sequence">
      <div className="sticky-sequence-inner">
        <div className="sticky-canvas">
          {steps.map((s, i) => (
            <div key={i} className={`sticky-frame ${active === i ? "active" : ""}`}>
              {render(s, i, active === i)}
            </div>
          ))}
        </div>
        <div className="sticky-steps">
          {steps.map((s, i) => (
            <div
              key={i}
              ref={(el) => (refs.current[i] = el)}
              className={`sticky-step ${active === i ? "active" : ""}`}
              onClick={() => setActive(i)}
            >
              <div className="num">Step {String(i + 1).padStart(2, "0")} / {String(steps.length).padStart(2, "0")}</div>
              <h3>{s.title}</h3>
              <p>{s.body}</p>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  useScrollReveal, useCursorBlob,
  TextReveal, Navbar, Marquee, Ph, Img, PHOTOS, Counter, SectionHead, Footer, StickyScroll,
});
