import { ApiProperty, ApiPropertyOptional, PartialType } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsArray, IsEnum, IsInt, IsNumber, IsOptional, IsString, IsUUID, Matches, Min, ValidateNested } from 'class-validator';

import { FEE_RULE_BASES, FEE_RULE_TYPES, FeeRuleBasis, FeeRuleType } from '../entities/warehouse-fee-rule.entity';

export class FeeRuleTierDto {
  @ApiProperty({ example: 4 })
  @IsInt()
  @Min(1)
  fromDay!: number;

  @ApiPropertyOptional({ example: 4, description: 'Inclusive. Leave empty for an open-ended tier.' })
  @IsOptional()
  @IsInt()
  @Min(1)
  toDay?: number | null;

  @ApiProperty({ example: 2500 })
  @IsNumber()
  @Min(0)
  ratePerDay!: number;
}

export class CreateFeeRuleDto {
  @ApiProperty()
  @IsString()
  @Matches(/^[A-Za-z\s]+$/, { message: 'name may only contain letters and spaces' })
  name!: string;

  @ApiProperty({ enum: FEE_RULE_TYPES })
  @IsEnum(FEE_RULE_TYPES)
  ruleType!: FeeRuleType;

  @ApiPropertyOptional({ default: 100 })
  @IsOptional()
  @IsInt()
  priority?: number;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  freightType?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  tradeDirection?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  cargoTypeCode?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  containerType?: string;

  @ApiPropertyOptional({ format: 'uuid' })
  @IsOptional()
  @IsUUID()
  facilityId?: string;

  @ApiPropertyOptional({ format: 'uuid' })
  @IsOptional()
  @IsUUID()
  warehouseId?: string;

  @ApiPropertyOptional({ format: 'uuid' })
  @IsOptional()
  @IsUUID()
  yardId?: string;

  @ApiPropertyOptional({ format: 'uuid' })
  @IsOptional()
  @IsUUID()
  zoneId?: string;

  @ApiProperty({ description: 'Grace period in days before charging starts.' })
  @IsInt()
  @Min(0)
  freeDays!: number;

  @ApiProperty({ description: 'Day-based fees: rate/day. Double handling: flat rate per basis unit.' })
  @IsNumber()
  @Min(0)
  ratePerDay!: number;

  @ApiPropertyOptional({ description: 'Truck detention only: grace window in hours (default 3).' })
  @IsOptional()
  @IsInt()
  @Min(0)
  freeHours?: number;

  @ApiPropertyOptional({ description: 'Truck detention only: scope by vehicle type (TRUCK | VAN | TRAILER | …). Null = any.' })
  @IsOptional()
  @IsString()
  vehicleType?: string;

  @ApiPropertyOptional({
    enum: FEE_RULE_BASES,
    description: 'Double-handling charge basis: PER_CONTAINER | PER_TON | PER_ITEM.',
  })
  @IsOptional()
  @IsEnum(FEE_RULE_BASES)
  basis?: FeeRuleBasis;

  @ApiPropertyOptional({ type: [FeeRuleTierDto] })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => FeeRuleTierDto)
  tiers?: FeeRuleTierDto[];

  @ApiPropertyOptional({ default: 'USD' })
  @IsOptional()
  @IsString()
  currency?: string;
}

export class UpdateFeeRuleDto extends PartialType(CreateFeeRuleDto) {}
