// Where Plex returns the user after they sign in.
//
// A ROUTE HANDLER, NOT A PAGE, AND THAT IS THE POINT. Finishing the link means
// deleting the PIN cookie and revalidating the profile, and Next.js permits
// neither during a page render. Doing this on /profile is why linking never
// completed: Plex returned the user, the page tried to clear the cookie mid
// render, and threw.
//
// The forward URL has NO QUERY STRING either, which matters more than it looks.
// Plex passes it inside the fragment of app.plex.tv/auth#?...&forwardUrl=...,
// where it is parsed by their client-side code rather than by a server. A bare
// path cannot be mangled by that; one carrying its own `?a=b` depends entirely
// on how carefully somebody else's parser splits a string.

import { cookies } from "next/headers";
import { revalidatePath } from "next/cache";
import { NextResponse } from "next/server";

import { auth } from "@/auth";
import { appUrl } from "@/lib/app-url";
import { completePlexLink, PIN_COOKIE } from "@/lib/plex-link";

export const dynamic = "force-dynamic";

function backToProfile(params: Record<string, string | undefined>) {
  const url = new URL(appUrl("/profile"));
  for (const [key, value] of Object.entries(params)) {
    if (value) url.searchParams.set(key, value);
  }
  return NextResponse.redirect(url);
}

export async function GET() {
  const session = await auth();
  // The session cookie is SameSite=Lax and this is a top-level GET navigation,
  // so it is sent even though Plex is a different site. No session here means
  // the person genuinely signed out mid-flow.
  if (!session?.user?.id) return NextResponse.redirect(new URL(appUrl("/login")));

  const jar = await cookies();
  const pinId = jar.get(PIN_COOKIE)?.value;

  // No PIN means somebody reached this URL without starting a link. Nothing to
  // finish, and nothing worth an error page.
  if (!pinId) return backToProfile({});

  const result = await completePlexLink(session.user.id, Number(pinId));

  const response = backToProfile({
    plex: result.outcome,
    who: result.username,
    // Truncated: this ends up in a URL, and the full text of a Plex error is
    // for the log rather than the address bar.
    reason: result.reason?.slice(0, 120),
  });

  // Allowed here, unlike in a render. Both are why this route exists.
  response.cookies.delete(PIN_COOKIE);
  revalidatePath("/profile");
  revalidatePath("/embed/profile");

  return response;
}
