import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { IsNumberOrStringDto } from 'src/utils/common/numberOrStringDto';

/**
 * Generic Create Data Transfer Object (DTO)
 *
 * This DTO is used for creating new records in the system where the basic
 * required fields are: reason, active status, and optional user reference.
 *
 * Commonly used for creating master data entries like:
 * - Reason codes (difference reasons, response reasons, etc.)
 * - Status types
 * - Categories
 * - Other reference data
 *
 * The DTO supports flexible input types for numeric fields that might come
 * as strings from frontend forms or API clients.
 *
 * @example
 * // Creating a new difference reason:
 * {
 *   "reason": "Price discrepancy in commission calculation",
 *   "active": 1,
 *   "by_user": 123
 * }
 *
 * @example
 * // Creating with string numeric values (common from form submissions):
 * {
 *   "reason": "Client requested adjustment",
 *   "active": "1",
 *   "by_user": "456"
 * }
 *
 * @example
 * // Creating without specifying user (system-generated):
 * {
 *   "reason": "Standard procedure update",
 *   "active": 1
 * }
 */
export class CreateDto {
  /**
   * Descriptive reason or explanation for the record.
   * This is the primary human-readable content of the record.
   *
   * @type {string}
   * @required
   * @example "Price discrepancy in commission calculation"
   * @example "Client requested adjustment"
   * @example "System error in calculation"
   *
   * @isNotEmpty - Validation: Cannot be empty string
   *   Error message: "reason should not be empty"
   *
   * @isString - Validation: Must be a string
   *   Error message: "reason must be a string"
   *
   * @apiProperty - Swagger documentation with example
   *
   * @note Consider adding length validation: @MinLength(3), @MaxLength(500)
   */
  @ApiProperty({
    description: 'Descriptive reason or explanation for the record',
    example: 'Difference Reason is required',
    type: String,
    minLength: 3,
    maxLength: 500,
  })
  @IsNotEmpty({ message: 'Reason is required' })
  @IsString({ message: 'Reason must be a string' })
  reason: string;

  /**
   * Activation status of the record.
   * Typically 1 for active, 0 for inactive. Supports both number and string input.
   *
   * @type {number | string}
   * @required
   * @example 1 (active)
   * @example 0 (inactive)
   * @example "1" (string representation)
   *
   * @isNotEmpty - Validation: Cannot be null, undefined, or empty
   *   Error message: "active should not be empty"
   *
   * @isNumberOrStringDto - Custom validation: Must be number or string
   *   First parameter (1): Default value if invalid
   *   Second parameter ('Status'): Field name for error messages
   *   Validates and converts string numbers to actual numbers
   *
   * @note The custom validator likely handles:
   *   - String "1" → number 1
   *   - String "0" → number 0
   *   - Number 1 → number 1
   *   - Invalid strings → default value (1)
   */
  @ApiProperty({
    description: 'Activation status (1 = active, 0 = inactive)',
    example: 1,
    oneOf: [
      { type: 'number', example: 1 },
      { type: 'string', example: '1' },
    ],
    default: 1,
  })
  @IsNotEmpty({ message: 'Status is required' })
  @IsNumberOrStringDto(1, 'Status')
  active: number | string;

  /**
   * Optional user ID of the creator.
   * Used for audit trails to track who created the record.
   *
   * @type {number | string}
   * @optional
   * @example 123
   * @example "456"
   *
   * @isOptional - Validation: Field is not required
   *
   * @isNumberOrStringDto - Custom validation: Must be number or string if provided
   *   First parameter (0): Default value if invalid
   *   Second parameter ('User ID'): Field name for error messages
   *
   * @apiPropertyOptional - Swagger documentation for optional field
   *
   * @note In practice, this is often populated from the authenticated user's session
   * rather than client input, for security reasons.
   */
  @ApiPropertyOptional({
    description: 'ID of the user creating the record (for audit trail)',
    example: 1,
    oneOf: [
      { type: 'number', example: 123 },
      { type: 'string', example: '456' },
    ],
  })
  @IsOptional()
  @IsNumberOrStringDto(0, 'User ID')
  by_user?: number | string;
}
