import { BadRequestException } from '@nestjs/common';
import { TesChequeService } from './tes-cheques.service';

/**
 * Corregir el monto de un cheque (pedido de DOBA, cheque 682809).
 *
 * Sólo en cheques cargados a mano en Tesorería: el alta no genera movimiento
 * ni asiento y el monto recién se usa al depositar. Un cheque que salió de un
 * recibo tiene el monto imputado a facturas y contabilizado; ahí no.
 */
describe('TesChequeService.update - monto', () => {
  const chequeBase = {
    id: 'chq-1',
    empresa_id: 'emp-1',
    tipo: 'RECIBIDO',
    estado: 'EN_CARTERA',
    numero_cheque: '682809',
    monto: 2_408_582,
    origen_tipo: null as string | null,
    movimiento_id: null as string | null,
  };

  const crear = (cheque: Record<string, unknown> = {}, movimiento: { estado: string } | null = null) => {
    const prisma: any = {
      tes_cheques: {
        findFirst: jest.fn().mockResolvedValue({ ...chequeBase, ...cheque }),
        update: jest.fn().mockImplementation(({ data }) => Promise.resolve({ ...chequeBase, ...cheque, ...data })),
      },
      tes_movimientos: { findUnique: jest.fn().mockResolvedValue(movimiento) },
    };
    const service: any = Object.create(TesChequeService.prototype);
    service.prisma = prisma;
    service.audit = { log: jest.fn().mockResolvedValue(undefined) };
    return { service: service as TesChequeService, prisma, audit: service.audit };
  };

  it('cheque cargado a mano en cartera: corrige el monto y lo deja en auditoría', async () => {
    const { service, prisma, audit } = crear();

    await service.update('chq-1', { monto: 2_480_582, motivo: 'Se cargó mal el monto' }, 'emp-1', 'u-1');

    expect(prisma.tes_cheques.update).toHaveBeenCalledWith(
      expect.objectContaining({ data: expect.objectContaining({ monto: 2_480_582 }) }),
    );
    expect(audit.log).toHaveBeenCalledWith(
      expect.objectContaining({
        old_value: { monto: 2_408_582 },
        new_value: expect.objectContaining({ cambios: { monto: 2_480_582 } }),
      }),
    );
  });

  it('cheque que salió de un recibo: no deja cambiar el monto y dice por qué', async () => {
    const { service, prisma } = crear({ origen_tipo: 'recibos_multi', origen_id: 'rec-1' });

    await expect(service.update('chq-1', { monto: 1, motivo: 'x' }, 'emp-1', 'u-1')).rejects.toThrow(
      /recibo de cobro/,
    );
    expect(prisma.tes_cheques.update).not.toHaveBeenCalled();
  });

  it('con un movimiento vigente no deja; con uno anulado sí', async () => {
    const vigente = crear({ movimiento_id: 'mov-1' }, { estado: 'CONFIRMADO' });
    await expect(vigente.service.update('chq-1', { monto: 10, motivo: 'x' }, 'emp-1', 'u-1')).rejects.toBeInstanceOf(
      BadRequestException,
    );

    const anulado = crear({ movimiento_id: 'mov-1' }, { estado: 'ANULADO' });
    await anulado.service.update('chq-1', { monto: 10, motivo: 'x' }, 'emp-1', 'u-1');
    expect(anulado.prisma.tes_cheques.update).toHaveBeenCalled();
  });

  it('el mismo monto no cuenta como cambio', async () => {
    const { service } = crear({ origen_tipo: 'recibos_multi' });
    // Igual al actual: no debe frenar por el origen, sólo decir que no hay cambios.
    await expect(service.update('chq-1', { monto: 2_408_582, motivo: 'x' }, 'emp-1', 'u-1')).rejects.toThrow(
      'No hay cambios para guardar',
    );
  });
});
