// Google Sign-In via Google Identity Services (GIS).
//
// Exposes on window:
//   useUser()            — React hook returning { user, signOut, signingIn }
//   authFetch(url, opts) — fetch wrapper that adds `Authorization: Bearer <id_token>`
//   SignInScreen         — full-page sign-in component
//   UserPill             — small avatar/role badge for the top bar
//
// Token storage: id_token in localStorage. Expires in ~1 hour; GIS issues fresh
// tokens on the next interactive sign-in. We also auto-prompt One Tap when the
// page loads if no valid token is present.

const STORAGE_KEY = "mcc.auth.v1";

function decodeJwtPayload(jwt) {
  try {
    const part = jwt.split(".")[1];
    const json = atob(part.replace(/-/g, "+").replace(/_/g, "/"));
    return JSON.parse(decodeURIComponent(escape(json)));
  } catch { return null; }
}

function readStored() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    const obj = JSON.parse(raw);
    if (!obj || !obj.idToken) return null;
    // Sanity check expiry from the JWT itself (don't trust stored data).
    const payload = decodeJwtPayload(obj.idToken);
    if (!payload || !payload.exp) return null;
    if (payload.exp * 1000 <= Date.now() + 5000) return null; // 5s skew
    return { ...obj, _exp: payload.exp * 1000 };
  } catch { return null; }
}
function writeStored(user) {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(user)); } catch {}
}
function clearStored() {
  try { localStorage.removeItem(STORAGE_KEY); } catch {}
}

const _authSubscribers = new Set();
function notifyAuthChanged() { _authSubscribers.forEach(fn => { try { fn(); } catch {} }); }

// Config loaded once
let _authConfig = null;
async function loadAuthConfig() {
  if (_authConfig) return _authConfig;
  const r = await fetch("data/auth-config.json", { cache: "no-store" });
  const raw = await r.json();
  // Pick the right client_id for the current hostname. Falls back to `clientId`.
  const map = raw.clientIdsByHostname || {};
  const host = window.location.hostname;
  const resolved = map[host] || raw.clientId;
  _authConfig = { ...raw, clientId: resolved };
  return _authConfig;
}

// One-shot promise: resolves when GIS library has loaded
let _gisReady = null;
function whenGisReady() {
  if (_gisReady) return _gisReady;
  _gisReady = new Promise((resolve) => {
    if (window.google && window.google.accounts && window.google.accounts.id) return resolve();
    const id = setInterval(() => {
      if (window.google && window.google.accounts && window.google.accounts.id) {
        clearInterval(id); resolve();
      }
    }, 100);
  });
  return _gisReady;
}

async function initGsi(onCredential) {
  await whenGisReady();
  const cfg = await loadAuthConfig();
  window.google.accounts.id.initialize({
    client_id: cfg.clientId,
    callback: (resp) => onCredential(resp.credential),
    auto_select: true,
    cancel_on_tap_outside: false,
    use_fedcm_for_prompt: true,
  });
}

function handleCredential(idToken) {
  const payload = decodeJwtPayload(idToken);
  if (!payload) return;
  const user = {
    idToken,
    email: (payload.email || "").toLowerCase(),
    name:  payload.name || payload.email,
    picture: payload.picture || null,
    _exp: (payload.exp || 0) * 1000,
  };
  writeStored(user);
  notifyAuthChanged();
}

function useUser() {
  const [user, setUser] = React.useState(() => readStored());
  const [signingIn, setSigningIn] = React.useState(false);

  React.useEffect(() => {
    const sub = () => setUser(readStored());
    _authSubscribers.add(sub);
    initGsi(handleCredential).catch(e => console.warn("[auth] init failed", e));
    return () => _authSubscribers.delete(sub);
  }, []);

  const signOut = React.useCallback(() => {
    clearStored();
    try { window.google?.accounts?.id?.disableAutoSelect(); } catch {}
    notifyAuthChanged();
  }, []);

  return { user, signOut, signingIn, setSigningIn };
}

async function authFetch(url, opts = {}) {
  const stored = readStored();
  const headers = { ...(opts.headers || {}) };
  if (stored && stored.idToken) headers.Authorization = "Bearer " + stored.idToken;
  const r = await fetch(url, { ...opts, headers });
  if (r.status === 401) {
    // Token rejected — wipe and force re-sign-in
    clearStored();
    notifyAuthChanged();
  }
  return r;
}

function SignInScreen() {
  const buttonRef = React.useRef(null);
  const [mode, setMode] = React.useState("google"); // "google" | "password"
  const [u, setU] = React.useState("");
  const [p, setP] = React.useState("");
  const [err, setErr] = React.useState("");
  const [busy, setBusy] = React.useState(false);

  React.useEffect(() => {
    if (mode !== "google") return;
    let cancelled = false;
    (async () => {
      await initGsi(handleCredential);
      if (cancelled || !buttonRef.current) return;
      // Force English (CISO/UX: avoid auto-detected Hebrew button text)
      window.google.accounts.id.renderButton(buttonRef.current, {
        theme: "outline", size: "large", shape: "pill",
        text: "signin_with", logo_alignment: "left",
        locale: "en",
      });
      try { window.google.accounts.id.prompt(); } catch {}
    })();
    return () => { cancelled = true; };
  }, [mode]);

  const submitPassword = async (e) => {
    if (e && e.preventDefault) e.preventDefault();
    if (!u.trim() || !p) return;
    setBusy(true); setErr("");
    try {
      const r = await fetch("/api/auth/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ username: u.trim(), password: p }),
      });
      const j = await r.json();
      if (!r.ok) { setErr(j.error || ("HTTP " + r.status)); setBusy(false); return; }
      // Store same shape as Google flow so authFetch sends the Bearer header.
      writeStored({ idToken: j.token, email: j.user.email, name: j.user.name, picture: null, _exp: Date.now() + 8 * 3600 * 1000 });
      notifyAuthChanged();
    } catch (ex) {
      setErr(ex.message || String(ex));
      setBusy(false);
    }
  };

  return (
    <div style={{
      minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center",
      background:
        "radial-gradient(ellipse 90% 45% at 50% -5%, var(--sky-1) 0%, transparent 55%)," +
        "radial-gradient(ellipse 55% 35% at 85% 10%, var(--sky-2) 0%, transparent 55%)," +
        "var(--bg)",
      padding: 24,
    }}>
      <div style={{
        background: "var(--bg-card)", border: "1px solid var(--line)",
        borderRadius: 24, padding: "48px 40px", maxWidth: 440, width: "100%",
        boxShadow: "0 10px 60px -20px rgba(0,0,0,0.15)", textAlign: "center",
      }}>
        <img src="assets/favicon.svg" alt="" style={{ width: 64, height: 64, margin: "0 auto 16px" }}/>
        <div className="mono" style={{ color: "var(--ink-muted)", marginBottom: 8 }}>MEDICAL BY MOVEO</div>
        <h1 style={{
          fontFamily: "'Fraunces','Noto Sans Hebrew',serif",
          fontSize: 28, fontWeight: 500, marginBottom: 8, letterSpacing: "-0.02em",
        }}>Control Center</h1>
        <p style={{ color: "var(--ink-soft)", marginBottom: 24, fontSize: 14 }}>
          {mode === "google"
            ? <>Sign in with your <b>@moveomedical.com</b> Google account</>
            : <>Sign in with username & password</>}
        </p>

        {mode === "google" && (
          <>
            <div ref={buttonRef} style={{ display: "flex", justifyContent: "center" }}/>
            <button onClick={() => setMode("password")}
                    style={{
                      marginTop: 18, background: "transparent", border: "none",
                      color: "var(--ink-soft)", fontSize: 12, cursor: "pointer",
                      textDecoration: "underline",
                    }}>
              Or use username & password
            </button>
          </>
        )}

        {mode === "password" && (
          <form onSubmit={submitPassword} style={{ display: "flex", flexDirection: "column", gap: 10, textAlign: "left" }}>
            <label style={{ fontSize: 11, color: "var(--ink-muted)", textTransform: "uppercase", letterSpacing: ".06em" }}>Username</label>
            <input autoFocus value={u} onChange={e => setU(e.target.value)} disabled={busy}
                   style={{ padding: "10px 12px", borderRadius: 10, border: "1px solid var(--line)", background: "var(--bg)" }}/>
            <label style={{ fontSize: 11, color: "var(--ink-muted)", textTransform: "uppercase", letterSpacing: ".06em" }}>Password</label>
            <input type="password" value={p} onChange={e => setP(e.target.value)} disabled={busy}
                   style={{ padding: "10px 12px", borderRadius: 10, border: "1px solid var(--line)", background: "var(--bg)" }}/>
            {err && <div style={{ color: "var(--red)", fontSize: 12 }}>{err}</div>}
            <button type="submit" disabled={busy || !u.trim() || !p}
                    style={{
                      marginTop: 6, padding: "10px 14px", borderRadius: 999,
                      background: "var(--ink)", color: "#fff", border: "none",
                      cursor: busy ? "wait" : "pointer", fontSize: 14, fontWeight: 500,
                      opacity: (busy || !u.trim() || !p) ? .5 : 1,
                    }}>
              {busy ? "Signing in…" : "Sign in"}
            </button>
            <button type="button" onClick={() => { setMode("google"); setErr(""); }}
                    style={{
                      background: "transparent", border: "none",
                      color: "var(--ink-soft)", fontSize: 12, cursor: "pointer",
                      textDecoration: "underline", marginTop: 4,
                    }}>
              ← Back to Google sign-in
            </button>
          </form>
        )}

        <p style={{ color: "var(--ink-muted)", marginTop: 24, fontSize: 11 }}>
          Access restricted to invited Moveo Medical team members.
        </p>
      </div>
    </div>
  );
}

function UserPill({ user, onSignOut }) {
  const [open, setOpen] = React.useState(false);
  if (!user) return null;
  return (
    <div style={{ position: "relative" }}>
      <button onClick={() => setOpen(v => !v)}
              title={user.email}
              style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "4px 12px 4px 4px", borderRadius: 999,
                background: "var(--bg-card)", border: "1px solid var(--line)",
                cursor: "pointer",
              }}>
        {user.picture ? (
          <img src={user.picture} alt="" style={{ width: 24, height: 24, borderRadius: "50%" }}/>
        ) : (
          <span style={{
            width: 24, height: 24, borderRadius: "50%", background: "var(--accent)",
            color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center",
            fontSize: 11, fontWeight: 600,
          }}>{(user.name || user.email)[0].toUpperCase()}</span>
        )}
        <span style={{ fontSize: 12, color: "var(--ink)" }}>{(user.name || user.email).split(" ")[0]}</span>
      </button>
      {open && (
        <div style={{
          position: "absolute", right: 0, top: "calc(100% + 6px)",
          background: "var(--bg-card)", border: "1px solid var(--line)",
          borderRadius: 12, padding: 12, minWidth: 220, zIndex: 100,
          boxShadow: "0 8px 24px -8px rgba(0,0,0,.18)",
        }}>
          <div style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)" }}>{user.name}</div>
          <div style={{ fontSize: 11, color: "var(--ink-muted)", marginBottom: 8 }}>{user.email}</div>
          <button onClick={() => { setOpen(false); onSignOut(); }}
                  style={{
                    width: "100%", padding: "6px 10px", borderRadius: 8,
                    border: "1px solid var(--line)", background: "transparent",
                    color: "var(--ink)", fontSize: 12, cursor: "pointer",
                  }}>
            Sign out
          </button>
        </div>
      )}
    </div>
  );
}

window.useUser      = useUser;
window.authFetch    = authFetch;
window.SignInScreen = SignInScreen;
window.UserPill     = UserPill;
