import type { FastifyReply, FastifyRequest } from "fastify";

const ALL_ROLES = ["Admin", "Form Builder", "Master Data Manager", "Read-only"] as const;
const WRITERS   = ["Admin", "Form Builder"] as const;
const ADMINS    = ["Admin"] as const;
const MDM_WRITE = ["Admin", "Master Data Manager"] as const;

/**
 * Method-aware authorization matrix.
 * Each entry: [HTTP method ("*" = any), URL prefix, allowed roles].
 * Entries are evaluated in order — first match wins.
 * Empty roles array [] = public route.
 */
const MATRIX: Array<[string, string, readonly string[]]> = [
  // Public
  ["*",      "/health",                      []],
  // Forms — read-only endpoints (GET)
  ["GET",    "/api/forms/schema",             ALL_ROLES],
  ["GET",    "/api/forms",                    ALL_ROLES],
  // Forms — write endpoints
  ["POST",   "/api/forms/submissions",        WRITERS],
  ["POST",   "/api/forms",                    WRITERS],
  ["PATCH",  "/api/forms",                    WRITERS],
  ["DELETE", "/api/forms",                    ADMINS],
  // Master data — read
  ["GET",    "/api/master-data",              ALL_ROLES],
  // Master data — write
  ["POST",   "/api/master-data",              MDM_WRITE],
  ["PATCH",  "/api/master-data",              MDM_WRITE],
  ["DELETE", "/api/master-data",              ADMINS],
];

export async function authorize(request: FastifyRequest, reply: FastifyReply): Promise<void> {
  const role   = (request.headers["x-maf-role"] as string | undefined) ?? "Read-only";
  const method = request.method.toUpperCase();
  const path   = request.url.split("?")[0] ?? "";

  for (const [entryMethod, prefix, allowed] of MATRIX) {
    if (!path.startsWith(prefix)) continue;
    if (entryMethod !== "*" && entryMethod !== method) continue;

    if (allowed.length === 0) return;                       // public
    if ((allowed as string[]).includes(role)) return;       // authorized

    return void reply.code(403).send({ message: "Forbidden for current role" });
  }

  return void reply.code(403).send({ message: "Forbidden: route not permitted" });
}
