// ============ CLIENT-MONITOR — viewer app root ============
// A deliberately tiny shell: license-key sign-in, then the Monitors feature and
// nothing else. No sidebar / NAV / other pages exist in this bundle. Hooks,
// ToastProvider and icons (I) come from shared/primitives.jsx + shared/icons.jsx.

const { useState, useEffect } = React;

// Frameless-window title bar (drag region + min/max/close), trimmed to this
// app's branding. When onSignOut is given (authed view) it also renders a
// sign-out button to switch keys.
function TitleBar({ onSignOut }) {
  const wc = (typeof window !== "undefined" && window.windowControls) || null;
  const onMin = () => wc && wc.minimize();
  const onMax = () => wc && wc.toggleMaximize();
  const onClose = () => wc && wc.close();
  return (
    <div className="titlebar">
      <div className="titlebar-left">
        <span className="logo"><I.Logo /></span>
        <span>monitors</span>
      </div>
      <div className="titlebar-center">— MONITORS —</div>
      <div className="titlebar-right">
        {onSignOut && (
          <button
            className="titlebar-btn"
            onClick={onSignOut}
            title="Sign out"
            style={{ width: "auto", padding: "0 10px", marginRight: 4, display: "flex", alignItems: "center", gap: 6, fontSize: 11 }}
          >
            <I.Logout size={13} /><span>Sign out</span>
          </button>
        )}
        <button className="titlebar-btn" onClick={onMin} title="Minimize"><I.Minus size={13} /></button>
        <button className="titlebar-btn" onClick={onMax} title="Maximize"><svg width="11" height="11" viewBox="0 0 11 11" fill="none"><rect x="1" y="1" width="9" height="9" stroke="currentColor" strokeWidth="1.25"/></svg></button>
        <button className="titlebar-btn close" onClick={onClose} title="Close"><I.X size={13} /></button>
      </div>
    </div>
  );
}

// ============ AUTH ============

function Auth({ onAuthed }) {
  const [server, setServer] = useState(Api.getServerUrl());
  const [key, setKey] = useState("");
  const [showServer, setShowServer] = useState(false);
  const [status, setStatus] = useState(null); // null | "checking" | "ok" | "err"
  const [err, setErr] = useState("");

  const activate = async () => {
    setStatus("checking");
    setErr("");
    Api.setServerUrl(server.trim().replace(/\/$/, ""));
    try {
      const user = await Api.login(key.trim());
      // Viewer keys are the intended audience; user/admin keys are accepted too
      // so the same app can be used to spot-check the Monitors view.
      if (!["viewer", "user", "admin"].includes(user.role)) {
        throw new Error("Unsupported role: " + user.role);
      }
      setStatus("ok");
      setTimeout(() => onAuthed(user), 300);
    } catch (e) {
      Api.logout();
      setStatus("err");
      setErr(e.message || "Sign-in failed");
    }
  };

  const fmt = (v) => {
    const clean = v.replace(/[^A-Za-z0-9]/g, "").toUpperCase().slice(0, 16);
    return clean.match(/.{1,4}/g)?.join("-") || "";
  };

  return (
    <div className="auth-shell">
      <TitleBar/>
      <div className="auth-body">
        <div className="bg-grid"/>
        <div className="auth-card auth">
          <div className="auth-logo"><I.Logo size={22}/></div>
          <h1>Activate access</h1>
          <div className="auth-sub">Enter your access key to open Monitors</div>

          <div className="field" style={{ marginBottom: 14 }}>
            <div className="input">
              <input
                autoFocus
                placeholder="XXXX-XXXX-XXXX-XXXX"
                value={key}
                onChange={(e) => setKey(fmt(e.target.value))}
                onKeyDown={(e) => e.key === "Enter" && activate()}
              />
            </div>
            {err && <div style={{ color: "var(--err)", fontSize: 11, marginTop: 2 }}>{err}</div>}
          </div>

          {showServer ? (
            <div className="field" style={{ marginBottom: 14 }}>
              <div className="field-label">Server URL</div>
              <div className="input">
                <input value={server} onChange={(e) => setServer(e.target.value)} placeholder="http://127.0.0.1:4000"/>
              </div>
            </div>
          ) : (
            <div style={{ fontSize: 11, color: "var(--fg-3)", marginBottom: 14, cursor: "pointer" }}
                 onClick={() => setShowServer(true)}>
              connecting to <span className="mono" style={{ color: "var(--fg-2)" }}>{server}</span> · change
            </div>
          )}

          <button
            className="btn primary lg"
            style={{ width: "100%", justifyContent: "center", height: 40 }}
            onClick={activate}
            disabled={status === "checking" || !key.trim()}
          >
            {status === "checking" ? <><I.Refresh size={13} style={{ animation: "spin 0.8s linear infinite" }}/> Checking…</>
              : status === "ok" ? <><I.Check size={13}/> Activated</>
              : <><I.Shield size={13}/> Activate</>}
          </button>

          <div className="auth-foot">v2.4.1 · ENCRYPTED · SERVER-BACKED</div>
        </div>
      </div>
      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
    </div>
  );
}

// ============ APP ROOT ============

function App() {
  // me === null  → verifying cached key; me === false → signed out; me === {} → in.
  const [me, setMe] = useState(() => (Api.getKey() ? Api.getCachedUser() : false));

  // Resume a cached session — verify the stored key is still good on the server.
  useEffect(() => {
    if (me !== null) return;
    Api.refreshMe()
      .then((u) => setMe(u))
      .catch(() => { Api.logout(); setMe(false); });
  }, [me]);

  // Keep the realtime socket alive while signed in.
  useEffect(() => {
    if (me && typeof me === "object") {
      Api.connect();
      return () => Api.disconnect();
    }
  }, [me && typeof me === "object"]);

  // Server rejected the key (revoked / expired) → bounce to sign-in.
  useEffect(() => Api.on("auth.expired", () => { Api.disconnect(); setMe(false); }), []);

  const MonitorsPage = window.MonitorsPage;
  const signOut = () => { Api.logout(); Api.disconnect(); setMe(false); };

  if (me === null) return <div className="app"/>; // verifying — avoid auth flash
  if (!me) {
    return (
      <ToastProvider>
        <Auth onAuthed={setMe}/>
      </ToastProvider>
    );
  }
  return (
    <ToastProvider>
      <div style={{ display: "flex", flexDirection: "column", height: "100vh" }}>
        <TitleBar onSignOut={signOut}/>
        <main style={{ flex: 1, minHeight: 0, overflow: "auto" }}>
          <MonitorsPage/>
        </main>
      </div>
    </ToastProvider>
  );
}

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