import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';

import { CreateVehicleDto } from './create-vehicle.dto';

const base = {
  vehicleType: 'TRUCK',
  manufacturer: 'IVECO',
  model: 'HYT',
  year: 2020,
  fuelType: 'DIESEL',
  capacity: 0,
  status: 'ACTIVE',
};

const errorsFor = (over: Record<string, unknown>) =>
  validate(plainToInstance(CreateVehicleDto, { ...base, ...over }));

const plateErrors = (
  errors: Awaited<ReturnType<typeof errorsFor>>,
  property: string,
) => errors.find((e) => e.property === property && e.constraints?.matches);

describe('CreateVehicleDto — plate format', () => {
  it('accepts a plate like ET-9875', async () => {
    expect(plateErrors(await errorsFor({ plateNumber: 'ET-9875' }), 'plateNumber')).toBeUndefined();
  });

  it('accepts a plate like AA-8642', async () => {
    expect(plateErrors(await errorsFor({ plateNumber: 'AA-8642' }), 'plateNumber')).toBeUndefined();
  });

  it('upper-cases a lower-case plate before validating', async () => {
    const dto = plainToInstance(CreateVehicleDto, { ...base, plateNumber: 'et-9875' });
    expect(dto.plateNumber).toBe('ET-9875');
    expect(plateErrors(await validate(dto), 'plateNumber')).toBeUndefined();
  });

  it('rejects a free-text plate like assadasd', async () => {
    expect(plateErrors(await errorsFor({ plateNumber: 'assadasd' }), 'plateNumber')).toBeDefined();
  });

  it('rejects a plate with no letters or no digits', async () => {
    expect(plateErrors(await errorsFor({ plateNumber: '1234' }), 'plateNumber')).toBeDefined();
    expect(plateErrors(await errorsFor({ plateNumber: 'ABCD' }), 'plateNumber')).toBeDefined();
  });

  it('rejects a bad trailer plate but allows a valid one', async () => {
    expect(
      plateErrors(await errorsFor({ plateNumber: 'ET-1', trailerPlateNo: 'asdasdasda' }), 'trailerPlateNo'),
    ).toBeDefined();
    expect(
      plateErrors(await errorsFor({ plateNumber: 'ET-1', trailerPlateNo: 'AA-8642' }), 'trailerPlateNo'),
    ).toBeUndefined();
  });

  it('allows an empty trailer plate (optional)', async () => {
    const errors = await errorsFor({ plateNumber: 'ET-1', trailerPlateNo: '' });
    expect(plateErrors(errors, 'trailerPlateNo')).toBeUndefined();
  });
});
