import type { Repository } from 'typeorm';
import type { ClsService } from 'nestjs-cls';
import { BookingRepository } from './booking.repository';
import type { BookingEntity } from '../../../entities/booking.entity';

describe('BookingRepository.findPaymentGateInputs', () => {
  const TENANT = 'tenant-a';
  const BOOKING = '11111111-1111-4111-8111-111111111111';
  let query: jest.Mock;
  let repo: BookingRepository;

  beforeEach(() => {
    query = jest.fn();
    const orm = { manager: { query } } as unknown as Repository<BookingEntity>;
    const cls = { get: jest.fn().mockReturnValue(TENANT) } as unknown as ClsService;
    repo = new BookingRepository(orm, cls);
  });

  it('skips the database when there are no bookings', async () => {
    const result = await repo.findPaymentGateInputs([]);
    expect(result.size).toBe(0);
    expect(query).not.toHaveBeenCalled();
  });

  it('scopes every query to the CLS tenant (cross-tenant rows never load)', async () => {
    query.mockResolvedValue([]);
    await repo.findPaymentGateInputs([BOOKING]);
    expect(query).toHaveBeenCalledTimes(2);
    for (const [sql, params] of query.mock.calls) {
      expect(params[0]).toBe(TENANT);
      expect(sql).toContain('tenant_id = $1');
    }
  });

  it('returns nothing for a booking id owned by another tenant', async () => {
    query
      .mockResolvedValueOnce([])
      .mockResolvedValueOnce([{ booking_id: BOOKING, day: '2026-09-26', amount: '100.00' }]);
    const result = await repo.findPaymentGateInputs([BOOKING]);
    expect(result.has(BOOKING)).toBe(false);
  });

  it('maps paid + day-wise amounts per booking', async () => {
    query
      .mockResolvedValueOnce([
        { id: BOOKING, is_guaranteed: false, currency_code: 'AED', paid: '120.00' },
      ])
      .mockResolvedValueOnce([
        { booking_id: BOOKING, day: '2026-09-26', amount: '100.00' },
        { booking_id: BOOKING, day: '2026-09-27', amount: '200.00' },
      ]);
    const gate = (await repo.findPaymentGateInputs([BOOKING])).get(BOOKING);
    expect(gate?.paid).toBe(120);
    expect(gate?.currency_code).toBe('AED');
    expect(Array.from(gate?.day_amounts ?? [])).toEqual([
      ['2026-09-26', 100],
      ['2026-09-27', 200],
    ]);
  });
});
