/* global React, ReactDOM, StatusBar, HomeScreen, RulesScreen, RequestSheet, KeyholderDashboard,
   Icon, API, rulesToPolicy, policyToDisplay, DEFAULT_POLICY, nowSec */
const { useState, useEffect } = React;

/* ---------- scale the fixed 820×1180 device surface to fill the viewport ---------- */
function DeviceStage({ children }) {
  const [scale, setScale] = useState(1);
  useEffect(() => {
    function fit() { setScale(Math.min(window.innerWidth / 820, window.innerHeight / 1180)); }
    fit();
    window.addEventListener("resize", fit);
    return () => window.removeEventListener("resize", fit);
  }, []);
  return (
    <div className="device-stage">
      <div className="device-scaler" style={{ width: 820, height: 1180, transform: "scale(" + scale + ")" }}>
        {children}
      </div>
    </div>
  );
}

/* ================= DEVICE APP (wired to the live backend) ================= */
function DeviceApp() {
  const [sync, setSync] = useState(null);
  const [view, setView] = useState("home");
  const [sheet, setSheet] = useState(null);
  const [picked, setPicked] = useState("youtube");
  const [mins, setMins] = useState(15);
  const [reason, setReason] = useState("");
  const [reqId, setReqId] = useState(null);
  const [left, setLeft] = useState(0);
  const [toast, setToast] = useState(null);
  const [err, setErr] = useState(null);

  async function refresh() {
    try { setSync(await API.dev("/sync")); }
    catch (e) { if (String(e.message).indexOf("unauthorized") >= 0) { API.unpair(); location.reload(); } }
  }
  useEffect(() => { refresh(); const t = setInterval(refresh, 12000); return () => clearInterval(t); }, []);

  const policy = sync ? rulesToPolicy(sync.rules || []) : DEFAULT_POLICY;
  const disp = policyToDisplay(policy);
  const keyholder = (sync && sync.keyholder) || "your keyholder";
  const ag = sync && sync.activeGrants && sync.activeGrants[0];
  const expiresAt = ag && ag.expiresAt;
  const grantApp = ag && ag.target && ag.target.app;
  const totalSecs = ag ? (ag.minutes ? ag.minutes * 60 : (ag.expiresAt - (ag.startsAt || ag.expiresAt))) || 1 : 1;

  function flash(m) { setToast(m); setTimeout(() => setToast(null), 2800); }

  // local countdown
  useEffect(() => {
    if (!expiresAt) { setLeft(0); return; }
    function tick() {
      const l = expiresAt - nowSec();
      if (l <= 0) { setLeft(0); flash("Time's up — it locked itself"); refresh(); }
      else setLeft(l);
    }
    tick();
    const t = setInterval(tick, 1000);
    return () => clearInterval(t);
  }, [expiresAt]);

  // while waiting on an answer, watch the request's status
  useEffect(() => {
    if (sheet !== "waiting" || !reqId) return;
    const t = setInterval(async () => {
      try {
        const { requests } = await API.dev("/requests");
        const r = requests.find((x) => x.id === reqId);
        if (r && r.status === "approved") { setSheet("granted"); refresh(); }
        else if (r && r.status === "denied") { setSheet(null); flash(keyholder + " said not this time"); }
      } catch (e) {}
    }, 3000);
    return () => clearInterval(t);
  }, [sheet, reqId]);

  async function send() {
    setErr(null);
    try {
      const r = await API.dev("/grants", {
        method: "POST",
        body: JSON.stringify({ target: { app: picked }, minutes: mins, reason: reason }),
      });
      setReqId(r.grantId);
      setSheet("waiting");
    } catch (e) { setErr(e.message); }
  }
  function openApp() { setSheet(null); setView("home"); setReason(""); }
  async function lockNow() { try { await API.dev("/lock", { method: "POST", body: "{}" }); } catch (e) {} flash("Locked. The wall is back up."); refresh(); }

  const grant = (expiresAt && left > 0) ? { app: grantApp, total: totalSecs } : null;

  return (
    <DeviceStage>
      <div className="surface">
        <div className="grain"></div>
        <StatusBar />
        <div className="app-top">
          <div className="wordmark"><span className="wm-dot"></span> Daylight</div>
          <div className="keyholder">
            <span className="kh-av">{keyholder.slice(0, 1).toUpperCase()}</span>
            <span className="kh-meta"><span className="knm">{keyholder}</span><span className="krl">Keyholder</span></span>
          </div>
        </div>

        <div className="screen" key={view}>
          {view === "home" && (
            <HomeScreen
              keyholder={keyholder}
              blocked={disp.blocked}
              statCount={disp.statCount}
              statCap={disp.statCap}
              grant={grant}
              secondsLeft={left}
              totalSecs={grant ? grant.total : 1}
              onRequest={() => setSheet("compose")}
              onLockNow={lockNow}
            />
          )}
          {view === "rules" && (
            <RulesScreen keyholder={keyholder} groups={disp.groups} onBack={() => setView("home")} onRequestChange={() => setSheet("compose")} />
          )}
        </div>

        <div className="tabbar">
          <div className={"tab" + (view === "home" ? " on" : "")} onClick={() => setView("home")}>{Icon.home()} Today</div>
          <div className={"tab" + (view === "rules" ? " on" : "")} onClick={() => setView("rules")}>{Icon.shield()} Rules</div>
        </div>

        {sheet && (
          <RequestSheet
            step={sheet} keyholder={keyholder} choices={disp.choices}
            picked={picked} setPicked={setPicked} mins={mins} setMins={setMins}
            reason={reason} setReason={setReason} error={err}
            onClose={() => { setSheet(null); setErr(null); }} onSend={send} onOpen={openApp}
          />
        )}

        {toast && <div className="toast">{Icon.lock({ style: { color: "#e7b25a" } })} {toast}</div>}
      </div>
    </DeviceStage>
  );
}

/* ================= LANDING / PAIR / KEYHOLDER GATE ================= */
function Gate({ children }) {
  return <div className="gate"><div className="gate-sun"></div><div className="gate-mark"><span className="wm-dot big"></span> Daylight</div>{children}</div>;
}

function Landing({ onPick }) {
  return (
    <Gate>
      <h1 className="gate-h">Step out of the scroll.<br /><em>Back into the light.</em></h1>
      <p className="gate-sub">Who's here?</p>
      <div className="gate-choices">
        <button className="gate-choice" onClick={() => onPick("pair")}>
          <div className="gc-ic">▢</div>
          <div className="gc-t">This is my device</div>
          <div className="gc-s">See your rules · request time</div>
        </button>
        <button className="gate-choice" onClick={() => onPick("keyholder")}>
          <div className="gc-ic">🔑</div>
          <div className="gc-t">I'm the keyholder</div>
          <div className="gc-s">Set rules · approve requests</div>
        </button>
      </div>
    </Gate>
  );
}

function PairScreen({ onDone, onBack }) {
  const [code, setCode] = useState("");
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);
  async function go() {
    setBusy(true); setErr(null);
    try {
      const r = await API.call("/enroll", { method: "POST", body: JSON.stringify({ code: code.trim().toUpperCase() }) });
      API.pair(r.deviceId, r.enrollSecret); onDone();
    } catch (e) { setErr("That code didn't work — ask your keyholder for a fresh one."); } finally { setBusy(false); }
  }
  return (
    <Gate>
      <h1 className="gate-h">Pair this device</h1>
      <p className="gate-sub">Enter the code your keyholder gave you.</p>
      <input className="gate-in code" placeholder="K7P-3QF" value={code} onChange={(e) => setCode(e.target.value)} maxLength={7} onKeyDown={(e) => e.key === "Enter" && go()} />
      {err && <div className="form-err center">{err}</div>}
      <button className="btn gate-btn" disabled={busy || !code} onClick={go}>{busy ? "Pairing…" : "Pair"}</button>
      <button className="gate-link" onClick={onBack}>Back</button>
    </Gate>
  );
}

function KeyholderGate({ status, onAuthed, onBack }) {
  const [setup, setSetup] = useState(!!(status && status.needsSetup));
  const [pw, setPw] = useState("");
  const [name, setName] = useState("");
  const [code, setCode] = useState("");
  const [err, setErr] = useState(null);
  const [busy, setBusy] = useState(false);

  async function login() {
    setBusy(true); setErr(null);
    try { await API.call("/auth/login", { method: "POST", body: JSON.stringify({ password: pw }) }); onAuthed(); }
    catch (e) { setErr("Wrong password."); } finally { setBusy(false); }
  }
  async function doSetup() {
    setBusy(true); setErr(null);
    try {
      await API.call("/setup", { method: "POST", body: JSON.stringify({ setupToken: code.trim(), password: pw, keyholderName: name }) });
      await API.call("/auth/login", { method: "POST", body: JSON.stringify({ password: pw }) });
      onAuthed();
    } catch (e) { setErr(e.message); } finally { setBusy(false); }
  }

  return (
    <Gate>
      {setup ? (
        <React.Fragment>
          <h1 className="gate-h">Set up the keyholder</h1>
          <p className="gate-sub">The one person who holds the keys.</p>
          <input className="gate-in" placeholder="Keyholder's name (e.g. Sarah)" value={name} onChange={(e) => setName(e.target.value)} />
          <input className="gate-in" type="password" placeholder="Choose a password" value={pw} onChange={(e) => setPw(e.target.value)} />
          <input className="gate-in" placeholder="Setup code" value={code} onChange={(e) => setCode(e.target.value)} />
          {err && <div className="form-err center">{err}</div>}
          <button className="btn gate-btn" disabled={busy || !pw || !name || !code} onClick={doSetup}>{busy ? "Creating…" : "Create keyholder"}</button>
        </React.Fragment>
      ) : (
        <React.Fragment>
          <h1 className="gate-h">Keyholder sign in</h1>
          <p className="gate-sub">Welcome back{status && status.keyholder ? ", " + status.keyholder : ""}.</p>
          <input className="gate-in" type="password" placeholder="Password" value={pw} onChange={(e) => setPw(e.target.value)} onKeyDown={(e) => e.key === "Enter" && login()} />
          {err && <div className="form-err center">{err}</div>}
          <button className="btn gate-btn" disabled={busy || !pw} onClick={login}>{busy ? "…" : "Unlock"}</button>
        </React.Fragment>
      )}
      <button className="gate-link" onClick={onBack}>Back</button>
    </Gate>
  );
}

/* ================= ROOT ================= */
function Root() {
  const [mode, setMode] = useState("loading");
  const [status, setStatus] = useState(null);

  useEffect(() => { boot(); }, []);
  async function boot() {
    let st = {};
    try { st = await API.call("/status"); } catch (e) {}
    setStatus(st);
    if (API.isPaired()) { setMode("device"); return; }
    try { await API.call("/auth/me"); setMode("keyholder"); return; } catch (e) {}
    setMode("landing");
  }
  async function refreshStatusThen(m) {
    let st = {}; try { st = await API.call("/status"); } catch (e) {}
    setStatus(st); setMode(m);
  }
  async function signOut() { try { await API.call("/auth/logout", { method: "POST" }); } catch (e) {} setMode("landing"); }

  if (mode === "loading") return <Gate><p className="gate-sub">One moment…</p></Gate>;
  if (mode === "device") return <DeviceApp />;
  if (mode === "keyholder") return <KeyholderDashboard keyholder={status && status.keyholder ? status.keyholder : "Keyholder"} onSignOut={signOut} />;
  if (mode === "pair") return <PairScreen onDone={() => setMode("device")} onBack={() => setMode("landing")} />;
  if (mode === "keyholderGate") return <KeyholderGate status={status} onAuthed={() => refreshStatusThen("keyholder")} onBack={() => setMode("landing")} />;
  return <Landing onPick={(p) => setMode(p === "keyholder" ? "keyholderGate" : "pair")} />;
}

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