import { NextRequest, NextResponse } from "next/server";
import { createSessionToken, SESSION_COOKIE } from "@/lib/session";
import { lookupUser, resolveGoogleAuth } from "@/lib/googleAuth";
import { withBase, googleCallbackUrl, COOKIE_PATH } from "@/lib/basePath";

/**
 * Completes the Google OAuth flow: exchanges the code, reads the id_token, then
 * resolves the user against the Users & Roles directory — only users present in
 * the directory may sign in (unless it's empty → bootstrap), and their roles come
 * from there.
 */
export async function GET(req: NextRequest): Promise<NextResponse> {
  const { clientId, clientSecret } = await resolveGoogleAuth();
  if (!clientId || !clientSecret) {
    return NextResponse.redirect(new URL(withBase("/login?error=google_not_configured"), req.url));
  }

  const code = req.nextUrl.searchParams.get("code");
  const state = req.nextUrl.searchParams.get("state");
  const expectedState = req.cookies.get("g_state")?.value;
  if (!code || !state || state !== expectedState) {
    return NextResponse.redirect(new URL(withBase("/login?error=invalid_state"), req.url));
  }

  const redirectUri = googleCallbackUrl(req);
  const tokenResp = await fetch("https://oauth2.googleapis.com/token", {
    method: "POST",
    headers: { "content-type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      code,
      client_id: clientId,
      client_secret: clientSecret,
      redirect_uri: redirectUri,
      grant_type: "authorization_code",
    }),
  });
  const token = await tokenResp.json();
  if (!token.id_token) {
    return NextResponse.redirect(new URL(withBase("/login?error=token_exchange"), req.url));
  }

  const claims = decodeJwtPayload(token.id_token);
  const email = String(claims.email || "");
  const name = String(claims.name || email);
  if (!email) {
    return NextResponse.redirect(new URL(withBase("/login?error=no_email"), req.url));
  }

  const dir = await lookupUser(email);
  if (!dir.found && !dir.anyAllowed) {
    return NextResponse.redirect(new URL(withBase("/login?error=not_allowed"), req.url));
  }
  // Mapped roles when the user exists; least-privilege default during bootstrap.
  const roles = dir.found && dir.roles.length > 0 ? dir.roles : ["monitoring"];
  const session = await createSessionToken({ email, name: dir.name || name, roles });
  const res = NextResponse.redirect(new URL(withBase("/"), req.url));
  res.cookies.set(SESSION_COOKIE, session, {
    httpOnly: true,
    sameSite: "lax",
    path: COOKIE_PATH,
    secure: process.env.NODE_ENV === "production",
    maxAge: 60 * 60 * 12,
  });
  res.cookies.delete({ name: "g_state", path: COOKIE_PATH });
  return res;
}

function decodeJwtPayload(jwt: string): Record<string, unknown> {
  try {
    const part = jwt.split(".")[1];
    const json = Buffer.from(part.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8");
    return JSON.parse(json);
  } catch {
    return {};
  }
}
