// GET /api/pam/approve/[token]
//
// Approval link clicked by the configured approver. Validates the
// token, activates the grant, audits the click. Tokens expire 24 h
// after the grant was requested; expired tokens deny the grant.
//
// This endpoint is intentionally NOT behind the auth middleware
// (handled by the matcher in middleware.ts) — the token IS the
// auth. Token is 24 bytes of base64url randomness.

import { prisma } from "@/database/prisma";
import { invalidateAuthzCache } from "@/lib/authz";
import { recordAudit } from "@/lib/pam";

export const dynamic = "force-dynamic";

const APPROVAL_TOKEN_TTL_MS = 24 * 60 * 60 * 1000;

function htmlPage(title: string, body: string, accent = "#0066cc"): Response {
  const html = `<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <title>${title} — GSC Admin PAM</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { font-family: system-ui, sans-serif; max-width: 480px; margin: 6rem auto; padding: 0 1rem; color: #222; }
    .card { border: 1px solid #ddd; border-radius: 8px; padding: 2rem; box-shadow: 0 2px 8px rgba(0,0,0,.05); }
    h1 { color: ${accent}; margin-top: 0; }
    code { background: #f4f4f4; padding: 1px 4px; border-radius: 3px; }
  </style>
</head><body>
  <div class="card">
    <h1>${title}</h1>
    ${body}
  </div>
</body></html>`;
  return new Response(html, {
    status: 200,
    headers: { "content-type": "text/html; charset=utf-8" },
  });
}

export async function GET(_req: Request, ctx: { params: Promise<{ token: string }> }) {
  const { token } = await ctx.params;
  if (!token || token.length < 16) {
    return htmlPage("Invalid link", "<p>This approval link is malformed.</p>", "#cc0000");
  }

  const grant = await prisma.privilegeGrant.findUnique({
    where: { approvalToken: token },
    select: {
      id: true,
      status: true,
      gscsid: true,
      roleName: true,
      requestedAt: true,
      expiresAt: true,
      justification: true,
      policy: { select: { approverEmail: true } },
    },
  });

  if (!grant) {
    return htmlPage(
      "Link not found",
      "<p>No matching pending request — it may have been revoked or already approved.</p>",
      "#cc0000",
    );
  }

  if (grant.status === "active") {
    return htmlPage(
      "Already approved",
      `<p>The request for <code>${escapeHtml(grant.roleName)}</code> is already active.</p>`,
    );
  }
  if (grant.status !== "pending") {
    return htmlPage(
      "Cannot approve",
      `<p>This request is in state <code>${escapeHtml(grant.status)}</code> and can't be approved.</p>`,
      "#cc0000",
    );
  }

  const ageMs = Date.now() - grant.requestedAt.getTime();
  if (ageMs > APPROVAL_TOKEN_TTL_MS) {
    await prisma.privilegeGrant.update({
      where: { id: grant.id },
      data: { status: "denied" },
    });
    await recordAudit({
      event: "denied",
      gscsid: grant.gscsid,
      roleName: grant.roleName,
      grantId: grant.id,
      detail: { reason: "approval_token_expired" },
    });
    return htmlPage(
      "Link expired",
      `<p>This approval link expired (older than 24 h). The request has been denied; the user can submit a new request.</p>`,
      "#cc0000",
    );
  }

  // Recompute expires_at relative to NOW (the duration stays the same).
  const durationMs = grant.expiresAt.getTime() - grant.requestedAt.getTime();
  const newExpires = new Date(Date.now() + durationMs);

  await prisma.privilegeGrant.update({
    where: { id: grant.id },
    data: {
      status: "active",
      grantedAt: new Date(),
      expiresAt: newExpires,
      approvalToken: null,             // burn the token
      grantedBy: grant.policy?.approverEmail ?? "approver",
    },
  });

  await recordAudit({
    event: "approved-manual",
    gscsid: grant.gscsid,
    roleName: grant.roleName,
    grantId: grant.id,
    actorEmail: grant.policy?.approverEmail ?? null,
  });
  await recordAudit({
    event: "activated",
    gscsid: grant.gscsid,
    roleName: grant.roleName,
    grantId: grant.id,
    actorEmail: grant.policy?.approverEmail ?? null,
  });
  invalidateAuthzCache(grant.gscsid, grant.roleName);

  return htmlPage(
    "Approved",
    `<p>Granted <code>${escapeHtml(grant.roleName)}</code> until <strong>${newExpires.toISOString()}</strong>.</p>
     <p>The requesting user can now use this privilege without re-logging in.</p>`,
    "#0a8a3e",
  );
}

function escapeHtml(s: string): string {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}
