import "reflect-metadata";
import { ForbiddenException } from "@nestjs/common";
import { PERMISSION_METADATA_KEY } from "../decorators/require-permission.decorator";
import { UserRole } from "../entities/usuario.entity";
import { PermissionGuard } from "./permission.guard";

function createContext(user: any, requirement?: { module: string; level: "read" | "write" }) {
  function handler() {}
  if (requirement) {
    Reflect.defineMetadata(PERMISSION_METADATA_KEY, requirement, handler);
  }
  class Controller {}
  return {
    getHandler: () => handler,
    getClass: () => Controller,
    switchToHttp: () => ({ getRequest: () => ({ user }) }),
  } as any;
}

// "configuracion" dejo de ser un solo modulo plano y paso a 5 claves
// granulares, una por grupo real del catalogo (taller-parametros.catalogo.ts,
// campo `grupo`) -- ver auth/default-permissions.ts. Los tests cubren las 5,
// no solo una, porque el bug que motivo la separacion (un usuario con
// escritura en notificaciones pero no en facturacion) es justo lo que una
// sola clave de prueba no puede distinguir.
const GRUPOS_CONFIGURACION = [
  "configuracion.facturacion",
  "configuracion.inventario",
  "configuracion.productos",
  "configuracion.tiendas",
  "configuracion.notificaciones",
] as const;

describe("PermissionGuard — módulos configuracion.*", () => {
  const guard = new PermissionGuard();

  it("SUPER_ADMIN siempre pasa (bypass existente, sin cambios)", () => {
    for (const modulo of GRUPOS_CONFIGURACION) {
      const ctx = createContext({ rol: UserRole.SUPER_ADMIN }, { module: modulo, level: "write" });
      expect(guard.canActivate(ctx)).toBe(true);
    }
  });

  it("ADMIN tiene write por default en las 5 claves de configuracion", () => {
    for (const modulo of GRUPOS_CONFIGURACION) {
      const ctx = createContext({ rol: UserRole.ADMIN }, { module: modulo, level: "write" });
      expect(guard.canActivate(ctx)).toBe(true);
    }
  });

  it("OPERATIVO no tiene acceso a ninguna de las 5 claves de configuracion", () => {
    for (const modulo of GRUPOS_CONFIGURACION) {
      const ctx = createContext({ rol: UserRole.OPERATIVO }, { module: modulo, level: "read" });
      expect(() => guard.canActivate(ctx)).toThrow(ForbiddenException);
    }
  });

  it("RECEPCION no tiene acceso a ninguna de las 5 claves de configuracion", () => {
    for (const modulo of GRUPOS_CONFIGURACION) {
      const ctx = createContext({ rol: UserRole.RECEPCION }, { module: modulo, level: "read" });
      expect(() => guard.canActivate(ctx)).toThrow(ForbiddenException);
    }
  });

  it("MECANICO no tiene acceso a ninguna de las 5 claves de configuracion", () => {
    for (const modulo of GRUPOS_CONFIGURACION) {
      const ctx = createContext({ rol: UserRole.MECANICO }, { module: modulo, level: "read" });
      expect(() => guard.canActivate(ctx)).toThrow(ForbiddenException);
    }
  });

  it("un usuario puede tener write en un grupo y none en otro (permiso granular real)", () => {
    const user = {
      rol: UserRole.OPERATIVO,
      permissions: { "configuracion.notificaciones": "write" },
    };
    const puedeNotificaciones = createContext(user, { module: "configuracion.notificaciones", level: "write" });
    const noPuedeFacturacion = createContext(user, { module: "configuracion.facturacion", level: "read" });

    expect(guard.canActivate(puedeNotificaciones)).toBe(true);
    expect(() => guard.canActivate(noPuedeFacturacion)).toThrow(ForbiddenException);
  });
});
