import { IsIn, IsInt, IsNotEmpty } from 'class-validator';
import { Type } from 'class-transformer';
import { AssociationType, ByUserType } from 'src/utils/enums/enum';
import { ApiProperty } from '@nestjs/swagger';

/**
 * DTO for fetching data based on user type and association type.
 *
 * This DTO ensures that requests include:
 * 1. `by` – the user type performing the action
 * 2. `type` – the type of association to filter by
 *
 * Both fields are validated to accept only predefined enum values.
 */
export class FetchByUsersDto {
  /**
   * The user type performing the action.
   *
   * Examples of user types could include:
   * - EMPLOYEE
   * - MANAGER
   * - ADMIN
   *
   * Validation:
   * - Must not be empty (`@IsNotEmpty`)
   * - Must match one of the values in the `ByUserType` enum (`@IsIn`)
   *
   * Swagger Documentation:
   * - `enum` displays all possible `ByUserType` values
   */
  @ApiProperty({ enum: ByUserType })
  @IsNotEmpty() // Ensures the field is provided
  @IsIn(Object.values(ByUserType)) // Validates against the enum values
  by: ByUserType;

  /**
   * The type of association to filter by.
   *
   * Examples of association types could include:
   * - INSTITUTE
   * - SUB_AGENT
   * - OTHER types as defined in `AssociationType` enum
   *
   * Validation:
   * - Must not be empty (`@IsNotEmpty`)
   * - Must be an integer (`@IsInt`)
   * - Must be one of the numeric values in the `AssociationType` enum (`@IsIn`)
   *
   * Transformation:
   * - `@Type(() => Number)` ensures that string input (common from query params)
   *   is converted to a number before validation.
   *
   * Swagger Documentation:
   * - `enum` lists all valid numeric `AssociationType` values
   * - `example` provides a sample value for API documentation
   */
  @ApiProperty({
    enum: AssociationType,
    example: AssociationType.INSTITUTE,
  })
  @IsNotEmpty() // Value is required
  @Type(() => Number) // Converts input to number (especially useful for query params)
  @IsInt() // Validates that the value is an integer
  @IsIn(Object.values(AssociationType).filter((v) => typeof v === 'number')) // Ensures the value exists in the numeric enum
  type: AssociationType;
}
