import { TesChequeService } from './tes-cheques.service';

/**
 * El alta de cheques no validaba duplicados: en DOBA el mismo cheque quedó
 * cargado tres veces y el banco mostraba tres ingresos por la misma plata.
 *
 * No se bloquea duro: dos bancos distintos pueden repetir número, y a veces el
 * usuario sabe lo que hace. Se avisa y se exige confirmación explícita.
 */
describe('TesChequeService.create — cheque duplicado', () => {
  const dto: any = {
    tipo: 'RECIBIDO',
    numero_cheque: '5792344',
    banco_emisor: 'Banco Familiar S.A.E.C.A.',
    monto: 4_040_709,
    fecha_emision: '2026-05-08',
  };

  const crear = (existente: any = null) => {
    const prisma: any = {
      tes_cheques: {
        findFirst: jest.fn().mockResolvedValue(existente),
        create: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'chq-nuevo', ...data })),
      },
      tes_cuentas: { findFirst: jest.fn().mockResolvedValue({ id: 'cta-1', banco_id: null, numero_cuenta: '1' }) },
    };
    const service = Object.create(TesChequeService.prototype) as any;
    service.prisma = prisma;
    service.logger = { log: jest.fn(), warn: jest.fn(), error: jest.fn() };
    service.audit = { log: jest.fn().mockResolvedValue(undefined) };
    service.nombreBanco = jest.fn().mockResolvedValue('Banco Familiar S.A.E.C.A.');
    return { service, prisma };
  };

  it('sin otro cheque igual, lo crea sin molestar', async () => {
    const { service, prisma } = crear(null);

    await service.create(dto, 'emp-1', 'usr-1');

    expect(prisma.tes_cheques.create).toHaveBeenCalled();
  });

  it('avisa del duplicado con los datos del cheque que ya existe', async () => {
    const { service, prisma } = crear({
      id: 'chq-viejo',
      numero_cheque: '5792344',
      banco_emisor: 'Banco Familiar S.A.E.C.A.',
      monto: 4_040_709,
      estado: 'DEPOSITADO',
      fecha_emision: new Date('2026-05-08'),
    });

    await expect(service.create(dto, 'emp-1', 'usr-1')).rejects.toThrow(/ya existe|duplicad/i);
    expect(prisma.tes_cheques.create).not.toHaveBeenCalled();
    // El mensaje tiene que decir cuál es, para que el usuario decida.
    await expect(service.create(dto, 'emp-1', 'usr-1')).rejects.toThrow(/5792344/);
  });

  it('busca por empresa, tipo, número y banco, y sólo entre los cheques vivos', async () => {
    const { service, prisma } = crear(null);

    await service.create(dto, 'emp-1', 'usr-1');

    const where = prisma.tes_cheques.findFirst.mock.calls[0][0].where;
    expect(where.empresa_id).toBe('emp-1');
    expect(where.tipo).toBe('RECIBIDO');
    expect(where.numero_cheque).toBe('5792344');
    expect(where.estado.in).toEqual(expect.arrayContaining(['EN_CARTERA', 'DIFERIDO', 'DEPOSITADO']));
    // Un cheque rechazado o anulado no bloquea volver a cargarlo.
    expect(where.estado.in).not.toContain('RECHAZADO');
  });

  it('con confirmar_duplicado lo crea igual', async () => {
    const { service, prisma } = crear({ id: 'chq-viejo', numero_cheque: '5792344', estado: 'EN_CARTERA', monto: 1 });

    await service.create({ ...dto, confirmar_duplicado: true }, 'emp-1', 'usr-1');

    expect(prisma.tes_cheques.create).toHaveBeenCalled();
  });
});
