/**
 * Server-side session read for the admin shell (task 3.4).
 *
 * The layout resolves the session on the server so an unauthenticated visitor is redirected
 * before any admin markup is generated — rather than flashing a dashboard skeleton and then
 * discovering, client-side, that there is no session.
 *
 * The role that comes back drives which navigation items render. That is presentation only.
 * FastAPI re-reads the role from the database on every request, so a stale or forged
 * session here cannot widen anyone's permissions (task 8.1).
 */
import "server-only";

import { cookies } from "next/headers";

import type { components } from "./schema";

export type Session = components["schemas"]["SessionRead"];

const API_BASE = process.env.INTERNAL_API_URL ?? "http://api:8000";

/** Returns null when there is no valid session, so callers redirect rather than throw. */
export async function readSession(): Promise<Session | null> {
  // Server-to-server over the internal network, so the browser's cookie must be forwarded
  // explicitly — it is not attached automatically the way it is on a same-origin fetch.
  const jar = await cookies();
  const header = jar
    .getAll()
    .map((c) => `${c.name}=${c.value}`)
    .join("; ");

  const response = await fetch(`${API_BASE}/api/auth/me`, {
    headers: { accept: "application/json", ...(header ? { cookie: header } : {}) },
    cache: "no-store",
  });

  if (response.status === 401 || response.status === 403) return null;
  if (!response.ok) throw new Error(`auth/me failed: ${response.status}`);
  return (await response.json()) as Session;
}

/** True when the signed-in role holds a capability, for hiding controls it cannot use. */
export function can(session: Session, action: string): boolean {
  return session.permissions.includes(action);
}
