import { CanActivate, ExecutionContext, Injectable, ServiceUnavailableException } from "@nestjs/common";
import { PrismaService } from "../prisma/prisma.service";

const maintenanceRoles = new Set(["SUPPORT", "MODERATOR", "ADMIN", "SUPER_ADMIN"]);
const alwaysAvailablePaths = new Set([
  "/health/live",
  "/health/ready",
  "/settings/public",
  "/auth/login",
  "/auth/google",
  "/auth/refresh",
  "/auth/logout",
]);

@Injectable()
export class MaintenanceGuard implements CanActivate {
  constructor(private readonly prisma: PrismaService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    if (context.getType() !== "http") return true;
    const request = context.switchToHttp().getRequest<{ originalUrl?: string; url?: string; user?: { role?: string } }>();
    const path = String(request.originalUrl ?? request.url ?? "")
      .split("?")[0]
      .replace(/^\/api(?=\/|$)/, "");
    if (alwaysAvailablePaths.has(path)) return true;

    const setting = await this.prisma.appSetting.findUnique({ where: { key: "maintenanceMode" }, select: { value: true } });
    if (setting?.value !== true) return true;
    if (request.user?.role && maintenanceRoles.has(request.user.role)) return true;
    throw new ServiceUnavailableException("maintenance_mode");
  }
}
