import { ApiProperty } from '@nestjs/swagger';
import { IsArray, IsNotEmpty } from 'class-validator';

/**
 * Data Transfer Object (DTO) for searching cities based on countries and optionally states.
 * This DTO defines the structure and validation rules for city search requests.
 *
 * DTOs in NestJS are used to:
 * 1. Define the expected shape of incoming request data
 * 2. Automatically validate incoming data using class-validator
 * 3. Generate API documentation using Swagger decorators
 * 4. Transform incoming data to the correct types
 *
 * @example
 * // Example request body:
 * {
 *   "countries": [1, 44, 91],  // Country IDs (required)
 *   "states": [5, 12, 18]      // State IDs (optional)
 * }
 *
 * @example
 * // In a controller:
 * @Post('search-cities')
 * async searchCities(@Body() citySearchDto: CitySearchDto) {
 *   return this.cityService.findCitiesByCountriesAndStates(
 *     citySearchDto.countries,
 *     citySearchDto.states
 *   );
 * }
 */
export class CitySearchDto {
  /**
   * Array of country IDs to search for cities within.
   * This is a required field and must be a non-empty array.
   *
   * @type {number[]}
   * @example [1, 44, 91] // USA, UK, India
   *
   * @apiProperty - Swagger documentation decorator
   *   - Shows this field in API documentation
   *   - Automatically infers type as array of numbers
   *
   * @isNotEmpty - Validation decorator
   *   - Ensures the field is not null, undefined, or empty array
   *   - Error message: "countries should not be empty"
   *
   * @isArray - Validation decorator
   *   - Ensures the value is an array
   *   - Error message: "countries must be an array"
   */
  @ApiProperty({
    description: 'Array of country IDs to filter cities by',
    example: [1, 44, 91],
    type: [Number],
  })
  @IsNotEmpty({ message: 'At least one country must be specified' })
  @IsArray({ message: 'Countries must be provided as an array' })
  countries: number[];

  /**
   * Optional array of state IDs to further filter cities.
   * If provided, the search will return cities within the specified states.
   * If not provided, all cities within the specified countries will be returned.
   *
   * @type {any[]}
   * @optional
   * @example [5, 12, 18] // California, Texas, Florida (if country is USA)
   *
   * @apiProperty - Swagger documentation decorator
   *   - Shows this field in API documentation
   *   - Marks field as optional in Swagger
   *
   * @isNotEmpty - Validation decorator (conditional)
   *   - Applied only when states array is provided
   *   - If states array is provided, it must not be empty
   *
   * @isArray - Validation decorator (conditional)
   *   - If states array is provided, it must be a valid array
   *
   * @note The type is `any[]` which provides flexibility but less type safety.
   * Consider using `number[]` or `string[]` based on your actual state ID format.
   */
  @ApiProperty({
    description: 'Optional array of state IDs to further filter cities',
    example: [5, 12, 18],
    type: [Number],
    required: false,
  })
  @IsNotEmpty({ message: 'States array must not be empty if provided' })
  @IsArray({ message: 'States must be an array if provided' })
  states?: any[];
}
