import { BookingPricingService } from './booking-pricing.service';
import type { Booking } from './entities/booking.entity';
import type { Rate } from '../rule-engine/entities/rate.entity';

const MOCK_CBE_RATE = 130;

describe('BookingPricingService — domestic corridor', () => {
  const intercityBulkUsd: Rate = {
    id: 'rate-intercity-bulk-usd',
    rateType: 'INTERCITY_BULK',
    currency: 'USD',
    rateValue: 35,
    rateUnit: 'PER_TON',
    status: 'LIVE',
    containerTypeId: null,
  } as Rate;

  const intercityContainerUsd: Rate = {
    id: 'rate-intercity-container-usd',
    rateType: 'INTERCITY_CONTAINER',
    currency: 'USD',
    rateValue: 400,
    rateUnit: 'PER_CONTAINER',
    status: 'LIVE',
    containerTypeId: null,
  } as Rate;

  let service: BookingPricingService;
  let bookingsRepository: { calculateWagonCount: jest.Mock };
  let ratesService: { findLiveRates: jest.Mock };
  let exchangeService: { getRate: jest.Mock };

  beforeEach(() => {
    bookingsRepository = { calculateWagonCount: jest.fn().mockResolvedValue(2) };
    ratesService = {
      findLiveRates: jest.fn().mockResolvedValue([intercityBulkUsd, intercityContainerUsd]),
    };
    exchangeService = {
      getRate: jest.fn().mockResolvedValue(MOCK_CBE_RATE),
    };

    service = new BookingPricingService(
      bookingsRepository as never,
      {} as never,
      {} as never,
      ratesService as never,
      exchangeService as never,
    );
  });

  it('prices domestic bulk in ETB using INTERCITY_BULK USD rate × CBE exchange rate', async () => {
    const booking = {
      id: 'b-1',
      freightType: 'BULK',
      tradeDirection: 'DOMESTIC',
      paymentCurrency: 'ETB',
      cargoTotalWeightVgm: 120,
      bookingContainers: [],
    } as unknown as Booking;

    const result = await (
      service as unknown as {
        computeBaseRailLinesWithRates: (
          b: Booking,
          input: { containers: [] },
        ) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
      }
    ).computeBaseRailLinesWithRates(booking, { containers: [] });

    expect(result.lineItems).toHaveLength(1);
    expect(result.lineItems[0].code).toBe('INTERCITY_BULK');
    expect(result.lineItems[0].currency).toBe('ETB');
    expect(result.lineItems[0].amount).toBe(Math.round(35 * 120 * MOCK_CBE_RATE));
  });

  it('prices domestic bulk in USD using INTERCITY_BULK USD rate directly', async () => {
    const booking = {
      id: 'b-1-usd',
      freightType: 'BULK',
      tradeDirection: 'DOMESTIC',
      paymentCurrency: 'USD',
      cargoTotalWeightVgm: 120,
      bookingContainers: [],
    } as unknown as Booking;

    const result = await (
      service as unknown as {
        computeBaseRailLinesWithRates: (
          b: Booking,
          input: { containers: [] },
        ) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
      }
    ).computeBaseRailLinesWithRates(booking, { containers: [] });

    expect(result.lineItems).toHaveLength(1);
    expect(result.lineItems[0].code).toBe('INTERCITY_BULK');
    expect(result.lineItems[0].currency).toBe('USD');
    expect(result.lineItems[0].amount).toBe(35 * 120);
  });

  it('prices domestic container in ETB using INTERCITY_CONTAINER USD fallback × CBE rate', async () => {
    const booking = {
      id: 'b-2',
      freightType: 'CONTAINER',
      tradeDirection: 'DOMESTIC',
      paymentCurrency: 'ETB',
      cargoTotalWeightVgm: 50,
      bookingContainers: [],
    } as unknown as Booking;

    const result = await (
      service as unknown as {
        computeBaseRailLinesWithRates: (
          b: Booking,
          input: {
            containers: Array<{ containerTypeId: string; quantity: number }>;
          },
        ) => Promise<{ lineItems: Array<{ amount: number; code: string; currency: string }> }>;
      }
    ).computeBaseRailLinesWithRates(booking, {
      containers: [{ containerTypeId: 'ct-20', quantity: 3 }],
    });

    expect(result.lineItems.some((l) => l.code === 'INTERCITY_CONTAINER')).toBe(true);
    const line = result.lineItems.find((l) => l.code === 'INTERCITY_CONTAINER')!;
    expect(line.currency).toBe('ETB');
  });
});
