import { BadRequestException, ForbiddenException } from '@nestjs/common';
import { CotizacionesInmService } from './cotizaciones.service';

describe('CotizacionesInmService.resolverOpcion', () => {
  const tramos = [
    {
      orden: 1,
      tipo: 'SENA',
      base: 'PORCENTAJE',
      valor: 10,
      cantidad: 1,
      periodicidad_meses: 1,
      inicio_meses: 0,
      hito_id: null,
      descripcion: null,
    },
    {
      orden: 2,
      tipo: 'CUOTA',
      base: 'SALDO',
      valor: 0,
      cantidad: 12,
      periodicidad_meses: 1,
      inicio_meses: 1,
      hito_id: null,
      descripcion: null,
    },
  ];
  const crear = (opts: { superadmin?: boolean; privilegios?: string[] } = {}) => {
    const prisma: any = {
      inm_planes_pago: { findFirst: jest.fn().mockResolvedValue({ nombre: 'Pozo', inm_plan_pago_tramos: tramos }) },
      usuario: {
        findUnique: jest.fn().mockResolvedValue({
          is_superadmin: !!opts.superadmin,
          usuario_perfiles: [
            {
              perfiles: {
                perfiles_privilegios: (opts.privilegios ?? []).map((codigo) => ({ privilegios: { codigo } })),
              },
            },
          ],
        }),
      },
    };
    return new CotizacionesInmService(prisma, { log: jest.fn() } as any, {} as any, {} as any);
  };
  const unidad = { proyecto_id: 'p1', precio_lista: 100_000_000, moneda_codigo: 'PYG' };
  const reglas = { pctDescuentoMax: 5, pctSenaMin: 10 };

  it('dentro del tope: precio con descuento y cronograma que cierra', async () => {
    const r = await crear().resolverOpcion(
      'e1',
      unidad,
      { plan_id: 'pl', descuento_pct: 5 },
      'u1',
      reglas,
      '2026-10-10',
    );
    expect(r.precio_final).toBe(95_000_000);
    expect(r.cronograma.reduce((a, c) => a + c.monto, 0)).toBe(95_000_000);
    expect(r.descuento_autorizado_por).toBeNull();
  });

  it('sobre el tope sin el privilegio: 403, y con el privilegio queda registrado quién autorizó', async () => {
    await expect(
      crear().resolverOpcion('e1', unidad, { plan_id: 'pl', descuento_pct: 8 }, 'u1', reglas),
    ).rejects.toBeInstanceOf(ForbiddenException);
    const r = await crear({ privilegios: ['INM_COT_DESCUENTO_AUTORIZAR'] }).resolverOpcion(
      'e1',
      unidad,
      { plan_id: 'pl', descuento_pct: 8 },
      'sup',
      reglas,
    );
    expect(r.descuento_autorizado_por).toBe('sup');
  });

  it('seña por debajo del mínimo: se rechaza al cotizar, no recién al reservar', async () => {
    await expect(
      crear().resolverOpcion('e1', unidad, { plan_id: 'pl' }, 'u1', { pctDescuentoMax: 5, pctSenaMin: 15 }),
    ).rejects.toThrow(/menor al mínimo/);
    await expect(
      crear().resolverOpcion(
        'e1',
        unidad,
        { tramos: [{ tipo: 'CUOTA', base: 'SALDO', valor: 0 } as any] },
        'u1',
        reglas,
      ),
    ).rejects.toBeInstanceOf(BadRequestException);
  });
});
