import { ApiPropertyOptional } from '@nestjs/swagger';
import { Transform, TransformFnParams } from 'class-transformer';
import { IsBoolean, IsIn, IsOptional, IsString, IsUUID, MaxLength } from 'class-validator';
import { PaginationQueryDto } from '../../../common/dto/pagination-query.dto';

/**
 * Query-string booleans arrive as strings; implicit conversion is disabled
 * app-wide, so coerce explicitly. Mirrors the previous controller behaviour
 * (`query['flag'] === 'true'`): only the literal "true" is truthy.
 */
const toOptionalBoolean = ({ value }: TransformFnParams): boolean | undefined =>
  value === undefined || value === null || value === '' ? undefined : value === true || value === 'true';

/**
 * Shared list query for rule-engine resources. Every rule-engine list endpoint
 * returns the standard `PaginatedResponse` envelope (`items` + `meta`) built by
 * `common/utils/pagination.util.ts`; `search` is applied server-side against
 * each resource's human-readable columns (see the repository `findPaged`).
 */
export class ListRuleEngineQueryDto extends PaginationQueryDto {
  @ApiPropertyOptional({ description: 'Filter by active flag.' })
  @IsOptional()
  @Transform(toOptionalBoolean)
  @IsBoolean()
  isActive?: boolean;
}

export class ListCargoTypesQueryDto extends ListRuleEngineQueryDto {
  @ApiPropertyOptional({ description: 'Filter by director-approval requirement.' })
  @IsOptional()
  @Transform(toOptionalBoolean)
  @IsBoolean()
  requiresDirectorApproval?: boolean;

  @ApiPropertyOptional({ description: 'Filter by parent cargo-type group.' })
  @IsOptional()
  @IsUUID()
  parentGroupId?: string;

  @ApiPropertyOptional({ enum: ['displayOrder', 'cargoTypeName', 'code', 'createdAt'], default: 'displayOrder' })
  @IsOptional()
  @IsIn(['displayOrder', 'cargoTypeName', 'code', 'createdAt'])
  sortBy?: string;
}

export class ListContainerTypesQueryDto extends ListRuleEngineQueryDto {
  @ApiPropertyOptional({ enum: ['displayOrder'], default: 'displayOrder' })
  @IsOptional()
  @IsIn(['displayOrder'])
  sortBy?: string;
}

export class ListPriorityConfigsQueryDto extends ListRuleEngineQueryDto {
  @ApiPropertyOptional({ enum: ['WAGON', 'CURRENCY', 'CUSTOMS'] })
  @IsOptional()
  @IsIn(['WAGON', 'CURRENCY', 'CUSTOMS'])
  type?: 'WAGON' | 'CURRENCY' | 'CUSTOMS';

  @ApiPropertyOptional({ enum: ['displayOrder'], default: 'displayOrder' })
  @IsOptional()
  @IsIn(['displayOrder'])
  sortBy?: string;
}

export class ListServiceTypesQueryDto extends ListRuleEngineQueryDto {
  @ApiPropertyOptional({ description: 'Filter by standalone-bookable flag.' })
  @IsOptional()
  @Transform(toOptionalBoolean)
  @IsBoolean()
  canBeBookedAlone?: boolean;

  @ApiPropertyOptional({ enum: ['displayOrder', 'serviceName', 'code', 'createdAt'], default: 'displayOrder' })
  @IsOptional()
  @IsIn(['displayOrder', 'serviceName', 'code', 'createdAt'])
  sortBy?: string;
}

export class ListYardsQueryDto extends ListRuleEngineQueryDto {
  @ApiPropertyOptional({ description: 'Filter by yard country.' })
  @IsOptional()
  @IsString()
  @MaxLength(50)
  country?: string;

  @ApiPropertyOptional({ enum: ['displayOrder'], default: 'displayOrder' })
  @IsOptional()
  @IsIn(['displayOrder'])
  sortBy?: string;
}

export class ListYardDistancesQueryDto extends PaginationQueryDto {
  @ApiPropertyOptional({ description: 'Return only distances touching this yard.' })
  @IsOptional()
  @IsUUID()
  yardId?: string;

  @ApiPropertyOptional({ enum: ['createdAt', 'distanceKm'], default: 'createdAt' })
  @IsOptional()
  @IsIn(['createdAt', 'distanceKm'])
  sortBy?: string;
}

export class ListApprovalRulesQueryDto extends PaginationQueryDto {
  @ApiPropertyOptional({ description: 'Filter by approval chain (director vs standard).' })
  @IsOptional()
  @Transform(toOptionalBoolean)
  @IsBoolean()
  requiresDirectorApproval?: boolean;

  @ApiPropertyOptional({ enum: ['stepOrder'], default: 'stepOrder' })
  @IsOptional()
  @IsIn(['stepOrder'])
  sortBy?: string;
}

export class ListRatesQueryDto extends PaginationQueryDto {
  @ApiPropertyOptional({ description: 'Filter by rate status (DRAFT, PENDING_APPROVAL, LIVE...).' })
  @IsOptional()
  @IsString()
  @MaxLength(20)
  status?: string;

  @ApiPropertyOptional({ description: 'Filter by derived rate type.' })
  @IsOptional()
  @IsString()
  @MaxLength(50)
  rateType?: string;

  @ApiPropertyOptional({
    description: 'Filter by rate category — comma-separated appliesTo values (e.g. "CONTAINER" or "FIRST_MILE,LAST_MILE").',
  })
  @IsOptional()
  @IsString()
  @MaxLength(100)
  appliesTo?: string;

  @ApiPropertyOptional({
    description: 'Filter by surcharge trigger — comma-separated trigger values (e.g. "CUSTOMS_CLEARANCE" or "HAZARDOUS,REEFER").',
  })
  @IsOptional()
  @IsString()
  @MaxLength(200)
  trigger?: string;
}

export class ListWeightLimitRulesQueryDto extends PaginationQueryDto {
  @ApiPropertyOptional({ description: 'Filter by container type.' })
  @IsOptional()
  @IsUUID()
  containerTypeId?: string;

  @ApiPropertyOptional({ description: 'Filter by trade direction (IMPORT/EXPORT/BOTH).' })
  @IsOptional()
  @IsString()
  @MaxLength(10)
  tradeDirection?: string;
}
