import { WarehouseFeeService } from './warehouse-fee.service';

/**
 * Double handling bills ONLY when warehouse staff answered Yes after
 * unloading. Undecided (null) or No must produce a zero charge even when a
 * matching DOUBLE_HANDLING_FEE rule exists.
 */
type Item = Parameters<WarehouseFeeService['previewForInventory']> extends unknown
  ? Record<string, unknown>
  : never;

const svc = Object.create(WarehouseFeeService.prototype) as {
  computeDoubleHandling: (
    rule: Record<string, unknown> | null,
    item: Item,
    now: Date,
    billingCurrency: string,
  ) => Promise<{ amount: number; billableUnits: number }>;
  normalizeCurrency: (c?: string | null) => string;
  convertAmount: (a: number, from: string, to: string) => Promise<number>;
  resolveBulkQuantity: (item: Item) => { quantity: number; unitLabel: string };
};
// No exchange service on a bare prototype — bill in the rule's own currency.
svc.normalizeCurrency = (c) => (c ? String(c).toUpperCase() : 'USD');
svc.convertAmount = async (a) => a;

const rule = { basis: 'PER_CONTAINER', ratePerDay: 100, currency: 'USD', id: 'r1', name: 'DH' };
const item = (doubleHandling: boolean | null) => ({
  tradeDirection: 'IMPORT',
  freightType: 'CONTAINER',
  inventoryQuantity: 2,
  bookingContainerCount: 3,
  inventoryWeight: 10,
  cargoUnitOfMeasure: 'PER_TON',
  doubleHandling,
}) as unknown as Item;

describe('double handling gate', () => {
  it('bills rate x containers when the booking is flagged Yes', async () => {
    const out = await svc.computeDoubleHandling(rule, item(true), new Date(), 'USD');
    expect(out.billableUnits).toBe(3);
    expect(out.amount).toBe(300);
  });

  it('charges nothing when the answer is No', async () => {
    const out = await svc.computeDoubleHandling(rule, item(false), new Date(), 'USD');
    expect(out.billableUnits).toBe(0);
    expect(out.amount).toBe(0);
  });

  it('charges nothing while the answer is undecided', async () => {
    const out = await svc.computeDoubleHandling(rule, item(null), new Date(), 'USD');
    expect(out.amount).toBe(0);
  });

  it('charges nothing for export even when flagged Yes', async () => {
    const exportItem = { ...(item(true) as Record<string, unknown>), tradeDirection: 'EXPORT' } as Item;
    const out = await svc.computeDoubleHandling(rule, exportItem, new Date(), 'USD');
    expect(out.amount).toBe(0);
  });
});
