/**
 * persistSessionCookie — AUTH-02: upgrade the OIDC session cookie to a persistent one.
 *
 * WHY THIS EXISTS
 * ---------------
 * @hono/oidc-auth 1.8.3 sets its `oidc-auth` session cookie with
 *   { path, httpOnly: true, secure: true [, domain] }
 * and NO maxAge/expires. That makes it a SESSION-SCOPED cookie: the browser discards
 * it when the PWA or browser tab is closed. On reopen there is no cookie, so the OIDC
 * guard 302-redirects to Authelia and forces a full re-login — even though the
 * server-side JWT is still valid for OIDC_AUTH_EXPIRES seconds (default 86 400 / 1 day).
 *
 * The library has no option to set maxAge. This middleware wraps around it and
 * re-issues the same signed JWT as a persistent cookie (with maxAge + sameSite:'Lax').
 *
 * WHEN THE RE-ISSUE FIRES
 * -----------------------
 * @hono/oidc-auth calls `c.set('oidcAuthJwt', session_jwt)` ONLY on requests where a
 * valid session is created or refreshed. Logged-out / no-session / unauthenticated
 * requests do NOT set `oidcAuthJwt`. This is the guard signal: re-issue the persistent
 * cookie only when the library produced a valid session this request.
 */

import type { MiddlewareHandler } from 'hono';
import { setCookie } from 'hono/cookie';

/**
 * Returns a Hono MiddlewareHandler that upgrades the session-scoped oidc-auth cookie
 * (set by @hono/oidc-auth) to a persistent cookie with a Max-Age.
 *
 * Mount immediately after oidcAuthMiddleware() on '/api/*' inside the !devBypassActive
 * block in index.ts. Under dev bypass there is no oidc-auth cookie so it must not run.
 */
export function persistSessionCookie(): MiddlewareHandler {
  return async (c, next) => {
    // Read the freshly-signed session JWT placed on context by @hono/oidc-auth.
    // The 'as never' cast is required because 'oidcAuthJwt' is a library-internal key
    // that is not declared in Hono's ContextVariableMap — mirrors the loose-context
    // convention used elsewhere in this codebase (e.g. resolveUserId).
    const jwt = c.get('oidcAuthJwt' as never) as string | undefined;

    // CRITICAL CORRECTNESS GUARD: if no valid session JWT is on context (logged-out,
    // deleted, or never-set request), do NOT touch cookies and fall straight through.
    // This property prevents resurrecting a deleted or absent cookie. Without it a
    // logged-out user would receive a new oidc-auth Set-Cookie with no value, which
    // could re-authenticate them or produce confusing browser state.
    if (!jwt) {
      await next();
      return;
    }

    // A valid session JWT is present — re-issue the cookie BEFORE next() so that if
    // any future downstream handler deletes the cookie, that delete Set-Cookie header
    // comes last and wins (safe ordering even without a current logout/revoke route).
    const name = process.env.OIDC_COOKIE_NAME ?? 'oidc-auth';
    const path = process.env.OIDC_COOKIE_PATH ?? '/';
    const maxAge = Number(process.env.OIDC_AUTH_EXPIRES ?? 86400);

    // Build the options object. domain is included ONLY when OIDC_COOKIE_DOMAIN is set —
    // mirroring the library's own conditional-domain logic so the two Set-Cookie headers
    // carry identical scope attributes (avoids a split-cookie situation where the library
    // sets domain=X but we set no domain, or vice-versa).
    const options: Parameters<typeof setCookie>[3] = {
      path,
      httpOnly: true,
      secure: true,
      sameSite: 'Lax',
      maxAge, // seconds — Hono's setCookie maxAge unit matches OIDC_AUTH_EXPIRES unit
    };

    if (process.env.OIDC_COOKIE_DOMAIN) {
      options.domain = process.env.OIDC_COOKIE_DOMAIN;
    }

    // Re-issue the same JWT the library signed. Do NOT re-sign or modify the payload.
    setCookie(c, name, jwt, options);

    await next();
  };
}
