import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import {
  IsArray,
  IsBoolean,
  IsInt,
  IsNumber,
  IsOptional,
  IsString,
  MaxLength,
  Min,
} from 'class-validator';

const toNumber = ({ value }: { value: unknown }) =>
  value === '' || value == null ? value : Number(value);

const toOptionalNumber = ({ value }: { value: unknown }) =>
  value === '' || value == null ? undefined : Number(value);

const toBoolean = ({ value }: { value: unknown }) => {
  if (typeof value === 'boolean') return value;
  if (value === 'true') return true;
  if (value === 'false') return false;
  return value;
};

const toStringArray = ({ value }: { value: unknown }) => {
  if (Array.isArray(value)) {
    return value.map((entry) => String(entry).trim()).filter(Boolean);
  }

  if (typeof value !== 'string') return [];

  return value
    .split(',')
    .map((entry) => entry.trim())
    .filter(Boolean);
};

export class CreateWagonTypeDto {
  @ApiProperty({ maxLength: 32, example: 'NW5' })
  @IsString()
  @MaxLength(32)
  code!: string;

  @ApiProperty({ maxLength: 100, example: 'Flat wagon container' })
  @IsString()
  @MaxLength(100)
  name!: string;

  @ApiProperty({ description: 'Maximum payload capacity in metric tons', example: 70 })
  @Transform(toNumber)
  @IsNumber()
  @Min(0.001)
  capacityTons!: number;

  @ApiProperty({ description: 'Wagon length in meters', example: 14 })
  @Transform(toNumber)
  @IsNumber()
  @Min(0.001)
  lengthMeters!: number;

  @ApiPropertyOptional({ description: 'Maximum wagons of this type per train', example: 53 })
  @IsOptional()
  @Transform(toOptionalNumber)
  @IsInt()
  @Min(1)
  maxWagonsPerTrain?: number;

  @ApiPropertyOptional({
    description: 'Supported load types, e.g. CONTAINER,BULK',
    type: [String],
    default: [],
  })
  @IsOptional()
  @Transform(toStringArray)
  @IsArray()
  @IsString({ each: true })
  supportedLoadTypes?: string[];

  @ApiPropertyOptional({ default: true })
  @IsOptional()
  @Transform(toBoolean)
  @IsBoolean()
  isActive?: boolean;
}
