import { DataSource, Repository } from 'typeorm';

import { Booking } from './entities/booking.entity';
import { BookingsRepository } from './bookings.repository';

function mockQueryBuilder() {
  const qb = {
    leftJoinAndSelect: jest.fn().mockReturnThis(),
    leftJoin: jest.fn().mockReturnThis(),
    where: jest.fn().mockReturnThis(),
    andWhere: jest.fn().mockReturnThis(),
    orderBy: jest.fn().mockReturnThis(),
    addOrderBy: jest.fn().mockReturnThis(),
    skip: jest.fn().mockReturnThis(),
    take: jest.fn().mockReturnThis(),
    getMany: jest.fn(),
    getManyAndCount: jest.fn().mockResolvedValue([[], 0]),
  };
  return qb;
}

describe('BookingsRepository', () => {
  let repository: jest.Mocked<Repository<Booking>>;
  let dataSource: { getRepository: jest.Mock };
  let bookingsRepository: BookingsRepository;

  beforeEach(() => {
    repository = {
      createQueryBuilder: jest.fn(),
    } as unknown as jest.Mocked<Repository<Booking>>;
    dataSource = { getRepository: jest.fn() };
    bookingsRepository = new BookingsRepository(repository, dataSource as unknown as DataSource);
  });

  it('findEligibleForScheduling does not filter by schedule date', async () => {
    const qb = mockQueryBuilder();
    const bookings = [
      { id: 'b1', scheduledDate: new Date('2026-06-20T08:00:00.000Z') },
      { id: 'b2', scheduledDate: new Date('2026-06-21T14:00:00.000Z') },
    ];
    qb.getMany.mockResolvedValue(bookings);
    repository.createQueryBuilder.mockReturnValue(qb as never);

    const result = await bookingsRepository.findEligibleForScheduling({
      originStationId: 'yard-origin',
      destinationStationId: 'yard-destination',
      freightType: 'CONTAINER',
    });

    expect(result).toHaveLength(2);
    const dateFilters = qb.andWhere.mock.calls.filter(([clause]) =>
      String(clause).includes('scheduled_date'),
    );
    expect(dateFilters).toHaveLength(0);
  });

  it('applyListFilters excludes assigned bookings when assignedToSchedule is false', async () => {
    const qb = mockQueryBuilder();
    repository.createQueryBuilder.mockReturnValue(qb as never);
    dataSource.getRepository.mockReturnValue({ find: jest.fn().mockResolvedValue([]) });

    await bookingsRepository.findAllPaginated({
      page: 1,
      pageSize: 10,
      assignedToSchedule: 'false',
    });

    expect(qb.andWhere).toHaveBeenCalledWith(expect.stringContaining('NOT EXISTS'));
  });
});
