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

import { VehiclesService } from './vehicles.service';

// One driver ⇒ one truck: create/update must refuse a driver already assigned
// to another (non-deleted) vehicle until they are detached.
describe('VehiclesService driver assignment guard', () => {
  const otherTruck = { id: 'v2', plateNumber: '3-11111', assignedDriverId: 'd1' };

  const makeService = (findOne: jest.Mock) =>
    new VehiclesService(
      { findOne, create: jest.fn((x) => x), save: jest.fn(async (x) => x) } as any,
      { record: jest.fn() } as any,
      { findById: jest.fn(async () => ({ code: 'TRUCK', name: 'Truck', hasTrailer: true })) } as any,
    );

  it('rejects create when the driver is on another truck', async () => {
    // First findOne = plate uniqueness (null), second = driver holder.
    const findOne = jest.fn().mockResolvedValueOnce(null).mockResolvedValueOnce(otherTruck);
    const svc = makeService(findOne);
    await expect(
      svc.create({ plateNumber: '3-22222', truckTypeId: 'tt1', assignedDriverId: 'd1' } as any),
    ).rejects.toThrow(ConflictException);
  });

  it('rejects update when reassigning a driver still attached elsewhere', async () => {
    const findOne = jest
      .fn()
      .mockResolvedValueOnce({ id: 'v1', plateNumber: '3-22222', assignedDriverId: null }) // findById
      .mockResolvedValueOnce(otherTruck); // driver holder
    const svc = makeService(findOne);
    await expect(svc.update('v1', { assignedDriverId: 'd1' } as any)).rejects.toThrow(
      ConflictException,
    );
  });

  it('allows update that keeps the same driver on the same truck', async () => {
    const findOne = jest
      .fn()
      .mockResolvedValueOnce({ id: 'v1', plateNumber: '3-22222', assignedDriverId: 'd1' });
    const svc = makeService(findOne);
    await expect(svc.update('v1', { assignedDriverId: 'd1' } as any)).resolves.toBeDefined();
    expect(findOne).toHaveBeenCalledTimes(1); // guard skipped — no holder lookup
  });
});
