import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
  IsArray,
  IsBoolean,
  IsNumberString,
  IsOptional,
  IsString,
  ValidateNested,
} from 'class-validator';
import { DateRangeDto } from 'src/utils/datetime/dateRangeDto';
import { PaginationDto } from 'src/config/pagination/paginationDto';

/**
 * DTO for searching commission or related records with multiple optional filters.
 *
 * Inherits from PaginationDto to support paginated API responses.
 * Each property represents a filter that can be applied to the search query.
 */
export class SearchDto extends PaginationDto {
  /**
   * Optional ID of the record.
   * Can be number or string depending on context (e.g., auto-increment ID or UUID).
   * Example: "123" or 123
   */
  @ApiPropertyOptional({ description: 'Record ID (number or string)' })
  @IsOptional()
  @IsNumberString({}, { message: 'id must be a numeric string or number' })
  id?: number | string;

  /**
   * Optional search title for filtering records by name or title.
   * Example: "Commission July 2025"
   */
  @ApiPropertyOptional({ description: 'Search title or name' })
  @IsOptional()
  @IsString()
  search_title?: string;

  /**
   * Association type (mandatory).
   * Indicates the type of association for the search (e.g., Institute, Agent).
   * Example: "1" (numeric string representing an enum value)
   */
  @ApiProperty({ description: 'Association type', example: '1' })
  @IsString()
  association_type: string;

  /**
   * Optional array of visa service country IDs to filter the search.
   * Example: [1, 2, 3]
   */
  @ApiPropertyOptional({
    description: 'Filter by visa service country IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  visa_service_country_id?: number[];

  /**
   * Optional array of institute IDs to filter the search.
   * Example: [101, 102]
   */
  @ApiPropertyOptional({
    description: 'Filter by institute IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  institute_id?: number[];

  /**
   * Optional array of client country IDs for filtering.
   * Example: [80, 81]
   */
  @ApiPropertyOptional({
    description: 'Filter by client country IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  client_from_country_id?: number[];

  /**
   * Optional array of intake/session IDs for filtering records.
   * Example: [95504, 95505]
   */
  @ApiPropertyOptional({
    description: 'Filter by intake/session IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  intake_id?: number[];

  /**
   * Optional array of commission instance IDs.
   * Example: [1, 2, 3]
   */
  @ApiPropertyOptional({
    description: 'Filter by commission instance IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  commission_instance_id?: number[];

  /**
   * Optional array of associate IDs.
   * Can be used to filter records linked to specific associates.
   * Example: ["A123", "A124"]
   */
  @ApiPropertyOptional({
    description: 'Filter by associate IDs',
    type: [String],
  })
  @IsOptional()
  @IsArray()
  associate_id?: string[];

  /**
   * Optional array of branch IDs used for invoicing.
   * Example: [1, 2]
   */
  @ApiPropertyOptional({
    description: 'Filter by invoice branch IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  invoice_branch_id?: number[];

  /**
   * Optional array of bank account IDs used for invoicing.
   * Example: [10, 11]
   */
  @ApiPropertyOptional({
    description: 'Filter by invoice bank account IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  invoice_bank_account_id?: number[];

  /**
   * Optional array of received/recorded IDs for filtering payment or receipt records.
   * Example: [1]
   */
  @ApiPropertyOptional({
    description: 'Filter by received or recorded IDs',
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  received_recorded?: number[];

  /**
   * Optional array of statuses indicating active/inactive records.
   * Each value should be a string representing status.
   * Example: ["active", "inactive"]
   */
  @ApiPropertyOptional({
    description: 'Filter by active status',
    type: [String],
  })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  active?: string[];

  /**
   * Optional array of user IDs who created the record.
   */
  @ApiPropertyOptional({
    description: 'Filter by created_by user IDs',
    type: [String],
  })
  @IsOptional()
  @IsArray()
  created_by?: string[];

  /**
   * Optional array of user IDs who updated the record.
   */
  @ApiPropertyOptional({
    description: 'Filter by updated_by user IDs',
    type: [String],
  })
  @IsOptional()
  @IsArray()
  updated_by?: string[];

  /**
   * Optional boolean to indicate if results should be exported as CSV.
   * Default value is false.
   */
  @ApiPropertyOptional({
    description: 'Flag to export results as CSV',
    default: false,
  })
  @IsOptional()
  @IsBoolean()
  is_csv?: boolean = false;

  /**
   * Optional date range for filtering records by creation date.
   * Uses DateRangeDto which supports `from` and `to` dates.
   */
  @ApiPropertyOptional({
    description: 'Filter by creation date range',
    type: DateRangeDto,
  })
  @IsOptional()
  @ValidateNested()
  @Type(() => DateRangeDto)
  created_on?: DateRangeDto;

  /**
   * Optional date range for filtering records by last update date.
   * Uses DateRangeDto which supports `from` and `to` dates.
   */
  @ApiPropertyOptional({
    description: 'Filter by update date range',
    type: DateRangeDto,
  })
  @IsOptional()
  @ValidateNested()
  @Type(() => DateRangeDto)
  updated_on?: DateRangeDto;
}
