import { createCookieSessionStorage, redirect } from "@remix-run/node";

if (!process.env.SESSION_SECRET) {
  throw new Error("SESSION_SECRET environment variable must be set");
}
const SESSION_SECRET = process.env.SESSION_SECRET;

const sessionStorage = createCookieSessionStorage({
  cookie: {
    name: "__nomadic_session",
    httpOnly: true,
    maxAge: 60 * 60 * 24 * 30, // 30 days
    path: "/",
    sameSite: "lax",
    secrets: [SESSION_SECRET],
    secure: process.env.NODE_ENV === "production",
  },
});

export async function getSession(request: Request) {
  return sessionStorage.getSession(request.headers.get("Cookie"));
}

export async function commitSession(session: Awaited<ReturnType<typeof getSession>>) {
  return sessionStorage.commitSession(session);
}

export async function destroySession(session: Awaited<ReturnType<typeof getSession>>) {
  return sessionStorage.destroySession(session);
}

/**
 * Store the JWT token in the server-side cookie session.
 * Call this from an action after successful login.
 */
export async function createUserSession(request: Request, token: string, redirectTo: string) {
  const session = await getSession(request);
  session.set("auth_token", token);
  return redirect(redirectTo, {
    headers: {
      "Set-Cookie": await commitSession(session),
    },
  });
}

/**
 * Get the auth token from the cookie session.
 * Returns null if no token is stored.
 */
export async function getAuthTokenFromSession(request: Request): Promise<string | null> {
  const session = await getSession(request);
  return session.get("auth_token") || null;
}

/**
 * Require authentication in a loader/action. Redirects to /login if not authenticated.
 * Returns the JWT token string if authenticated.
 */
export async function requireAuth(request: Request, redirectTo: string = "/login"): Promise<string> {
  const token = await getAuthTokenFromSession(request);
  if (!token) {
    const url = new URL(request.url);
    const searchParams = new URLSearchParams([["redirectTo", url.pathname]]);
    throw redirect(`${redirectTo}?${searchParams}`);
  }
  return token;
}

/**
 * Logout: destroy the session cookie and redirect.
 */
export async function logout(request: Request) {
  const session = await getSession(request);
  return redirect("/login", {
    headers: {
      "Set-Cookie": await destroySession(session),
    },
  });
}
