/* App shell — Spec Compare */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "comfortable",
  "valueFont": "sans"
}/*EDITMODE-END*/;

const LS_STATE = "speccompare-state-v1";
const LS_RECENTS = "speccompare-recents-v1";

const SEED_RECENTS = [
  { ids: ["hw-n6703", "zb-se4710", "dl-dse0420"], ts: Date.now() - 86400000 },
  { ids: ["hw-hf520", "zb-ms4717"], ts: Date.now() - 3 * 86400000 },
];

function loadJSON(key, fallback) {
  try { const v = JSON.parse(localStorage.getItem(key)); return v ?? fallback; } catch { return fallback; }
}

function StepIndicator({ screen, onJump, hasSelection }) {
  const steps = [
    { id: "category", n: 1, label: "Category" },
    { id: "select", n: 2, label: "Products" },
    { id: "compare", n: 3, label: "Compare" },
  ];
  const order = { category: 1, select: 2, compare: 3 };
  const current = order[screen] || 0;
  if (current === 0) return null;
  return (
    <nav className="steps" aria-label="Progress">
      {steps.map((s) => {
        const state = s.n === current ? "current" : s.n < current ? "done" : "todo";
        const clickable = s.n < current || (s.id === "compare" && hasSelection);
        return (
          <React.Fragment key={s.id}>
            {s.n > 1 ? <span className="steps-sep"></span> : null}
            <button
              className={"step step-" + state}
              disabled={!clickable && state !== "current"}
              onClick={() => clickable && onJump(s.id)}
            >
              <span className="step-n">{state === "done" ? <Icons.check size={11} /> : s.n}</span>
              {s.label}
            </button>
          </React.Fragment>
        );
      })}
    </nav>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  /* Owner/admin mode — unlocked with a password from the Admin button,
     then remembered on this machine. Regular users never see data tools. */
  const ADMIN_PASSWORD = "scaniq2026"; /* ← change the owner password here */
  const [admin, setAdmin] = React.useState(() => localStorage.getItem("scaniq-admin") === "1");
  const [pwOpen, setPwOpen] = React.useState(false);
  const [pw, setPw] = React.useState("");
  const [pwErr, setPwErr] = React.useState(false);
  const [pwShow, setPwShow] = React.useState(false);
  const [pwFocus, setPwFocus] = React.useState(false);
  const tryUnlock = (e) => {
    e.preventDefault();
    if (pw === ADMIN_PASSWORD) {
      localStorage.setItem("scaniq-admin", "1");
      setAdmin(true); setPwOpen(false); setPw(""); setPwErr(false);
      window.toast("Admin mode unlocked", "check");
      setScreen("data");
    } else {
      setPwErr(true);
    }
  };

  const persisted = React.useMemo(() => {
    /* Sanitize persisted state: categories/products may have been removed from the catalog */
    const raw = loadJSON(LS_STATE, {});
    const db = window.SPECDB;
    const category = raw.category && db.categories.some((c) => c.id === raw.category) ? raw.category : null;
    const selection = (raw.selection || []).filter((id) => db.find(id));
    let screen = raw.screen || "landing";
    if (screen === "select" && !category) screen = "category";
    if (screen === "compare" && selection.length < 2) screen = category ? "select" : "landing";
    if (screen === "data" && localStorage.getItem("scaniq-admin") !== "1") screen = "landing";
    return { screen, category, selection };
  }, []);
  const [screen, setScreen] = React.useState(persisted.screen || "landing");
  const [category, setCategory] = React.useState(persisted.category || null);
  const [selection, setSelection] = React.useState(persisted.selection || []);
  const [recents, setRecents] = React.useState(() => loadJSON(LS_RECENTS, SEED_RECENTS));

  React.useEffect(() => {
    localStorage.setItem(LS_STATE, JSON.stringify({ screen, category, selection }));
  }, [screen, category, selection]);

  /* The shared catalog loads asynchronously (and can change when an admin
     uploads new Excel). Re-render so engine counts and lists stay in sync,
     and drop any selected products that no longer exist in the new catalog. */
  const [, bumpDbVersion] = React.useState(0);
  React.useEffect(() => {
    const onDbUpdated = () => {
      setSelection((sel) => sel.filter((id) => window.SPECDB.find(id)));
      setCategory((c) => (c && !window.SPECDB.categories.some((x) => x.id === c) ? null : c));
      bumpDbVersion((v) => v + 1);
    };
    window.addEventListener("scaniq-db-updated", onDbUpdated);
    return () => window.removeEventListener("scaniq-db-updated", onDbUpdated);
  }, []);

  const pushRecent = (ids) => {
    setRecents((r) => {
      const key = ids.slice().sort().join("|");
      const next = [{ ids, ts: Date.now() }, ...r.filter((x) => x.ids.slice().sort().join("|") !== key)].slice(0, 5);
      localStorage.setItem(LS_RECENTS, JSON.stringify(next));
      return next;
    });
  };

  const toggleProduct = (id) =>
    setSelection((sel) => sel.includes(id) ? sel.filter((x) => x !== id) : sel.length >= 4 ? sel : [...sel, id]);

  const goCompare = (ids) => {
    const list = ids || selection;
    if (list.length < 2) return;
    pushRecent(list);
    setScreen("compare");
  };

  const openComparison = (ids) => {
    const valid = ids.filter((id) => window.SPECDB.find(id)).slice(0, 4);
    if (valid.length < 2) return;
    setSelection(valid);
    setCategory(window.SPECDB.find(valid[0]).category);
    pushRecent(valid);
    setScreen("compare");
  };

  const swapProduct = (oldId, newId) =>
    setSelection((sel) => sel.map((id) => (id === oldId ? newId : id)));

  const removeFromCompare = (id) =>
    setSelection((sel) => (sel.length > 2 ? sel.filter((x) => x !== id) : sel));

  const jumpStep = (s) => {
    if (s === "category") setScreen("category");
    else if (s === "select") { if (category) setScreen("select"); else setScreen("category"); }
    else if (s === "compare" && selection.length >= 2) goCompare();
  };

  return (
    <div className={"app density-" + t.density}>
      <header className="topbar">
        <button className="topbar-brand" onClick={() => setScreen("landing")}>
          <span className="logomark">
            <span></span><span></span><span></span><span></span>
          </span>
          <span className="topbar-id">
            <span className="topbar-name">ScanIQ</span>
            <span className="topbar-sub">Compare specs</span>
          </span>
          <span className="topbar-tag">Honeywell Sales</span>
        </button>
        <StepIndicator screen={screen} onJump={jumpStep} hasSelection={selection.length >= 2} />
        <div className="topbar-right">
          {admin ? (
            <button className="btn btn-outline btn-sm" onClick={() => setScreen("data")}><Icons.doc size={14} /> Update data</button>
          ) : (
            <button className="btn btn-ghost btn-sm" onClick={() => { setPwOpen(true); setPw(""); setPwErr(false); setPwShow(false); }}>Admin</button>
          )}
          <span className="topbar-meta">{window.SPECDB.products.length} engines{admin && window.SPECDB.meta ? " · " + window.SPECDB.meta.sourceName : ""}</span>
        </div>
      </header>

      <main className="main">
        {screen === "landing" ? (
          <LandingScreen
            recents={recents}
            onStart={() => setScreen("category")}
            onOpenRecent={openComparison}
          />
        ) : screen === "data" && admin ? (
          <DataScreen
            onApplied={() => { setSelection([]); setCategory(null); setScreen("category"); }}
            onBack={() => setScreen("landing")}
            onExitAdmin={() => { localStorage.removeItem("scaniq-admin"); setAdmin(false); setScreen("landing"); }}
          />
        ) : screen === "category" ? (
          <CategoryScreen onPick={(c) => { if (c !== category) setSelection([]); setCategory(c); setScreen("select"); }} />
        ) : screen === "select" ? (
          <SelectScreen
            category={category}
            selection={selection}
            onToggle={toggleProduct}
            onCompare={() => goCompare()}
            onBack={() => setScreen("category")}
            onClear={() => setSelection([])}
          />
        ) : (
          <CompareScreen
            selection={selection}
            onRemove={removeFromCompare}
            onSwap={swapProduct}
            onAddAnother={() => setScreen("select")}
            onBack={() => setScreen("select")}
            tweaks={t}
          />
        )}
      </main>

      <AssistantWidget onCompare={openComparison} />
      <ToastHost />

      {pwOpen ? (
        <div className="pwoverlay" onClick={(e) => { if (e.target === e.currentTarget) setPwOpen(false); }}>
          <form className="pwmodal" onSubmit={tryUnlock}>
            <AdminScene password={pw} showPassword={pwShow} focused={pwFocus} />
            <div className="pwmodal-title">Admin access</div>
            <div className="pwmodal-sub">Enter the owner password to manage the product database.</div>
            <div className="pwfield">
              <input
                type={pwShow ? "text" : "password"}
                className={"pwinput" + (pwErr ? " pwinput-err" : "")}
                placeholder="Password"
                value={pw}
                autoFocus={true}
                onChange={(e) => { setPw(e.target.value); setPwErr(false); }}
                onFocus={() => setPwFocus(true)}
                onBlur={() => setPwFocus(false)}
                onKeyDown={(e) => { if (e.key === "Escape") setPwOpen(false); }}
                aria-label="Admin password"
              />
              <button type="button" className="pweye" title={pwShow ? "Hide password" : "Show password"} onClick={() => setPwShow(!pwShow)}>
                <PwEyeIcon off={pwShow} />
              </button>
            </div>
            {pwErr ? <div className="pwerror">Incorrect password — try again.</div> : null}
            <div className="pwmodal-actions">
              <button type="button" className="btn btn-ghost" onClick={() => setPwOpen(false)}>Cancel</button>
              <button type="submit" className="btn btn-primary" disabled={!pw}>Unlock</button>
            </div>
          </form>
        </div>
      ) : null}

      <TweaksPanel>
        <TweakSection label="Comparison table" />
        <TweakRadio label="Density" value={t.density} options={["comfortable", "compact"]}
          onChange={(v) => setTweak("density", v)} />
        <TweakRadio label="Value typeface" value={t.valueFont} options={["sans", "mono"]}
          onChange={(v) => setTweak("valueFont", v)} />
      </TweaksPanel>
    </div>
  );
}

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