import { BadRequestException } from '@nestjs/common';
import { GastosService } from './gastos.service';

describe('GastosService - reglas F4', () => {
  const createService = (prismaOverrides: Record<string, any> = {}) => {
    const prisma = {
      $transaction: jest.fn(),
      ...prismaOverrides,
    };
    const contabilidadIntegracion = {
      integrarGasto: jest.fn().mockResolvedValue(undefined),
    };
    const gastosTesoreria = {
      integrarGasto: jest.fn().mockResolvedValue({}),
      revertirGasto: jest.fn().mockResolvedValue(undefined),
    };
    return new GastosService(
      prisma as any,
      contabilidadIntegracion as any,
      gastosTesoreria as any,
      { recalcular: jest.fn().mockResolvedValue(undefined) } as any,
    );
  };

  describe('normalizeDocumentoFiscal', () => {
    it('si no hay documento fiscal retorna deducible=false sin exigir campos', () => {
      const service = createService();
      const normalizeDocumentoFiscal = (service as any).normalizeDocumentoFiscal.bind(service);

      const result = normalizeDocumentoFiscal({});

      expect(result).toEqual({
        timbrado: null,
        establecimiento: null,
        punto_expedicion: null,
        numero_factura: null,
        deducible: false,
      });
    });

    it('normaliza con zero-pad y marca deducible=true cuando documento está completo', () => {
      const service = createService();
      const normalizeDocumentoFiscal = (service as any).normalizeDocumentoFiscal.bind(service);

      const result = normalizeDocumentoFiscal({
        timbrado: '123',
        establecimiento: '1',
        punto_expedicion: '2',
        numero_factura: '45',
      });

      expect(result).toEqual({
        timbrado: '00000123',
        establecimiento: '001',
        punto_expedicion: '002',
        numero_factura: '0000045',
        deducible: true,
      });
    });

    it('bloquea gasto deducible con documento incompleto', () => {
      const service = createService();
      const normalizeDocumentoFiscal = (service as any).normalizeDocumentoFiscal.bind(service);

      expect(() =>
        normalizeDocumentoFiscal({
          timbrado: '12345678',
          establecimiento: '001',
          punto_expedicion: '001',
          numero_factura: '',
        }),
      ).toThrow(BadRequestException);
    });
  });

  describe('create', () => {
    it('bloquea alta cuando config exige requisición obligatoria y cabecera.requisicion_id no viene', async () => {
      const tx = {
        config_compras: {
          findUnique: jest.fn().mockResolvedValue({
            empresa_id: 'emp-1',
            modo_flujo_compra: 'requisicion_obligatoria',
          }),
          create: jest.fn(),
        },
      };
      const prisma = {
        $transaction: jest.fn(async (cb: any) => cb(tx)),
      };
      const contabilidadIntegracion = {
        integrarGasto: jest.fn().mockResolvedValue(undefined),
      };
      const gastosTesoreria = {
        integrarGasto: jest.fn().mockResolvedValue({}),
        revertirGasto: jest.fn().mockResolvedValue(undefined),
      };
      const service = new GastosService(
      prisma as any,
      contabilidadIntegracion as any,
      gastosTesoreria as any,
      { recalcular: jest.fn().mockResolvedValue(undefined) } as any,
    );

      await expect(
        service.create(
          {
            cabecera: {
              proveedor_id: 'prov-1',
              forma_pago: 'CONTADO',
            },
            items: [
              {
                descripcion: 'Servicio de prueba',
                cantidad: 1,
                precio_unitario: 1000,
                porcentaje_iva: 10,
              },
            ],
          } as any,
          'emp-1',
          'u-1',
        ),
      ).rejects.toThrow(BadRequestException);
    });

    it('bloquea payload si item no tiene producto_id ni descripción', async () => {
      const service = createService();

      await expect(
        service.create(
          {
            cabecera: {
              proveedor_id: 'prov-1',
            },
            items: [
              {
                cantidad: 1,
                precio_unitario: 1000,
                porcentaje_iva: 10,
              },
            ],
          } as any,
          'emp-1',
        ),
      ).rejects.toThrow(BadRequestException);
    });
  });
});
