import "reflect-metadata";
import { ForbiddenException } from "@nestjs/common";
import { AuthController } from "./auth.controller";
import { PermissionGuard } from "./guards/permission.guard";
import { UserRole } from "./entities/usuario.entity";

// Igual que en permission.guard.spec.ts: getHandler() devuelve el metodo
// REAL del prototype (donde vive la metadata que deja @RequirePermission),
// no un stub -- si alguien le quita el decorador a una ruta, este test lo
// detecta.
function createContext(metodo: keyof AuthController, user: any) {
  const handler = (AuthController.prototype as any)[metodo];
  return {
    getHandler: () => handler,
    getClass: () => AuthController,
    switchToHttp: () => ({ getRequest: () => ({ user }) }),
  } as any;
}

const RUTAS_LECTURA: Array<keyof AuthController> = ["listUsers", "listTiendas"];
const RUTAS_ESCRITURA: Array<keyof AuthController> = [
  "createTienda",
  "updateTienda",
  "createUser",
  "updateUser",
  "setActive",
];

// Antes, listUsers/listTiendas/createUser/updateUser/setActive/createTienda/
// updateTienda usaban un chequeo de rol crudo (ensureCanManageUsers:
// admin/super_admin siempre pasa) que ignoraba el permiso granular
// "usuarios" -- el mismo que el editor de /dashboard/usuarios permite pisar
// por usuario (quitarle "usuarios" a un admin puntual). Resultado: la
// opción seguía funcionando igual aunque se le quitara el acceso. Ahora
// estas rutas usan @RequirePermission("usuarios", ...) + PermissionGuard,
// igual que el resto de los controllers del sistema.
describe("AuthController — permiso granular 'usuarios'", () => {
  const guard = new PermissionGuard();

  it("un admin con 'usuarios' en 'none' (override explícito) no puede listar usuarios ni tiendas", () => {
    const user = { rol: UserRole.ADMIN, permissions: { usuarios: "none" } };

    for (const metodo of RUTAS_LECTURA) {
      expect(() => guard.canActivate(createContext(metodo, user))).toThrow(ForbiddenException);
    }
  });

  it("un admin con 'usuarios' en solo lectura puede listar pero no crear/editar usuarios ni tiendas", () => {
    const user = { rol: UserRole.ADMIN, permissions: { usuarios: "read" } };

    for (const metodo of RUTAS_LECTURA) {
      expect(guard.canActivate(createContext(metodo, user))).toBe(true);
    }
    for (const metodo of RUTAS_ESCRITURA) {
      expect(() => guard.canActivate(createContext(metodo, user))).toThrow(ForbiddenException);
    }
  });

  it("un admin con 'usuarios' en escritura puede listar y también crear/editar usuarios y tiendas", () => {
    const user = { rol: UserRole.ADMIN, permissions: { usuarios: "write" } };

    for (const metodo of [...RUTAS_LECTURA, ...RUTAS_ESCRITURA]) {
      expect(guard.canActivate(createContext(metodo, user))).toBe(true);
    }
  });

  it("SUPER_ADMIN siempre pasa (bypass existente del guard, sin cambios)", () => {
    const user = { rol: UserRole.SUPER_ADMIN, permissions: {} };

    for (const metodo of [...RUTAS_LECTURA, ...RUTAS_ESCRITURA]) {
      expect(guard.canActivate(createContext(metodo, user))).toBe(true);
    }
  });
});
