// The Lucia project.
// Copyright 2026-2026 DSP, inc.  All rights reserved.
// Authors:
//   imacat.yang@dsp.im (imacat), 2026/03/08
/**
 * @module router/authGuard Shared auth-guard decision logic for router.beforeEach
 *   and unit tests.
 */

/** Minimal route shape used by auth guard decision logic. */
export interface GuardRouteTarget {
  name?: unknown;
  path?: string;
  fullPath?: string;
  matched?: Array<{ meta?: { requiresAuth?: boolean } }>;
}

/** Dependency contract for evaluating authentication navigation decisions. */
export interface AuthGuardDependencies {
  /** Reads a cookie value by name. */
  getCookie: (name: string) => string | null;
  /** Attempts to refresh session credentials. */
  refreshSession: () => Promise<void>;
  /** Persists the logged-in marker cookie after successful refresh. */
  setLoginMarker: () => void;
  /** Encodes return-to path into query-safe payload. */
  encodeReturnTo: (returnToPath: string) => string;
}

/**
 * Evaluates auth-related navigation decisions.
 * @param {GuardRouteTarget} to - Target route object from router guard.
 * @param {AuthGuardDependencies} deps - Side-effect dependencies for auth checks.
 * @returns {Promise<{name: string}|{path: string, query: {"return-to": string}}|undefined>}
 *   Redirect target when needed, otherwise undefined.
 */
export async function evaluateAuthNavigation(
  to: GuardRouteTarget,
  deps: AuthGuardDependencies,
) {
  const hasLoginMarker = Boolean(deps.getCookie("isLuciaLoggedIn"));
  const hasAccessToken = Boolean(deps.getCookie("luciaToken"));
  const hasRefreshToken = Boolean(deps.getCookie("luciaRefreshToken"));
  const isAuthenticated = hasLoginMarker && hasAccessToken;

  if (to.name === "Login" && isAuthenticated) {
    return { name: "Files" };
  }

  const requiresAuth = (to.matched || []).some(
    (routeRecord) => routeRecord.meta?.requiresAuth,
  );
  if (!requiresAuth || isAuthenticated) {
    return undefined;
  }

  if (hasRefreshToken) {
    try {
      await deps.refreshSession();
      deps.setLoginMarker();
      return undefined;
    } catch {
      // Fall through to login redirect below.
    }
  }

  const returnToPath = to.fullPath || to.path || "/";
  return {
    path: "/login",
    query: {
      "return-to": deps.encodeReturnTo(returnToPath),
    },
  };
}
