import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

// Next.js 16 renamed `middleware.ts` to `proxy.ts` — this file must live
// at the project root (same level as `app/`), not inside `app/`. See
// node_modules/next/dist/docs/01-app/03-api-reference/03-file-conventions/proxy.md.
//
// Sliding-session refresh: Payload's customers auth token is valid for
// 7200s (2h, Payload default — see Customers.ts in the Payload repo,
// unchanged). Rather than issuing a long-lived token (harder to reason
// about if one ever leaks) or building a separate refresh-token cookie,
// this silently extends the *existing* token via Payload's own built-in
// refresh-token endpoint whenever it's getting close to expiry and the
// customer is actually still browsing — so an active shopper never gets
// logged out mid-session, but someone who walks away is logged out within
// 2h of their last request, same as before.
const SESSION_COOKIE = "ep_customer_token";
const REFRESH_THRESHOLD_MS = 15 * 60 * 1000; // refresh once < 15min remain
const PAYLOAD_URL = process.env.PAYLOAD_URL || "https://payload.mk360.de";

function getTokenExpiry(token: string): number | null {
  try {
    const payloadSegment = token.split(".")[1];
    if (!payloadSegment) return null;
    // Not verified here — this is only a "should I bother refreshing?"
    // heuristic. Payload verifies the token for real on every actual API
    // call regardless of what this function decides.
    const json = JSON.parse(Buffer.from(payloadSegment, "base64url").toString("utf8"));
    return typeof json.exp === "number" ? json.exp * 1000 : null;
  } catch {
    return null;
  }
}

export default async function proxy(request: NextRequest) {
  const token = request.cookies.get(SESSION_COOKIE)?.value;
  if (!token) return NextResponse.next();

  const expiresAt = getTokenExpiry(token);
  if (!expiresAt || expiresAt - Date.now() > REFRESH_THRESHOLD_MS) return NextResponse.next();

  try {
    const res = await fetch(`${PAYLOAD_URL}/api/customers/refresh-token`, {
      method: "POST",
      headers: { Authorization: `JWT ${token}` },
    });
    if (!res.ok) return NextResponse.next();

    const data: { refreshedToken?: string } = await res.json();
    if (!data.refreshedToken) return NextResponse.next();

    const response = NextResponse.next();
    response.cookies.set(SESSION_COOKIE, data.refreshedToken, {
      httpOnly: true,
      secure: true,
      sameSite: "lax",
      path: "/",
      maxAge: 60 * 60 * 2,
    });
    return response;
  } catch {
    // Refresh failing (Payload briefly unreachable etc.) shouldn't block
    // the actual page request — worst case the session just expires
    // normally and the customer logs in again.
    return NextResponse.next();
  }
}

export const config = {
  matcher: ["/checkout", "/konto/:path*", "/api/account/:path*"],
};
