import { NotFoundException } from '@nestjs/common';
import { TesTransferenciasService } from './tes-transferencias.service';

/**
 * Las transferencias no tienen cabecera propia y no entran en Conciliación →
 * "Sin asiento": si quedan sin asiento por falta de mapeo (spec 2026-10-13), se
 * regeneran desde Tesorería.
 */
describe('reintentar la contabilización de una transferencia', () => {
  const movimientos = [
    { id: 'mo', origen_tipo: 'TRANSFERENCIA_ORIGEN', estado: 'CONFIRMADO' },
    { id: 'md', origen_tipo: 'TRANSFERENCIA_DESTINO', estado: 'CONFIRMADO' },
  ];
  const crear = (opciones: { movs?: any[]; doc?: any; constancia?: any } = {}) => {
    const prisma: any = {
      tes_movimientos: { findMany: jest.fn().mockResolvedValue(opciones.movs ?? movimientos) },
      cont_documentos: { findFirst: jest.fn().mockResolvedValue(opciones.doc ?? null) },
      audit_logs: { findFirst: jest.fn().mockResolvedValue(opciones.constancia ?? null) },
    };
    const contabilidad: any = { integrarTransferenciaTes: jest.fn().mockResolvedValue(undefined) };
    const service = new TesTransferenciasService(prisma, contabilidad, {} as any);
    return { service, prisma, contabilidad };
  };

  it('arma la llamada con los dos movimientos y avisa que quedó contabilizada', async () => {
    const { service, prisma, contabilidad } = crear({ doc: { id: 'doc-1' } });

    await expect(service.reintentarContabilizacion('emp-1', 'tr-1')).resolves.toEqual({ contabilizada: true, conceptosFaltantes: [] });

    expect(prisma.tes_movimientos.findMany.mock.calls[0][0].where).toEqual({ transferencia_id: 'tr-1', empresa_id: 'emp-1' });
    expect(contabilidad.integrarTransferenciaTes).toHaveBeenCalledWith('mo', 'md', 'tr-1', 'emp-1');
  });

  it('si sigue pendiente devuelve los conceptos de la última constancia de falta de mapeo', async () => {
    const { service, prisma } = crear({ constancia: { new_value: { origen_tipo: 'tes_transferencias', conceptos: ['DIFERENCIA_CAMBIO_GANADA'] } } });

    await expect(service.reintentarContabilizacion('emp-1', 'tr-1')).resolves.toEqual({
      contabilizada: false,
      conceptosFaltantes: ['DIFERENCIA_CAMBIO_GANADA'],
    });
    expect(prisma.audit_logs.findFirst.mock.calls[0][0].where).toEqual({
      empresa_id: 'emp-1', action: 'CONT_FALTA_MAPEO', entity_type: 'tes_transferencias', entity_id: 'tr-1',
    });
  });

  it('una transferencia de otra empresa no se encuentra', async () => {
    const { service, contabilidad } = crear({ movs: [] });

    await expect(service.reintentarContabilizacion('emp-2', 'tr-1')).rejects.toBeInstanceOf(NotFoundException);
    expect(contabilidad.integrarTransferenciaTes).not.toHaveBeenCalled();
  });

  it('una transferencia anulada no se contabiliza', async () => {
    const { service, contabilidad } = crear({ movs: movimientos.map((m) => ({ ...m, estado: 'ANULADO' })) });

    await expect(service.reintentarContabilizacion('emp-1', 'tr-1')).rejects.toThrow(/anulada/);
    expect(contabilidad.integrarTransferenciaTes).not.toHaveBeenCalled();
  });
});
