import { FastifyRequest, FastifyReply } from "fastify";
import { verifyAccessToken } from "../services/auth";
import { error } from "../utils/response";
import { AuthData } from "../types";

export async function requireAuth(
  request: FastifyRequest,
  reply: FastifyReply,
): Promise<void> {
  const authHeader = request.headers.authorization;
  if (!authHeader?.startsWith("Bearer ")) {
    return error(reply, "Vyžadována autentizace", 401);
  }

  const token = authHeader.slice(7);
  const authData = await verifyAccessToken(token);

  if (!authData) {
    return error(reply, "Neplatný nebo expirovaný token", 401);
  }

  request.authData = authData;
}

export async function optionalAuth(
  request: FastifyRequest,
  _reply: FastifyReply,
): Promise<void> {
  const authHeader = request.headers.authorization;
  if (!authHeader?.startsWith("Bearer ")) return;

  const token = authHeader.slice(7);
  request.authData = (await verifyAccessToken(token)) ?? undefined;
}

export function requirePermission(...permissionNames: string[]) {
  return async (
    request: FastifyRequest,
    reply: FastifyReply,
  ): Promise<void> => {
    await requireAuth(request, reply);
    if (reply.sent) return;

    const authData = request.authData!;

    // Admin has all permissions
    if (authData.roleName === "admin") return;

    const hasAll = permissionNames.every((p) =>
      authData.permissions.includes(p),
    );
    if (!hasAll) {
      return error(reply, "Nedostatečná oprávnění", 403);
    }
  };
}

export function requireAnyPermission(...permissionNames: string[]) {
  return async (
    request: FastifyRequest,
    reply: FastifyReply,
  ): Promise<void> => {
    await requireAuth(request, reply);
    if (reply.sent) return;

    const authData = request.authData!;

    // Admin has all permissions
    if (authData.roleName === "admin") return;

    const hasAny = permissionNames.some((p) =>
      authData.permissions.includes(p),
    );
    if (!hasAny) {
      return error(reply, "Nedostatečná oprávnění", 403);
    }
  };
}
