import { alcanceSucursalUsuario, exigirAccesoElevado } from './alcance-sucursal';
import { correrConRubro } from './rubro-context';

/**
 * El rubro elegido en el selector (header x-rubro-id) recorta el alcance por
 * sucursal, también para usuarios sin restricción. Ver docs/plan-rubros-multi-sucursal.md.
 */
describe('alcanceSucursalUsuario con rubro del request', () => {
  const SUC_TALLER = { id: 'suc-taller', punto_establecimiento: '001' };
  const SUC_AGOGO = { id: 'suc-agogo', punto_establecimiento: '003' };
  const RUBRO_TALLER = 'rubro-taller';
  const RUBRO_REGALOS = 'rubro-regalos';

  const crearPrisma = ({ superadmin = false, asignadas = [] as Array<{ suc: typeof SUC_TALLER; rubro: string }> } = {}) => ({
    usuario: { findUnique: jest.fn().mockResolvedValue({ is_superadmin: superadmin }) },
    rubros: { findFirst: jest.fn(({ where }) => Promise.resolve([RUBRO_TALLER, RUBRO_REGALOS].includes(where.id) ? { id: where.id } : null)) },
    empresas: { findUnique: jest.fn().mockResolvedValue({ type: 'subsidiary' }) },
    asignacion_sucursal_caja_usuario: {
      findMany: jest.fn(({ select }) =>
        Promise.resolve(
          select?.sucursal
            ? asignadas.map((a) => ({ sucursal: { sucursal_rubros: [{ rubro_id: a.rubro }] } }))
            : asignadas.map((a) => ({ sucursal_id: a.suc.id })),
        ),
      ),
    },
    empresas_sucursales: {
      findMany: jest.fn(({ where }) => {
        const todas = [SUC_TALLER, SUC_AGOGO];
        const rubro = where?.sucursal_rubros?.some?.rubro_id;
        const porRubro = rubro ? todas.filter((s) => (s === SUC_TALLER ? RUBRO_TALLER : RUBRO_REGALOS) === rubro) : todas;
        const ids: string[] | undefined = where?.id?.in;
        return Promise.resolve(ids ? porRubro.filter((s) => ids.includes(s.id)) : porRubro);
      }),
    },
    depositos: {
      findMany: jest.fn(({ where }) =>
        Promise.resolve((where.sucursal_id.in as string[]).map((id) => ({ id: `dep-${id}` }))),
      ),
    },
  });

  it('sin rubro en el request: como siempre (superadmin sin restricción)', async () => {
    const prisma: any = crearPrisma({ superadmin: true });
    expect(await alcanceSucursalUsuario(prisma, 'usr', 'emp')).toBeNull();
  });

  it('superadmin con rubro Taller: sólo las sucursales de ese rubro', async () => {
    const prisma: any = crearPrisma({ superadmin: true });
    const alcance = await correrConRubro(RUBRO_TALLER, () => alcanceSucursalUsuario(prisma, 'usr', 'emp'));
    expect(alcance).toEqual({ sucursalIds: ['suc-taller'], puntosEstablecimiento: ['001'], depositoIds: ['dep-suc-taller'] });
  });

  it('usuario restringido a Taller que elige su rubro: intersección = sus sucursales', async () => {
    const prisma: any = crearPrisma({ asignadas: [{ suc: SUC_TALLER, rubro: RUBRO_TALLER }] });
    const alcance = await correrConRubro(RUBRO_TALLER, () => alcanceSucursalUsuario(prisma, 'usr', 'emp'));
    expect(alcance?.sucursalIds).toEqual(['suc-taller']);
  });

  it('usuario restringido a Taller que elige Regalería: no ve nada', async () => {
    const prisma: any = crearPrisma({ asignadas: [{ suc: SUC_TALLER, rubro: RUBRO_TALLER }] });
    const alcance = await correrConRubro(RUBRO_REGALOS, () => alcanceSucursalUsuario(prisma, 'usr', 'emp'));
    expect(alcance).toEqual({ sucursalIds: [], puntosEstablecimiento: [], depositoIds: [] });
  });

  it('un rubro que no es de la empresa (elección guardada de otra empresa) se ignora', async () => {
    const prisma: any = crearPrisma({ superadmin: true });
    prisma.rubros = { findFirst: jest.fn().mockResolvedValue(null) };
    expect(await correrConRubro('rubro-de-otra-empresa', () => alcanceSucursalUsuario(prisma, 'usr', 'emp'))).toBeNull();
    expect(prisma.empresas_sucursales.findMany).not.toHaveBeenCalled();
  });

  it('el Libro IVA (exigirAccesoElevado) ignora el rubro: el superadmin sigue viendo el libro completo', async () => {
    const prisma: any = crearPrisma({ superadmin: true });
    await expect(
      correrConRubro(RUBRO_TALLER, () => exigirAccesoElevado(prisma, 'usr', 'emp', 'Libro IVA')),
    ).resolves.toBeUndefined();
  });
});
