/**
 * Verify magic link token and complete the OIDC login interaction.
 *
 * GET /oidc/interaction/verify?token=...
 *
 * This is the endpoint the magic link email points to. It:
 * 1. Verifies the JWT token
 * 2. Sets the Ghost Guild auth-token cookie
 * 3. Redirects the user back to the wiki — [uid].get.ts will then SSO them
 *    into a fresh OIDC interaction using that cookie
 *
 * We do NOT call provider.interactionFinished here because it requires the
 * short-lived _interaction cookie on the request, which is missing when the
 * user clicks the email link on a different device, in a different browser,
 * in a private window, or after the interaction cookie expired. That path
 * throws SessionNotFound, which was leaving users stranded on /coming-soon.
 */
import jwt from "jsonwebtoken";
import Member from "../../../models/member.js";
import { connectDB } from "../../../utils/mongoose.js";

const OIDC_ERROR = (description: string) =>
  `/auth/oidc-error?error=invalid_request&error_description=${encodeURIComponent(description)}`;

export default defineEventHandler(async (event) => {
  const { token } = getQuery(event);

  if (!token) {
    return sendRedirect(event, OIDC_ERROR("Login link is missing its token."), 302);
  }

  const config = useRuntimeConfig(event);

  let decoded: { memberId: string; oidcUid: string };
  try {
    decoded = jwt.verify(token as string, config.jwtSecret) as typeof decoded;
  } catch {
    return sendRedirect(
      event,
      OIDC_ERROR("This login link is invalid or has expired. Please request a new one."),
      302
    );
  }

  await connectDB();
  const member = await (Member as any).findById(decoded.memberId);

  if (!member) {
    return sendRedirect(event, OIDC_ERROR("Member not found."), 302);
  }

  if (member.status === "suspended" || member.status === "cancelled") {
    return sendRedirect(
      event,
      OIDC_ERROR(`Account is ${member.status}.`),
      302
    );
  }

  const sessionToken = jwt.sign(
    { memberId: member._id, email: member.email, tv: member.tokenVersion },
    config.jwtSecret,
    { expiresIn: "7d" }
  );

  setCookie(event, "auth-token", sessionToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    sameSite: "lax",
    path: "/",
    maxAge: 60 * 60 * 24 * 7,
  });

  // Send the user back to the wiki. Outline will bounce them to /oidc/auth,
  // which creates a fresh interaction whose cookie WILL be present, and then
  // [uid].get.ts sees the auth-token we just set and SSOs them through.
  return sendRedirect(event, "https://wiki.ghostguild.org", 302);
});
