/* ============================================================
   APP ROOT + FOOTER + TWEAKS
   ============================================================ */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "orgAccent": "#3B5BFF",
  "heroLayout": "slideshow",
  "homeExtras": true,
  "statsStyle": "underline",
  "cardShape": "square"
}/*EDITMODE-END*/;

function darkenHex(hex, amount = 0.22) {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  const d = (v) => Math.round(v * (1 - amount)).toString(16).padStart(2, "0");
  return "#" + d(r) + d(g) + d(b);
}

/* ---- scroll progress bar (telemetry stripe under the navbar) ---- */
function ScrollProgress() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onScroll = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      el.style.transform = "scaleX(" + (max > 0 ? window.scrollY / max : 0) + ")";
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    onScroll();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);
  return <div ref={ref} className="scroll-progress" aria-hidden="true"></div>;
}

/* ---- back to top ---- */
function BackToTop() {
  const [show, setShow] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setShow(window.scrollY > 600);
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return (
    <button className={"back-top" + (show ? " show" : "")} aria-label="Back to top"
      onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}>
      <span style={{ display: "grid", transform: "rotate(-90deg)" }}><Icon name="arrow" size={18} /></span>
    </button>
  );
}

/* ---- auto scroll-reveal: tags content blocks and fades them in on scroll ---- */
function useAutoReveal(dep) {
  React.useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let io, raf;
    const timers = [];
    const els = [];
    raf = requestAnimationFrame(() => {
      const root = document.querySelector("main");
      if (!root) return;
      const SEL = [
        "[data-reveal]", ".sec-title", ".eyebrow", ".card", ".ph",
        ".title-sponsor-grid > div", ".crew-grid > div:first-child", ".stats-grid > div",
        "h1", "h2", "h3", "p", "ul", "img", ".btn",
      ].join(", ");
      root.querySelectorAll(SEL).forEach((el) => {
        if (el.classList.contains("hero-bg")) return;
        if (el.closest(".hero-grid") || el.closest(".marquee") || el.closest(".acc-body")) return;
        if (el.parentElement && el.parentElement.closest(".rv")) return; // ancestor already reveals
        el.classList.add("rv");
        els.push(el);
      });
      io = new IntersectionObserver((entries) => {
        const vis = entries.filter((e) => e.isIntersecting);
        vis.forEach((e, i) => {
          const el = e.target;
          const d = Math.min(i * 70, 420);
          el.style.setProperty("--rv-d", d + "ms");
          el.classList.add("rv-in");
          io.unobserve(el);
          // clean up classes after the transition so hover transitions return to normal
          timers.push(setTimeout(() => {
            el.classList.remove("rv", "rv-in");
            el.style.removeProperty("--rv-d");
          }, d + 1050));
        });
      }, { threshold: 0, rootMargin: "0px 0px -8% 0px" });
      els.forEach((el) => io.observe(el));
    });
    return () => {
      cancelAnimationFrame(raf);
      if (io) io.disconnect();
      timers.forEach(clearTimeout);
      els.forEach((el) => {
        el.classList.remove("rv", "rv-in");
        el.style.removeProperty("--rv-d");
      });
    };
  }, [dep]);
}

function Footer({ go }) {
  return (
    <footer style={{ borderTop: "1px solid var(--border)", background: "var(--bg)" }}>
      <div className="wrap" style={{ paddingTop: 56, paddingBottom: 40 }}>
        <div className="footer-grid" style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr", gap: 40, alignItems: "start" }}>
          <div>
            <Logo team={ORG} onClick={() => { go("home"); window.scrollTo({ top: 0 }); }} />
            <p className="body muted" style={{ fontSize: 14, lineHeight: 1.65, margin: "20px 0 0", maxWidth: 360 }}>
              {ORG.footerBlurb}
              <br /><br />
              Designed by - @lakhberg
            </p>

          </div>
          <div>
            <div className="label" style={{ fontSize: 13, color: "var(--orange)", marginBottom: 18 }}>Explore</div>
            <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 12 }}>
              {[["Home","home"],["Team","team"],["Our Legacy","achievements"],["Our Sponsors","crowdfunding"],["About","about"],["Contact","contact"]].map(([l, id], i) => (
                <li key={i}><button onClick={() => { go(id); window.scrollTo({top:0}); }} className="head foot-link"
                  style={{ background: "none", border: "none", padding: 0, fontSize: 19, color: "var(--text)", letterSpacing: "0.03em" }}>{l}</button></li>
              ))}
            </ul>
          </div>
          <div>
            <div className="label" style={{ fontSize: 13, color: "var(--orange)", marginBottom: 18 }}>Campus</div>
            <p className="body muted" style={{ fontSize: 14, lineHeight: 1.7, margin: 0 }}>
              {ORG.locationName}<br/>{ORG.locationLines.map((ln, i) => <React.Fragment key={i}>{ln}<br/></React.Fragment>)}<br/>
              <span style={{ color: "var(--text)" }}>{ORG.email}</span>
            </p>
          </div>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 48, paddingTop: 24, borderTop: "1px solid var(--border)", flexWrap: "wrap", gap: 12 }}>
          <span className="body" style={{ fontSize: 13, color: "var(--muted-2)" }}>&copy; 2026 SGSITS Indore · Student Engineering Teams. All rights reserved.</span>
          <span className="label" style={{ fontSize: 12, color: "var(--muted-2)" }}>{ORG.footerTag}</span>
        </div>
      </div>
    </footer>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const PAGES = ["home","team","achievements","crowdfunding","about","contact"];
  const TEAM_PAGES = ["team","achievements"];   // pages that carry an in-page team selector

  const savedTeam = (() => { try { const s = localStorage.getItem("gs-active-team"); return TEAMS[s] ? s : null; } catch (e) { return null; } })();

  const parseHash = () => {
    const h = (location.hash || "").replace(/^#/, "");
    const parts = h.split("/");
    const page = PAGES.includes(parts[0]) ? parts[0] : "home";
    const team = TEAMS[parts[1]] ? parts[1] : null;
    return { page, team };
  };

  const init = parseHash();
  const [page, setPage] = React.useState(init.page);
  const [selectedTeam, setSelectedTeam] = React.useState(init.team || savedTeam || "gsm");

  const persist = (id) => { try { localStorage.setItem("gs-active-team", id); } catch (e) {} };

  const go = (p) => {
    if (p === page && !TEAM_PAGES.includes(p)) { window.scrollTo({ top: 0, behavior: "smooth" }); return; }
    setPage(p);
    history.pushState(null, "", "#" + p + (TEAM_PAGES.includes(p) ? "/" + selectedTeam : ""));
  };

  // pick a team from the in-page selector (stays on current page)
  const selectTeam = (id) => {
    if (id === selectedTeam) return;
    setSelectedTeam(id);
    persist(id);
    if (TEAM_PAGES.includes(page)) history.replaceState(null, "", "#" + page + "/" + id);
  };

  // enter a team from the home showcase → its Team page
  const enterTeam = (id) => {
    setSelectedTeam(id); persist(id);
    setPage("team");
    history.pushState(null, "", "#team/" + id);
    window.scrollTo({ top: 0 });
  };

  // route drives the page-transition + content swap
  const isTeamPage = TEAM_PAGES.includes(page);
  const route = isTeamPage ? page + "/" + selectedTeam : page;
  const [displayRoute, setDisplayRoute] = React.useState(route);
  const [phase, setPhase] = React.useState("in");
  const reduce = typeof window !== "undefined" &&
    window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  React.useEffect(() => {
    if (route === displayRoute) return;
    if (reduce) { setDisplayRoute(route); window.scrollTo({ top: 0 }); return; }
    setPhase("out");
    const tm = setTimeout(() => {
      setDisplayRoute(route);
      window.scrollTo({ top: 0 });
      setPhase("in");
    }, 190);
    return () => clearTimeout(tm);
  }, [route]);

  React.useEffect(() => {
    const onHash = () => { const p = parseHash(); setPage(p.page); if (p.team) setSelectedTeam(p.team); };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  const dParts = displayRoute.split("/");
  const dPage = dParts[0];
  const dTeam = TEAM_PAGES.includes(dPage) ? (dParts[1] || selectedTeam) : null;

  // accent + heading font follow the displayed team on team pages,
  // and the org (orange / default) on the common pages.
  // useLayoutEffect (not useEffect) so --orange is overwritten before the
  // browser paints — otherwise the CSS default (#FF6B00, orange) flashes for
  // a frame before this runs.
  React.useLayoutEffect(() => {
    const accent = dTeam ? TEAMS[dTeam].accent : t.orgAccent;
    const accentDim = dTeam ? TEAMS[dTeam].accentDim : darkenHex(t.orgAccent);
    document.documentElement.style.setProperty("--orange", accent);
    document.documentElement.style.setProperty("--orange-dim", accentDim);
    document.documentElement.setAttribute("data-team", dTeam || "org");
  }, [displayRoute, t.orgAccent]);

  const tweaks = { heroLayout: t.heroLayout, homeExtras: t.homeExtras, statsStyle: t.statsStyle, cardShape: t.cardShape };
  useAutoReveal(displayRoute);

  const renderPage = () => {
    const gsm = dTeam === "gsm";
    const teamCfg = dTeam ? TEAMS[dTeam] : null;
    const props = { go, t: tweaks, team: teamCfg };
    switch (dPage) {
      case "home":         return <OrgHomePage go={go} enterTeam={enterTeam} t={tweaks} />;
      case "crowdfunding": return <CrowdfundingPage go={go} t={tweaks} />;
      case "about":        return <AboutPage go={go} t={tweaks} enterTeam={enterTeam} />;
      case "contact":      return <ContactPage go={go} t={tweaks} />;
      case "alumni":       return <AlumniPage go={go} t={tweaks} />;
      case "team":         return gsm ? <TeamPage {...props} />         : <ScaffoldTeam {...props} />;
      case "achievements": return gsm ? <AchievementsPage {...props} /> : <ScaffoldLegacy {...props} />;
      default:             return <OrgHomePage go={go} enterTeam={enterTeam} />;
    }
  };

  const showSwitch = TEAM_PAGES.includes(dPage);

  return (
    <React.Fragment>
      <ScrollProgress />
      <Navbar page={page} go={go} />
      {showSwitch && <TeamSwitchBar selected={dTeam} onSelect={selectTeam} />}
      <div key={displayRoute} className={"page-anim " + phase}>
        {renderPage()}
      </div>
      <Footer go={go} />
      <BackToTop />

      <TweaksPanel>
        <TweakSection label="Org Pages — Accent" />
        <TweakColor label="Color" value={t.orgAccent}
          onChange={(v) => setTweak("orgAccent", v)} />
        <TweakSection label="Home — Hero" />
        <TweakSelect label="Layout" value={t.heroLayout}
          options={["banner", "mosaic", "filmstrip", "slideshow"]}
          onChange={(v) => setTweak("heroLayout", v)} />
        <TweakToggle label="Show cards & stats" value={t.homeExtras !== false}
          onChange={(v) => setTweak("homeExtras", v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

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