// Per-tab session state for the currently logged-in user.
//
// Only mutated client-side (onMount / form submits) so the module-level
// instance can't leak across SSR requests — SSR always renders the
// `loaded === false` state, and the client refreshes after hydration.
//
// IMPORTANT: do not call any `api/*` helper from `+page.server.ts` /
// `+layout.server.ts`. The `setOn401Hook` below is registered at
// module load (gated on `browser`, so it only fires in the client
// bundle), so a 401 from a server-side fetch would mutate this
// module-level `session.user` across SvelteKit requests — a real
// cross-request state leak. The `if (browser)` guard makes that
// failure mode mechanical rather than convention-based.

import { browser } from '$app/environment';
import { setOn401Hook } from './api/client';
import { me, type User } from './api/auth';

class SessionStore {
    user = $state<User | null>(null);
    loaded = $state(false);
    // Bumped on every explicit setUser so an in-flight refresh started before
    // a login/logout can't clobber the fresh state when it resolves.
    private seq = 0;

    async refresh(): Promise<void> {
        const seq = this.seq;
        try {
            const u = await me();
            if (seq === this.seq) this.user = u;
        } finally {
            this.loaded = true;
        }
    }

    setUser(user: User | null): void {
        this.seq++;
        this.user = user;
        this.loaded = true;
    }
}

export const session = new SessionStore();

// When any backend call returns 401, drop the cached user. Before this
// hook, the `*OrEmpty` wrappers silently returned empty pages on 401
// — so a mid-session expiry left the UI rendering as "logged in but
// no bookmarks/collections/etc." until the user manually reloaded.
// With the hook the session.user reactive store flips to null on the
// first 401, so the layout re-renders the login affordance.
//
// Gated on `browser` so it's only installed in the client bundle.
// See the module-level comment above for the SSR rationale.
if (browser) {
    setOn401Hook(() => session.setUser(null));
}
