import { BadRequestException } from '@nestjs/common';

import { WarehouseInventoryService } from './warehouse-inventory.service';

/**
 * Export cargo is received into the warehouse to wait for its train, and only a
 * paid booking may be received — otherwise storage and a GRN would start against
 * cargo the customer has not settled. Import is never blocked: it arrives OFF a
 * train and its receive is the unload.
 *
 * The guard touches only the DataSource, so the instance is built off the
 * prototype rather than stubbing all 20-odd collaborators.
 */
type Guard = (
  bookingId: string | null | undefined,
  direction: string | null,
) => Promise<void>;

function makeGuard(paymentStatus: string | null) {
  const query = jest.fn().mockResolvedValue([{ paymentStatus }]);
  const service = Object.create(WarehouseInventoryService.prototype) as Record<string, unknown>;
  service.dataSource = { query };
  const guard = (
    service as unknown as { assertExportBookingPaid: Guard }
  ).assertExportBookingPaid.bind(service);
  return { guard, query };
}

describe('receive() — export paid gate', () => {
  it('rejects an unpaid export booking', async () => {
    const { guard } = makeGuard('PENDING');

    await expect(guard('b-1', 'EXPORT')).rejects.toBeInstanceOf(BadRequestException);
  });

  it('allows a paid export booking', async () => {
    const { guard } = makeGuard('PAID');

    await expect(guard('b-1', 'EXPORT')).resolves.toBeUndefined();
  });

  it('never blocks import, paid or not', async () => {
    const { guard, query } = makeGuard('PENDING');

    await expect(guard('b-1', 'IMPORT')).resolves.toBeUndefined();
    expect(query).not.toHaveBeenCalled();
  });

  it('ignores a receive with no booking attached', async () => {
    const { guard, query } = makeGuard('PENDING');

    await expect(guard(null, 'EXPORT')).resolves.toBeUndefined();
    expect(query).not.toHaveBeenCalled();
  });
});
