"use client";

import { useEffect, useRef } from "react";
import { useSession, signIn } from "next-auth/react";

import type { SessionUser } from "./types";

/**
 * Drop-in client component that re-triggers Keycloak sign-in when the
 * kit's server-side refresh flow gives up (`session.user.error` set to
 * `RefreshAccessTokenError` or `RefreshTokenMissing`).
 *
 * Without this, a UI tab left open past the Keycloak SSO session lifetime
 * holds a stale `accessToken`: the middleware sees a cookie, `requireAuth`
 * sees an `accessToken` string, and the user only finds out things are
 * broken when a downstream API returns 401. Mount this inside a
 * `<SessionProvider>` (typically alongside other providers in the locale
 * root) so the session refetch interval surfaces the error within minutes.
 *
 * Renders nothing.
 */
export function SessionExpirationGuard() {
  const { data: session } = useSession();
  const error = (session?.user as Partial<SessionUser> | undefined)?.error;
  // Guard against React's StrictMode double-invoke + the brief window
  // between calling signIn and the page navigating away.
  const firedRef = useRef(false);

  useEffect(() => {
    if (!error || firedRef.current) return;
    if (
      error !== "RefreshAccessTokenError" &&
      error !== "RefreshTokenMissing"
    ) {
      return;
    }
    firedRef.current = true;
    const callbackUrl =
      typeof window !== "undefined"
        ? window.location.pathname + window.location.search
        : "/";
    // signIn() POSTs the CSRF-protected provider endpoint, which then
    // initiates a fresh OIDC flow; the stale session cookie is replaced
    // atomically when the flow completes. Keycloak's own SSO cookie may
    // still log the user in transparently if it hasn't also expired.
    void signIn("keycloak", { callbackUrl });
  }, [error]);

  return null;
}
