/* ──────────────────────────────────────────────────────────────────────
   user-detail.jsx — perms v2 (feedback b030cab9)
   ──────────────────────────────────────────────────────────────────────
   #user/:id detail page. Shows the user's role badge, sites, and an
   editable atomic capability grid. The grid is greyed for caps the
   inviter (caller) doesn't hold — the funnel.

   Save behaviour: PUT /api/auth/users/:id with { capabilities }. The
   server caps to the granter's set automatically and returns the
   effective capability array, which we mirror back into local state.
   "Reset to role default" sends { reset_capabilities: true }.
   ────────────────────────────────────────────────────────────────────── */

function UserDetailScreen({ param }) {
  const userId = param;
  const [user, setUser] = useState(null);
  const [caps, setCaps] = useState([]);
  const [originalCaps, setOriginalCaps] = useState([]);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);

  function load() {
    setLoading(true);
    setErr(null);
    apiFetch(`/api/auth/users/${userId}`)
      .then((res) => {
        const u = res.user || res;
        setUser(u);
        const c = Array.isArray(u.capabilities) ? u.capabilities : [];
        setCaps(c);
        setOriginalCaps(c);
        setLoading(false);
      })
      .catch((e) => { setErr(e.message); setLoading(false); });
  }

  useEffect(load, [userId]);

  /* Avoid sending a no-op PUT every time the inviter touches the grid; we
     only enable Save when the set actually differs from what's persisted. */
  const dirty = useMemo(() => {
    if (caps.length !== originalCaps.length) return true;
    const a = new Set(caps); for (const c of originalCaps) if (!a.has(c)) return true;
    return false;
  }, [caps, originalCaps]);

  async function save() {
    setBusy(true); setErr(null);
    try {
      const res = await apiFetch(`/api/auth/users/${userId}`, {
        method: 'PUT',
        body: JSON.stringify({ capabilities: caps }),
      });
      const newCaps = Array.isArray(res.capabilities) ? res.capabilities : caps;
      setCaps(newCaps);
      setOriginalCaps(newCaps);
      window.toast && window.toast.success('Capabilities updated');
    } catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  }

  async function resetToRoleDefault() {
    if (!window.confirm(`Reset ${user?.name || user?.email}'s capabilities to the ${user?.role} role default?`)) return;
    setBusy(true); setErr(null);
    try {
      const res = await apiFetch(`/api/auth/users/${userId}`, {
        method: 'PUT',
        body: JSON.stringify({ reset_capabilities: true }),
      });
      const newCaps = Array.isArray(res.capabilities) ? res.capabilities : [];
      setCaps(newCaps);
      setOriginalCaps(newCaps);
      window.toast && window.toast.success('Reset to role default');
    } catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  }

  if (loading) {
    return <div style={{ padding: 28, color: 'var(--aq-text-faint)' }}>Loading user…</div>;
  }
  if (err) {
    return (
      <div style={{
        padding: 28, color: 'var(--aq-danger)',
      }}>{err}</div>
    );
  }
  if (!user) {
    return <div style={{ padding: 28 }}>User not found.</div>;
  }

  return (
    <div className="aq-page" style={{ padding: 24, maxWidth: 760, margin: '0 auto' }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 14, marginBottom: 18,
      }}>
        <button
          className="x-btn ghost"
          onClick={() => { window.location.hash = '#users'; }}
        >← Back to Users</button>
      </div>

      <header style={{
        display: 'flex', alignItems: 'center', gap: 14, marginBottom: 22,
      }}>
        <div style={{
          width: 56, height: 56, borderRadius: '50%',
          background: 'var(--aq-surface-2)', border: '1px solid var(--aq-line)',
          display: 'grid', placeItems: 'center',
          fontSize: 18, color: 'var(--aq-text)', fontWeight: 500,
        }}>{(user.name || user.email || '?').slice(0, 2).toUpperCase()}</div>
        <div style={{ flex: 1 }}>
          <h1 style={{ margin: 0, fontSize: 19, color: 'var(--aq-text)', fontWeight: 500 }}>
            {user.name || user.email}
          </h1>
          <div style={{ fontSize: 12, color: 'var(--aq-text-faint)', marginTop: 4 }}>
            {user.email} · <strong style={{ color: 'var(--aq-text-muted)' }}>{user.role}</strong>
            {user.capabilities_customised && (
              <span style={{
                marginLeft: 8, padding: '1px 6px', fontSize: 10.5,
                borderRadius: 999, background: 'color-mix(in srgb, var(--aq-accent) 18%, transparent)',
                color: 'var(--aq-accent)',
              }}>Custom set</span>
            )}
          </div>
        </div>
      </header>

      <section style={{ marginBottom: 18 }}>
        <h2 style={{
          fontSize: 12, letterSpacing: 0.5, textTransform: 'uppercase',
          color: 'var(--aq-text-faint)', margin: '0 0 10px',
        }}>Capabilities</h2>
        <CapabilityGrid
          value={caps}
          onChange={setCaps}
          forRole={user.role}
        />
      </section>

      <footer style={{
        display: 'flex', justifyContent: 'flex-end', gap: 10, marginTop: 18,
        position: 'sticky', bottom: 0, background: 'var(--aq-page)',
        padding: '12px 0', borderTop: '1px solid var(--aq-line)',
      }}>
        <button
          className="x-btn ghost"
          onClick={resetToRoleDefault}
          disabled={busy}
        >Reset to role default</button>
        <button
          className="x-btn"
          onClick={save}
          disabled={busy || !dirty}
        >{busy ? 'Saving…' : (dirty ? 'Save changes' : 'Saved')}</button>
      </footer>
    </div>
  );
}

window.UserDetailScreen = UserDetailScreen;
