import {
  IsInt,
  IsOptional,
  IsString,
  ValidatorConstraint,
  ValidatorConstraintInterface,
  ValidationArguments,
} from 'class-validator';

/**
 * Custom validator to ensure **only one of `set_id` or `contract_id` is provided**.
 *
 * Rules:
 * - Either `set_id` or `contract_id` must be present.
 * - Both cannot be provided at the same time.
 *
 * Example:
 * Valid: { set_id: 1, contract_id: undefined }
 * Valid: { set_id: undefined, contract_id: 2 }
 * Invalid: { set_id: 1, contract_id: 2 }
 */
@ValidatorConstraint({ name: 'onlyOne', async: false })
export class OnlyOneIdConstraint implements ValidatorConstraintInterface {
  /**
   * Validation logic
   * @param _ - the value being validated (ignored here)
   * @param args - validation arguments containing the full object
   * @returns true if exactly one of `set_id` or `contract_id` exists
   */
  validate(_: any, args: ValidationArguments) {
    const obj = args.object as any;
    // Only valid if exactly one of the two IDs is provided
    return (
      (!!obj.set_id && !obj.contract_id) || (!obj.set_id && !!obj.contract_id)
    );
  }

  /**
   * Default error message when validation fails
   */
  defaultMessage(args: ValidationArguments) {
    return 'Either set_id or contract_id must be provided, but not both';
  }
}

/**
 * DTO for removing an attachment.
 *
 * This DTO ensures that:
 * 1. `id` of the attachment is provided.
 * 2. Either `set_id` or `contract_id` is provided, but not both.
 * 3. `file_name` and `file_url` are provided to identify the file to remove.
 */
export class RemoveAttachmentDto {
  /**
   * Unique identifier of the attachment record
   */
  @IsString()
  id: string;

  /**
   * Optional association to a specific set
   */
  @IsOptional()
  @IsInt()
  set_id?: number;

  /**
   * Optional association to a specific contract
   */
  @IsOptional()
  @IsInt()
  contract_id?: number;

  /**
   * Name of the file to remove
   */
  @IsString()
  file_name: string;

  /**
   * URL or path of the file to remove
   */
  @IsString()
  file_url: string;
}
