// Vanday — current-user / plan-limits hook.
//
// Single source of truth for "who am I, what plan am I on, what can I do."
// Other components read this via the global useVandayMe() hook so they only
// need to know about React state — no manual fetching, no prop-drilling.

(function () {
  // Cache the response on window so components mounted later don't re-fetch.
  let cache = null;
  let inflight = null;
  const subscribers = new Set();

  function setCache(data) {
    cache = data;
    subscribers.forEach((fn) => { try { fn(data); } catch {} });
  }

  async function fetchMe() {
    if (inflight) return inflight;
    inflight = (async () => {
      try {
        const r = await fetch("/api/me", {
          headers: await authHeaders(),
        });
        if (!r.ok) { setCache(null); return null; }
        const data = await r.json();
        setCache(data);
        return data;
      } finally { inflight = null; }
    })();
    return inflight;
  }

  async function authHeaders() {
    try {
      const session = window.Clerk && window.Clerk.session;
      if (!session) return {};
      const token = await session.getToken();
      return token ? { Authorization: `Bearer ${token}` } : {};
    } catch { return {}; }
  }

  // Mark the welcome modal as seen on the server, then clear it locally.
  async function markOnboarded() {
    try {
      await fetch("/api/onboarded", {
        method: "POST",
        headers: await authHeaders(),
      });
    } catch {}
    if (cache && cache.user) {
      setCache({ ...cache, user: { ...cache.user, onboardedAt: Date.now() } });
    }
  }

  // React hook: returns the current "me" object, refreshing on demand.
  function useVandayMe() {
    const [me, setMe] = React.useState(cache);
    React.useEffect(() => {
      const handler = (d) => setMe(d);
      subscribers.add(handler);
      if (cache === null && !inflight) { fetchMe(); }
      return () => { subscribers.delete(handler); };
    }, []);
    return me;
  }

  // Convenience: limits with safe defaults so components don't need to check
  // for nulls when /api/me hasn't loaded yet.
  function useVandayLimits() {
    const me = useVandayMe();
    return {
      maxUploads:        me?.limits?.maxUploads ?? 100,
      maxSeats:          me?.limits?.maxSeats ?? 3,
      maxStorageBytes:   me?.limits?.maxStorageBytes ?? (50 * 1024 * 1024 * 1024),
      uploadsUsed:       me?.usage?.uploads ?? 0,
      storageBytesUsed:  me?.usage?.storageBytes ?? 0,
      sharingEnabled:    me?.limits?.sharingEnabled ?? false,
      publishingEnabled: me?.limits?.publishingEnabled ?? false,
      planName:          me?.plan?.name || "free_beta",
      loaded:            me !== null && me !== undefined,
    };
  }

  // Feature-gate hook: returns the per-surface visibility map driven by
  // VANDAY_MODE. Default everything OFF until /api/me loads so we don't
  // briefly flash beta-restricted UI on first render. Dev mode flips them
  // all on; beta keeps them off.
  function useVandayFeatures() {
    const me = useVandayMe();
    const f = me?.features || {};
    // Per-member capabilities, mirroring the server's role enforcement:
    //   admin / editor -> write + publish, contributor -> write only,
    //   viewer -> read/download only. We only RESTRICT when the role is
    //   positively known to be limited; legacy / personal / super-admin
    //   contexts (no org role, or role "admin") keep full access. This matches
    //   the server, which blocks ONLY a positively-resolved viewer/contributor.
    const orgRole = me?.org?.role || null;
    return {
      mode:             me?.mode || "beta",
      isAdmin:          me?.isAdmin === true,
      // Workspace (org) admin: the role that can manage members + workspace
      // settings. Super-admins (isAdmin) always count. Personal workspaces make
      // their sole member an admin, so solo users keep full access.
      isWorkspaceAdmin: me?.isAdmin === true || me?.org?.role === "admin",
      // canWrite: may upload / edit / delete / organize. Only viewers can't.
      canWrite:         orgRole !== "viewer",
      // canPublish: may push to social. Viewers and contributors can't.
      canPublish:       orgRole !== "viewer" && orgRole !== "contributor",
      sharing:          f.sharing === true,
      publishing:       f.publishing === true,
      apiKeys:          f.apiKeys === true,
      webhooks:         f.webhooks === true,
      audit:            f.audit === true,
      versions:         f.versions === true,
      comments:         f.comments === true,
      contentSecurity:  f.contentSecurity === true,
      usageBilling:     f.usageBilling === true,
      branding:         f.branding === true,
      projects:         f.projects === true,
      notifications:    f.notifications === true,
      integrations:     f.integrations === true,
      loaded:           me !== null && me !== undefined,
    };
  }

  window.VandayMe = { fetchMe, markOnboarded };
  window.useVandayMe = useVandayMe;
  window.useVandayLimits = useVandayLimits;
  window.useVandayFeatures = useVandayFeatures;
})();
