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

/**
 * SearchDto - Comprehensive Data Transfer Object for commission data search and filtering
 *
 * This DTO extends PaginationDto and provides extensive filtering capabilities for
 * searching commission-related data across the system. It supports filtering by
 * multiple criteria including dates, associations, countries, institutes, and users.
 *
 * Business Context: Commission Data Search & Filtering
 * - Used across multiple endpoints for searching commission data
 * - Provides comprehensive filtering for reports and dashboards
 * - Supports both simple and complex search scenarios
 * - Essential for data analysis and business intelligence
 *
 * Key Features:
 * - Extends PaginationDto for pagination support
 * - Supports date range filtering with DateRangeDto
 * - Multiple array filters for OR conditions
 * - CSV export capability
 * - Comprehensive validation for all filter types
 *
 * Usage Across Modules:
 * - Commission Contracts search
 * - Commission Enquiries search
 * - Commission Received payments search
 * - Commission Reports generation
 */
export class SearchDto extends PaginationDto {
  /**
   * Text Search Filter
   *
   * Free-text search across relevant text fields in commission records.
   * Typically searches fields like notes, titles, transaction IDs, or remarks.
   *
   * Search Behavior:
   * - Usually performs LIKE %search_title% queries
   * - May search across multiple fields
   * - Case-insensitive in most implementations
   *
   * Example Usage:
   * - "Q1 2024 commission"
   * - "University of Melbourne"
   * - "Invoice #2024-001"
   *
   * @example "University commission"
   */
  @ApiPropertyOptional({
    description: 'Text search across commission record fields',
    example: 'University commission',
  })
  @IsOptional()
  @IsString()
  search_title?: string;

  /**
   * Association Type
   *
   * The type of commission association/relationship to filter by.
   * This is a required field that determines the commission workflow context.
   *
   * Business Significance:
   * - Required for all commission searches
   * - Determines which entities and relationships to query
   * - Affects which service methods are called
   *
   * Common Values:
   * - "1": Institute-based commissions
   * - "2": Master Agent-based commissions
   * - "3": Sub-Agent-based commissions
   *
   * @example "1"
   */
  @ApiProperty({
    description: 'Type of commission association',
    example: '1',
    required: true,
    enum: ['1', '2', '3'],
  })
  @IsString()
  association_type: string;

  /**
   * Visa Service Countries Filter
   *
   * Array of country IDs where visa services are provided.
   * Filters commission records by destination countries for visa applications.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Typically used with visa_service_country_id field
   * - Important for country-specific commission reporting
   *
   * Example Values:
   * - [1, 3, 5] → Commissions for USA, Australia, Canada
   * - [2] → Commissions only for United Kingdom
   *
   * @example [1, 3, 5]
   */
  @ApiPropertyOptional({
    description: 'Filter by visa service country IDs',
    example: [1, 3, 5],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  visa_service_country_id?: number[];

  /**
   * Institutes Filter
   *
   * Array of educational institute IDs to filter by.
   * Filters commission records by specific colleges/universities.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for institute-specific commission tracking
   * - Important for partner relationship management
   *
   * Example Values:
   * - [101, 102] → Commissions for University of Melbourne and University of Toronto
   * - [105] → Commissions only for University of Oxford
   *
   * @example [101, 102]
   */
  @ApiPropertyOptional({
    description: 'Filter by educational institute IDs',
    example: [101, 102],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  institute_id?: number[];

  /**
   * Client Countries Filter
   *
   * Array of client/source country IDs to filter by.
   * Filters commission records by student nationalities/countries of origin.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for market-specific commission analysis
   * - Important for geographical performance tracking
   *
   * Example Values:
   * - [1, 2] → Commissions for Indian and Chinese students
   * - [3] → Commissions only for Nigerian students
   *
   * @example [1, 2]
   */
  @ApiPropertyOptional({
    description: 'Filter by client/source country IDs',
    example: [1, 2],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  client_from_country_id?: number[];

  /**
   * Intake Periods Filter
   *
   * Array of academic intake IDs to filter by.
   * Filters commission records by specific intake periods (semesters/terms).
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for seasonal commission analysis
   * - Important for academic cycle reporting
   *
   * Example Values:
   * - [202401, 202407] → January and July 2024 intakes
   * - [202301] → Only January 2023 intake
   *
   * @example [202401, 202407]
   */
  @ApiPropertyOptional({
    description: 'Filter by academic intake period IDs',
    example: [202401, 202407],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  intake_id?: number[];

  /**
   * Commission Instances Filter
   *
   * Array of commission contract instance IDs to filter by.
   * Filters commission records by specific commission tiers or structures.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for commission structure analysis
   * - Important for contract performance tracking
   *
   * Example Values:
   * - [1, 2] → First and second commission tiers
   * - [3] → Special commission instance only
   *
   * @example [1, 2]
   */
  @ApiPropertyOptional({
    description: 'Filter by commission contract instance IDs',
    example: [1, 2],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  commission_instance_id?: number[];

  /**
   * Associates Filter (Master Agents)
   *
   * Array of associate/master agent IDs to filter by.
   * Used for association_type "2" (Master Agent) filtering.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Only applicable for association_type = "2"
   * - Used for agent performance tracking
   *
   * Example Values:
   * - ["AG001", "AG002"] → Specific master agents
   * - ["AG005"] → Single master agent
   *
   * Note: String type allows alphanumeric agent IDs
   *
   * @example ["AG001", "AG002"]
   */
  @ApiPropertyOptional({
    description: 'Filter by master agent/associate IDs',
    example: ['AG001', 'AG002'],
    type: [String],
  })
  @IsOptional()
  @IsArray()
  associate_id?: string[];

  /**
   * Bank Accounts Filter
   *
   * Array of bank account IDs to filter by.
   * Filters commission received records by payment destination accounts.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Primarily used for commission received searches
   * - Important for financial reconciliation
   *
   * Example Values:
   * - [1001, 1002] → Specific bank accounts
   * - [1005] → Single bank account
   *
   * @example [1001, 1002]
   */
  @ApiPropertyOptional({
    description: 'Filter by bank account IDs',
    example: [1001, 1002],
    type: [Number],
  })
  @IsOptional()
  @IsArray()
  bank_account_id?: number[];

  /**
   * Status Filter
   *
   * Array of status values to filter by (active/inactive).
   * Filters commission records by their current status.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Typically uses status codes like "1", "2", etc.
   * - Important for status-based filtering
   *
   * Common Values:
   * - ["1"] → Active records only
   * - ["2"] → Inactive records only
   * - ["1", "2"] → Both active and inactive
   *
   * @example ["1"]
   */
  @ApiPropertyOptional({
    description: 'Filter by status values (active/inactive)',
    example: ['1'],
    type: [String],
  })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  active?: string[];

  /**
   * Created By Users Filter
   *
   * Array of user IDs who created the records.
   * Filters commission records by the users who created them.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for user activity tracking
   * - Important for audit trails
   *
   * Example Values:
   * - ["U001", "U002"] → Specific users
   * - ["U005"] → Single user
   *
   * Note: String type allows alphanumeric user IDs
   *
   * @example ["U001", "U002"]
   */
  @ApiPropertyOptional({
    description: 'Filter by user IDs who created the records',
    example: ['U001', 'U002'],
    type: [String],
  })
  @IsOptional()
  @IsArray()
  created_by?: string[];

  /**
   * Updated By Users Filter
   *
   * Array of user IDs who last updated the records.
   * Filters commission records by the users who last modified them.
   *
   * Business Logic:
   * - Multi-select filter (OR condition)
   * - Used for modification tracking
   * - Important for change management
   *
   * Example Values:
   * - ["U003", "U004"] → Specific users
   * - ["U006"] → Single user
   *
   * Note: String type allows alphanumeric user IDs
   *
   * @example ["U003", "U004"]
   */
  @ApiPropertyOptional({
    description: 'Filter by user IDs who last updated the records',
    example: ['U003', 'U004'],
    type: [String],
  })
  @IsOptional()
  @IsArray()
  updated_by?: string[];

  /**
   * CSV Export Flag
   *
   * Boolean flag indicating whether the search results should be formatted for CSV export.
   * When true, the response may include additional formatting or different data structures.
   *
   * Business Logic:
   * - Defaults to false
   * - May trigger CSV-specific data transformations
   * - Could affect performance (larger data sets)
   *
   * Use Cases:
   * - false: Normal paginated API response
   * - true: CSV-optimized response for export
   *
   * @example false
   * @example true
   */
  @ApiPropertyOptional({
    description: 'Flag for CSV export formatting',
    example: false,
    default: false,
  })
  @IsOptional()
  @IsBoolean()
  is_csv?: boolean = false;

  /**
   * Creation Date Range Filter
   *
   * Date range filter for when records were created.
   * Uses DateRangeDto for flexible date range filtering.
   *
   * Business Logic:
   * - Supports from date, to date, or both
   * - Used for time-based analysis
   * - Important for period reporting
   *
   * DateRangeDto Structure:
   * - from: Start date (optional)
   * - to: End date (optional)
   *
   * Example Usage:
   * - { from: "2024-01-01", to: "2024-03-31" } → Q1 2024
   * - { from: "2024-01-01" } → From January 1st onward
   * - { to: "2024-12-31" } → Up to December 31st
   *
   * @example { "from": "2024-01-01", "to": "2024-03-31" }
   */
  @ApiPropertyOptional({
    type: DateRangeDto,
    description: 'Filter by creation date range',
    example: { from: '2024-01-01', to: '2024-03-31' },
  })
  @IsOptional()
  @ValidateNested()
  @Type(() => DateRangeDto)
  created_on?: DateRangeDto;

  /**
   * Update Date Range Filter
   *
   * Date range filter for when records were last updated.
   * Uses DateRangeDto for flexible date range filtering.
   *
   * Business Logic:
   * - Supports from date, to date, or both
   * - Used for modification tracking
   * - Important for change management reporting
   *
   * DateRangeDto Structure:
   * - from: Start date (optional)
   * - to: End date (optional)
   *
   * Example Usage:
   * - { from: "2024-04-01", to: "2024-06-30" } → Q2 2024 updates
   * - { from: "2024-07-01" } → Updates from July 1st onward
   * - { to: "2024-12-31" } → Updates up to December 31st
   *
   * @example { "from": "2024-04-01", "to": "2024-06-30" }
   */
  @ApiPropertyOptional({
    type: DateRangeDto,
    description: 'Filter by last update date range',
    example: { from: '2024-04-01', to: '2024-06-30' },
  })
  @IsOptional()
  @ValidateNested()
  @Type(() => DateRangeDto)
  updated_on?: DateRangeDto;
}
