/* ============ boot — runs LAST ============
   resolve district -> apply theme (pre-render, no FOUC) -> ensure a live dev session -> fetch the
   district bootstrap (config district row + live catalog + user) -> render <CoreApp/> inside the
   TenantProvider, with a review-aid district switcher and a backend-connection banner. */

function DistrictSwitcher({ current }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    function h(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  const keys = Object.keys(window.HARMONY_DISTRICTS);
  function pick(k) {
    localStorage.setItem("harmony.district", k);
    const p = new URLSearchParams(location.search);
    p.set("district", k);
    location.search = p.toString();          // hard reload re-runs the full boot (theme + catalog + session)
  }
  function toggleEmbed() {
    const p = new URLSearchParams(location.search);
    p.set("embed", window.resolveEmbedded() ? "0" : "1");
    location.search = p.toString();          // reload into/out of headerless embed mode
  }
  return (
    <div className="jumper" ref={ref} style={{ left: 18, right: "auto" }}>
      {open && (
        <div className="jumper-menu" style={{ left: 0, right: "auto" }}>
          <div className="jm-h">Switch district (review)</div>
          {keys.map((k, i) => (
            <button key={k} className={"jm-item" + (k === current ? " active" : "")} onClick={() => pick(k)}>
              <span className="jm-num">{i + 1}</span>{window.HARMONY_DISTRICTS[k].name}
            </button>
          ))}
          <div className="jm-h">Presentation</div>
          <button className={"jm-item" + (window.resolveEmbedded() ? " active" : "")} onClick={toggleEmbed}>
            <span className="jm-num">{window.resolveEmbedded() ? "✓" : ""}</span>Embedded (hide header/footer)
          </button>
        </div>
      )}
      <button className="jumper-btn" onClick={() => setOpen((v) => !v)}>
        <Icon name="grid" size={16} /> {window.HARMONY_DISTRICTS[current].name}
      </button>
    </div>
  );
}

function BootBanner({ error, apiBaseUrl }) {
  return (
    <div style={{
      position: "fixed", top: 0, left: 0, right: 0, zIndex: 200,
      background: "#7A1414", color: "#fff", padding: "10px 16px", fontSize: 13, fontWeight: 600,
      textAlign: "center", boxShadow: "0 2px 8px rgba(0,0,0,.25)"
    }}>
      Can’t reach the backend at <b>{apiBaseUrl}</b> ({error.message}). Run <b>npm run dev</b> in
      <b> backend/</b> and serve this folder over <b>http://localhost</b> (not file://). The screens
      stay empty until the catalog loads.
    </div>
  );
}

function isPlainObject(value) {
  return value && typeof value === "object" && !Array.isArray(value);
}

function deepMerge(base, override) {
  if (!isPlainObject(override)) return base;
  const out = Object.assign({}, base);
  Object.keys(override).forEach((key) => {
    const next = override[key];
    out[key] = isPlainObject(out[key]) && isPlainObject(next) ? deepMerge(out[key], next) : next;
  });
  return out;
}

function normalizeLaunchContext(raw, catalogData) {
  if (!raw) return null;

  const campuses = (catalogData && catalogData.campuses) || [];
  const campus = campuses.find((c) =>
    (raw.campusId && String(c.id) === String(raw.campusId)) ||
    (raw.campusRef && String(c.external_ref) === String(raw.campusRef))
  );

  return Object.assign({}, raw, {
    campusId: campus ? String(campus.id) : null,
    campusRef: campus ? String(campus.external_ref || campus.id) : null,
    campusName: campus ? campus.name : null,
    campusValid: !!campus,
    campusInvalid: !!(raw.campusId || raw.campusRef) && !campus
  });
}

function appEntryUrl(params) {
  const localStatic = location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.protocol === "file:";
  const url = new URL(localStatic ? "/" : "/app", location.origin);
  Object.keys(params || {}).forEach((key) => {
    if (params[key] != null && params[key] !== "") url.searchParams.set(key, params[key]);
  });
  if (localStatic) url.searchParams.set("app", "1");
  return url.pathname + url.search;
}

function localReviewHost() {
  return location.hostname === "localhost" || location.hostname === "127.0.0.1" || location.protocol === "file:";
}

function PlatformLanding({ config }) {
  const districtKey = config.key || "harmony";
  const districtName = config.name || "Harmony";
  const features = [
    { icon: "campus", title: "Campus-first shopping", text: "Families choose a campus first, then ecommerce receives the school context." },
    { icon: "parent", title: "Parent and student setup", text: "Role, student, and guardian relationships stay in one district-aware workflow." },
    { icon: "grid", title: "Multi-district ready", text: "Districts share one core app while branding, catalog, and commerce settings vary." },
    { icon: "shop", title: "Commerce adapters", text: "BigCommerce, Shopify, and BrightStores use the same redirect or iframe handoff boundary." },
    { icon: "key", title: "BrightStores auth bridge", text: "Custom-field keys authenticate users without exposing API secrets in storefront code." },
    { icon: "send", title: "Signed return context", text: "Campus and optional family context are validated before returning to the storefront." }
  ];
  return (
    <main className="platform-home">
      <nav className="platform-nav">
        <div className="logo-pill">
          <StarMark size={22} primary={config.branding.star.primary} secondary={config.branding.star.secondary} />
          <div className="logo-word">
            <b>{config.branding.wordmark.line1}</b>
            <b style={{ fontSize: "11.5px" }}>{config.branding.wordmark.line2}</b>
          </div>
        </div>
        <a className="btn btn-outline btn-sm" href={appEntryUrl({ district: districtKey, page: "school" })}>
          <Icon name="campus" size={16} /> Campus selector
        </a>
      </nav>

      <section className="platform-hero">
        <div className="platform-copy">
          <div className="eyebrow"><Icon name="sparkle" size={15} /> School Structurer Platform</div>
          <h1 className="platform-title">District-aware campus setup for ecommerce stores</h1>
          <p className="platform-sub">
            A shared app for school districts that collects campus, role, and family context before handing shoppers back to BigCommerce, Shopify, or BrightStores.
          </p>
          <div className="platform-actions">
            <a className="btn btn-primary" href={appEntryUrl({ district: districtKey, page: "school" })}>
              <Icon name="arrowR" size={18} /> Open {districtName} flow
            </a>
            <a className="btn btn-ghost" href={appEntryUrl({ district: districtKey, page: "manage-students" })}>
              <Icon name="parent" size={18} /> Manage students
            </a>
          </div>
        </div>
        <div className="platform-panel">
          <div className="platform-panel-head">
            <Icon name="shop" size={20} />
            <span>Launch examples</span>
          </div>
          <code>/app?district={districtKey}</code>
          <code>/app?district={districtKey}&amp;school=campus-ref</code>
          <code>/app?district={districtKey}&amp;school=campus-ref&amp;page=manage-students</code>
        </div>
      </section>

      <section className="platform-features">
        {features.map((feature) => (
          <article className="platform-feature" key={feature.title}>
            <span className="platform-feature-icon"><Icon name={feature.icon} size={21} /></span>
            <h2>{feature.title}</h2>
            <p>{feature.text}</p>
          </article>
        ))}
      </section>
    </main>
  );
}

(async function boot() {
  const key = window.resolveDistrictKey();
  const embedded = window.resolveEmbedded();
  let launchContext = window.resolveLaunchContext();
  if (embedded) document.body.classList.add("embed");
  let config = window.HARMONY_DISTRICTS[key] || window.HARMONY_DISTRICTS.harmony;

  // 1) theme + title FIRST, before any await, so the first paint is already district-skinned.
  window.applyTheme(config.theme);
  document.title = config.chrome.documentTitle;

  if (!window.isAppRoute()) {
    document.title = "School Structurer Platform";
    ReactDOM.createRoot(document.getElementById("root")).render(<PlatformLanding config={config} />);
    return;
  }

  const api = window.makeApi(config.apiBaseUrl, config.key);

  // 2) live data: bootstrap the district + catalog + user. Only mint a dev session if none exists yet.
  let catalogData = { regions: [], campuses: [], teachers: [], grades: [] };
  let user = null;
  let onboarding = { needsRole: true, needsProfile: false, needsFamily: false };
  let defaultCampus = null;
  let serverConfig = null;
  let runtime = null;
  let bootError = null;
  try {
    let boot = await api.bootstrap();
    if ((!boot || !boot.user) && !launchContext) {
      // No session yet: in the prototype, mint a dev session with a deterministic id per district so a
      // reload reuses the same user (role/profile persist), then bootstrap again. Dev-only — gate in prod.
      const devId = 990000 + (key === "harmony" ? 1 : key === "lonestar" ? 2 : 9);
      try {
        await api.devLogin({ email: "dev-" + key + "@example.test", bc_customer_id: devId, surface: "storefront" });
        boot = await api.bootstrap();
      } catch (devLoginError) {
        console.warn("Continuing as guest; dev login unavailable", devLoginError);
      }
    }
    if (boot && boot.catalog) catalogData = boot.catalog;
    user = (boot && boot.user) || null;
    if (boot && boot.onboarding) onboarding = boot.onboarding;
    defaultCampus = (boot && boot.defaultCampus) || null;
    serverConfig = (boot && boot.district && boot.district.config) || null;
    runtime = (boot && boot.runtime) || null;
    launchContext = normalizeLaunchContext(launchContext, catalogData);
  } catch (e) {
    bootError = e;
  }

  // S7: when school_district.config is populated, the DB is the source of truth for presentation;
  // the client config stays the offline fallback. Deep-merge preserves fallback subkeys that a district
  // does not override yet.
  if (serverConfig && Object.keys(serverConfig).length) {
    config = deepMerge(config, serverConfig);
    window.applyTheme(config.theme);
    document.title = config.chrome.documentTitle;
  }

  const reviewToolsEnabled = runtime && typeof runtime.reviewToolsEnabled === "boolean"
    ? runtime.reviewToolsEnabled
    : localReviewHost();

  const value = {
    config,
    catalog: new window.Catalog(catalogData),
    api,
    user,
    onboarding,
    defaultCampus,
    launchContext,
    embedded,
    runtime,
    reviewToolsEnabled
  };

  ReactDOM.createRoot(document.getElementById("root")).render(
    <TenantProvider value={value}>
      {bootError && <BootBanner error={bootError} apiBaseUrl={config.apiBaseUrl} />}
      <CoreApp />
      {reviewToolsEnabled && <DistrictSwitcher current={config.key} />}
    </TenantProvider>
  );
})();
