import { SeguridadSeedOrchestrator } from './seed-orchestrator.service';
import { PERFILES_SISTEMA_SEED } from './seguridad.seed-data';

/**
 * Verifica la sincronización de perfiles del sistema: backfill de perfiles
 * existentes + creación de los perfiles `autoProvision` (los de ecommerce) sólo
 * en empresas que ya usan perfiles del sistema, y el atajo por empresa.
 */
describe('SeguridadSeedOrchestrator perfiles de ecommerce', () => {
  const MOD_ECOMMERCE = 'mod-ecommerce';

  // Privilegios de sistema simulados: pedidos + tienda + novedades + pagos + 1 ajeno.
  const privilegios = [
    { id: 'p-ver', codigo: 'EC_PED_PEDIDO_VER', accion: 'VER', submodulos: { codigo: 'ECOMMERCE_PEDIDOS', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-proc', codigo: 'EC_PED_PEDIDO_PROCESAR', accion: 'PROCESAR', submodulos: { codigo: 'ECOMMERCE_PEDIDOS', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-desp', codigo: 'EC_PED_DESPACHO', accion: 'DESPACHAR', submodulos: { codigo: 'ECOMMERCE_PEDIDOS', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-mostr', codigo: 'EC_PED_MOSTRADOR', accion: 'RETIRAR', submodulos: { codigo: 'ECOMMERCE_PEDIDOS', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-cfg', codigo: 'EC_CFG_TIENDA_EDITAR', accion: 'EDITAR', submodulos: { codigo: 'ECOMMERCE_TIENDA', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-nov', codigo: 'EC_NOV_NOVEDAD_EDITAR', accion: 'EDITAR', submodulos: { codigo: 'ECOMMERCE_NOVEDADES', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-pagv', codigo: 'EC_PAG_PAGO_VER', accion: 'VER', submodulos: { codigo: 'ECOMMERCE_PAGOS', modulo_id: MOD_ECOMMERCE } },
    { id: 'p-otro', codigo: 'OTRO_VER', accion: 'VER', submodulos: { codigo: 'OTRO', modulo_id: 'mod-otro' } },
  ];
  const modulos = [
    { id: MOD_ECOMMERCE, codigo: 'ECOMMERCE' },
    { id: 'mod-otro', codigo: 'OTRO' },
  ];

  const TODOS = ['p-ver', 'p-proc', 'p-desp', 'p-mostr', 'p-cfg', 'p-nov', 'p-pagv', 'p-otro'];
  const NOMBRES_ECOMMERCE = ['Despacho Ecommerce', 'Gestor de Tienda', 'Mostrador Ecommerce', 'Operador Ecommerce'];

  // Forma cruda que devuelve loadSystemPrivileges() vía $queryRaw (INNER JOIN).
  const privilegiosRaw = privilegios.map((p) => ({
    id: p.id,
    codigo: p.codigo,
    accion: p.accion,
    sub_codigo: p.submodulos.codigo,
    modulo_id: p.submodulos.modulo_id,
  }));

  function buildPrismaMock(perfilesSistema: any[]) {
    const created: any[] = [];
    const asignaciones: any[] = [];
    return {
      created,
      asignaciones,
      prisma: {
        $queryRaw: jest.fn().mockResolvedValue(privilegiosRaw),
        modulos: { findMany: jest.fn().mockResolvedValue(modulos) },
        perfiles: {
          findMany: jest.fn().mockResolvedValue(perfilesSistema),
          create: jest.fn().mockImplementation(({ data }: any) => {
            const row = { id: `perfil-${created.length + 1}`, ...data };
            created.push(row);
            return Promise.resolve(row);
          }),
        },
        perfiles_privilegios: {
          createMany: jest.fn().mockImplementation(({ data }: any) => {
            asignaciones.push(...data);
            return Promise.resolve({ count: data.length });
          }),
        },
      } as any,
    };
  }

  const privsDe = (asignaciones: any[], perfilId: string) =>
    asignaciones.filter((a) => a.perfil_id === perfilId).map((a) => a.privilegio_id).sort();

  it('los perfiles del seed respetan los límites de columna (perfil<=50, desc<=100)', () => {
    for (const p of PERFILES_SISTEMA_SEED) {
      expect(p.perfil.length).toBeLessThanOrEqual(50);
      expect(p.desc.length).toBeLessThanOrEqual(100);
    }
  });

  it('crea los perfiles de ecommerce y backfillea el Administrador en empresas opt-in', async () => {
    const perfilesSistema = [
      { id: 'adm-e1', empresa_id: 'E1', perfil: 'Administrador', perfiles_privilegios: [] },
    ];
    const { prisma, created, asignaciones } = buildPrismaMock(perfilesSistema);
    const orch = new SeguridadSeedOrchestrator(prisma);

    const res = await orch.sincronizarPerfilesSistema();

    // Administrador (selector '*') recibe TODOS los privilegios por backfill.
    expect(privsDe(asignaciones, 'adm-e1')).toEqual([...TODOS].sort());

    // Se crean los 4 perfiles autoProvision de ecommerce para E1.
    expect(created.map((c) => c.perfil).sort()).toEqual(NOMBRES_ECOMMERCE);
    expect(res.perfiles_creados).toBe(4);
    expect(res.empresas).toBe(1);

    // "Despacho Ecommerce": ver + procesar + despacho, NO mostrador.
    const despacho = created.find((c) => c.perfil === 'Despacho Ecommerce');
    expect(privsDe(asignaciones, despacho.id)).toEqual(['p-desp', 'p-proc', 'p-ver']);
  });

  it('provisionarPerfilesEcommerce crea los 4 roles de la tienda con sus permisos', async () => {
    const { prisma, created, asignaciones } = buildPrismaMock([]);
    const orch = new SeguridadSeedOrchestrator(prisma);

    const res = await orch.provisionarPerfilesEcommerce('E1');

    expect(res.creados).toBe(4);
    expect(created.map((c) => c.perfil).sort()).toEqual(NOMBRES_ECOMMERCE);

    // Gestor de Tienda: config + novedades + ver pedidos + ver pagos. NO opera.
    const gestor = created.find((c) => c.perfil === 'Gestor de Tienda');
    expect(privsDe(asignaciones, gestor.id)).toEqual(['p-cfg', 'p-nov', 'p-pagv', 'p-ver']);

    // Operador Ecommerce: todo ECOMMERCE_PEDIDOS.* + ver pagos.
    const operador = created.find((c) => c.perfil === 'Operador Ecommerce');
    expect(privsDe(asignaciones, operador.id)).toEqual(['p-desp', 'p-mostr', 'p-pagv', 'p-proc', 'p-ver']);
  });

  it('provisionarPerfilesEcommerce es idempotente si ya están los 4', async () => {
    const yaCreados = [
      { id: 'ge', empresa_id: 'E1', perfil: 'Gestor de Tienda', perfiles_privilegios: [{ privilegio_id: 'p-cfg' }, { privilegio_id: 'p-nov' }, { privilegio_id: 'p-pagv' }, { privilegio_id: 'p-ver' }] },
      { id: 'op', empresa_id: 'E1', perfil: 'Operador Ecommerce', perfiles_privilegios: [{ privilegio_id: 'p-ver' }, { privilegio_id: 'p-proc' }, { privilegio_id: 'p-desp' }, { privilegio_id: 'p-mostr' }, { privilegio_id: 'p-pagv' }] },
      { id: 'de', empresa_id: 'E1', perfil: 'Despacho Ecommerce', perfiles_privilegios: [{ privilegio_id: 'p-ver' }, { privilegio_id: 'p-proc' }, { privilegio_id: 'p-desp' }] },
      { id: 'mo', empresa_id: 'E1', perfil: 'Mostrador Ecommerce', perfiles_privilegios: [{ privilegio_id: 'p-ver' }, { privilegio_id: 'p-proc' }, { privilegio_id: 'p-mostr' }] },
    ];
    const { prisma, created, asignaciones } = buildPrismaMock(yaCreados);
    const orch = new SeguridadSeedOrchestrator(prisma);

    const res = await orch.provisionarPerfilesEcommerce('E1');

    expect(res.creados).toBe(0);
    expect(res.privilegios_agregados).toBe(0);
    expect(created).toHaveLength(0);
    expect(asignaciones).toHaveLength(0);
  });
});
