// =================================================================
// pw-session.jsx — session management for the Operator Dashboard.
//
//   window.__session — singleton: { token, user, issuedAt, expiresAt }
//
//   - signIn({email, password})  → mints a session (mock) or POSTs to
//                                   the BFF /auth/session (live).
//   - signOut(reason)            → clears session.
//   - auto-expiry timer + idle countdown; 401 from the API → sign-out.
//   - persisted in localStorage; survives refresh until it expires.
//
//   <SessionGate> wraps the app: no valid session → <SignInScreen>.
// =================================================================

(() => {
  const KEY = "krafts.paywall.session.v1";
  const listeners = [];
  const emit = () => listeners.forEach(fn => { try { fn(current); } catch (e) {} });
  const subscribe = (fn) => { listeners.push(fn); return () => { const i = listeners.indexOf(fn); if (i >= 0) listeners.splice(i, 1); }; };

  const load = () => { try { const r = localStorage.getItem(KEY); return r ? JSON.parse(r) : null; } catch (e) { return null; } };
  const persist = () => { try { current ? localStorage.setItem(KEY, JSON.stringify(current)) : localStorage.removeItem(KEY); } catch (e) {} };

  let current = load();
  let timer = null;

  const ttlMs = () => (window.PAYWALL_API.auth.sessionTtlMinutes || 30) * 60000;
  const isValid = () => !!(current && current.token && current.expiresAt > Date.now());
  const remainingMs = () => (current ? Math.max(0, current.expiresAt - Date.now()) : 0);

  const scheduleExpiry = () => {
    clearTimeout(timer);
    if (!isValid()) return;
    timer = setTimeout(() => { signOut("expired"); }, remainingMs());
  };

  const fakeToken = (email) => "sess_" + btoa(unescape(encodeURIComponent(email))).replace(/=+$/, "").slice(0, 18) + "." + Math.random().toString(36).slice(2, 10);

  const startSession = (user) => {
    const now = Date.now();
    current = { token: fakeToken(user.email), user, issuedAt: now, expiresAt: now + ttlMs() };
    persist(); scheduleExpiry(); emit();
    return current;
  };

  const signIn = async ({ email, password }) => {
    const cfg = window.PAYWALL_API;
    const op = window.PAYWALL_CONFIG.operator;
    if (window.__api.getConfig().live) {
      // Live: authenticate against the BFF; it returns { token, user, expires_at }.
      const res = await window.__api.call("signIn", { body: { email, password } });
      const now = Date.now();
      current = {
        token: res.token, user: res.user || { name: email.split("@")[0], email, roleLabel: op.roleLabel },
        issuedAt: now, expiresAt: res.expires_at ? new Date(res.expires_at).getTime() : now + ttlMs(),
      };
      persist(); scheduleExpiry(); emit();
      if (current.user?.defaultRole && window.__setRole) window.__setRole(current.user.defaultRole);
      return current;
    }
    // Mock: accept any non-empty credentials; identity from config.
    await new Promise(r => setTimeout(r, 420));
    const normalizedEmail = email.trim().toLowerCase();
    const demo = (window.PAYWALL_CONFIG.demoUsers || []).find(u => [u.email, u.username].filter(Boolean).map(v => v.toLowerCase()).includes(normalizedEmail) && (!u.password || u.password === password));
    const known = normalizedEmail === op.email.toLowerCase();
    if (demo?.defaultRole && window.__setRole) window.__setRole(demo.defaultRole);
    if (known && op.defaultRole && window.__setRole) window.__setRole(op.defaultRole);
    return startSession(demo ? { ...demo, password: undefined } : known ? { ...op } : { name: email.split("@")[0].replace(/[._]/g, " ").replace(/\b\w/g, c => c.toUpperCase()), email: email.trim(), roleLabel: op.roleLabel, defaultRole: "operator" });
  };

  const extend = () => { if (current) { current.expiresAt = Date.now() + ttlMs(); persist(); scheduleExpiry(); emit(); } };

  const signOut = async (reason) => {
    if (window.__api.getConfig().live && current) { try { await window.__api.call("signOut"); } catch (e) {} }
    current = null; clearTimeout(timer); persist(); emit();
    if (reason === "expired") window.__toast && window.__toast("Session expired — please sign in again", "warn");
    else if (reason) window.__toast && window.__toast("Signed out");
  };

  // 401/403 from the API → force sign-out.
  window.__api.on("authError", () => { if (isValid()) signOut("expired"); });

  if (isValid()) scheduleExpiry();

  window.__session = { get: () => current, isValid, remainingMs, signIn, signOut, extend, subscribe };

  // React hook
  window.useSession = () => {
    const [s, setS] = React.useState(current);
    React.useEffect(() => window.__session.subscribe(setS), []);
    return { session: s, valid: isValid(), remainingMs, signIn, signOut, extend };
  };
})();

// =================================================================
// Sign-in screen
// =================================================================
const SignInScreen = () => {
  const cfg = window.PAYWALL_CONFIG;
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");
  const [show, setShow] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState("");

  const submit = async (e, override) => {
    e && e.preventDefault();
    const credentials = override || { email, password };
    if (!credentials.email.trim() || !credentials.password) { setErr("Enter your email and password."); return; }
    setBusy(true); setErr("");
    try { await window.__session.signIn(credentials); }
    catch (e2) { setErr(e2.message || "Sign-in failed."); setBusy(false); }
  };
  return (
    <div className="pw-auth">
      <form className="pw-auth-card" onSubmit={submit}>
        <div className="pw-auth-brand">
          <span className="pw-logo" style={{ width: 36, height: 36 }}><IconCoin size={22}/></span>
          <span className="pw-auth-word">{cfg.brand.name}{cfg.brand.suffix && <span style={{ color: "var(--accent)" }}>{cfg.brand.suffix}</span>}</span>
        </div>
        <h1 className="pw-auth-title">Sign in to DropCap</h1>

        {err && <div className="pw-auth-err"><IconInfo size={14}/>{err}</div>}

        <label className="pw-lbl">Work email or username</label>
        <Input value={email} onChange={e => setEmail(e.target.value)} placeholder="you@example.com" type="text" autoFocus/>

        <label className="pw-lbl" style={{ marginTop: 14 }}>Password</label>
        <div style={{ position: "relative" }}>
          <Input value={password} onChange={e => setPassword(e.target.value)} placeholder="••••••••" type={show ? "text" : "password"}/>
          <button type="button" className="pw-auth-eye" onClick={() => setShow(s => !s)} aria-label="Toggle password">
            {show ? <IconEyeOff size={15}/> : <IconEye size={15}/>}
          </button>
        </div>

        <Btn kind="primary" type="submit" disabled={busy} style={{ width: "100%", justifyContent: "center", marginTop: 18 }}>
          {busy ? "Signing in…" : "Sign in"}
        </Btn>
      </form>

      <style>{`
        .pw-auth { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px;
          background:
            radial-gradient(1200px 500px at 50% -10%, var(--accent-soft), transparent 60%),
            var(--bg); }
        .pw-auth-card { width: 100%; max-width: 400px; background: var(--panel); border: 1px solid var(--line);
          border-radius: var(--r-lg); box-shadow: var(--shadow-modal); padding: 34px 30px; display: flex; flex-direction: column; }
        .pw-auth-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 22px; }
        .pw-auth-word { font-size: 19px; font-weight: 600; letter-spacing: -.01em; }
        .pw-auth-title { font-size: 19px; font-weight: 600; margin: 0 0 20px; letter-spacing: -.01em; }
        .pw-auth-err { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--bad);
          background: color-mix(in oklab, var(--bad) 9%, transparent); border: 1px solid color-mix(in oklab, var(--bad) 26%, transparent);
          padding: 8px 11px; border-radius: var(--r-sm); margin-bottom: 16px; }
        .pw-auth-eye { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: transparent; border: none;
          cursor: pointer; color: var(--muted); padding: 6px; border-radius: 6px; display: inline-flex; }
        .pw-auth-eye:hover { background: var(--hover); color: var(--ink); }
      `}</style>
    </div>
  );
};

// =================================================================
// Session gate — show the app only with a valid session.
// =================================================================
const SessionGate = ({ children }) => {
  const { valid } = useSession();
  return valid ? children : <SignInScreen/>;
};

Object.assign(window, { SignInScreen, SessionGate });
