import { ForbiddenException } from "@nestjs/common";
import { SyncService } from "./sync.service";

// Los catalogos de danos y "cosas que trae" se escriben desde la cola offline
// directo contra CatalogosService, sin pasar por el controller (y por tanto sin
// pasar por RequiereFlagGuard): este es el unico punto que los protege.
function crearSync(flags: Record<string, boolean>) {
  const catalogosService = {
    createCosaTrae: jest.fn(async () => ({ id: 1 })),
    createTipoDano: jest.fn(async () => ({ id: 1 })),
    createTipoVehiculo: jest.fn(async () => ({ id: 1 })),
  };
  const tallerParametros = {
    exigirHabilitado: jest.fn(async (clave: string) => {
      if (!(flags[clave] ?? true)) throw new ForbiddenException(`${clave} apagado`);
    }),
  };
  const servicio = new SyncService(
    {} as any,
    {} as any,
    {} as any,
    catalogosService as any,
    {} as any,
    tallerParametros as any,
  );
  const procesar = (eventType: string, payload: any = {}) =>
    (servicio as any).processEvent(
      { eventId: "e1", eventType, entityType: "x", localId: "l1", payload, timestamp: 1 },
      1,
      new Map(),
    );
  return { procesar, catalogosService, tallerParametros };
}

describe("SyncService — gating de eventos offline", () => {
  it("rechaza altas de 'cosas que trae' con el flag apagado, sin escribir", async () => {
    const { procesar, catalogosService } = crearSync({ "ot.usa_cosas_trae": false });

    await expect(procesar("CREATE_COSA_TRAE", { nombre: "Gata" })).rejects.toThrow("ot.usa_cosas_trae");

    expect(catalogosService.createCosaTrae).not.toHaveBeenCalled();
  });

  it.each(["CREATE_COSA_TRAE", "UPDATE_COSA_TRAE", "INACTIVATE_COSA_TRAE"])("%s respeta ot.usa_cosas_trae", async (evento) => {
    const { procesar } = crearSync({ "ot.usa_cosas_trae": false });

    await expect(procesar(evento)).rejects.toThrow("ot.usa_cosas_trae");
  });

  it.each(["CREATE_TIPO_DANO", "UPDATE_TIPO_DANO", "INACTIVATE_TIPO_DANO"])("%s respeta ot.usa_danos", async (evento) => {
    const { procesar } = crearSync({ "ot.usa_danos": false });

    await expect(procesar(evento)).rejects.toThrow("ot.usa_danos");
  });

  it("con los flags encendidos los catalogos se escriben normalmente (control)", async () => {
    const { procesar, catalogosService } = crearSync({});

    await procesar("CREATE_COSA_TRAE", { nombre: "Gata" });

    expect(catalogosService.createCosaTrae).toHaveBeenCalled();
  });

  it("los catalogos de vehiculo (basicos de la OT) nunca se gatean", async () => {
    const { procesar, tallerParametros } = crearSync({ "ot.usa_cosas_trae": false, "ot.usa_danos": false });

    await procesar("CREATE_TIPO_VEHICULO", { nombre: "Sedan" });

    expect(tallerParametros.exigirHabilitado).not.toHaveBeenCalled();
  });
});
