import { convertToNumber } from '../../../utils/number';
import { InternalFormFieldValidationRule } from './internal-form-field-validation-rule.abstract';
/**
 * A rule that checks if the input is less than or equal to a maximum value
 *
 * @augments {InternalFormFieldValidationRule<string>}
 * @property {{ maxValue: number }} config config including the maxValue limit for validation
 */
export class MaxNumberRule extends InternalFormFieldValidationRule {
  /**
   * It creates a new instance of the class with the given config.
   *
   * @param {{ maxValue: number }} config config including the maxValue limit for validation
   * @param {number} config.maxValue number of the maxValue
   */
  constructor(config) {
    super();
    this.config = config;
  }
  /**
   * If the input is a number, return true if it's less than or equal to the maximum value, false otherwise
   *
   * @param {unknown} input - The input value to be evaluated.
   * @returns {EvaluateResultTranslation} The result of the evaluation.
   * @throws {Error} if input is unable to evaluate
   */
  evaluate(input) {
    var _a;
    if (!this.isAcceptedInputType(input)) {
      throw new Error(`Unexpected type of input: ${typeof input}: ${input}`);
    }
    const maxValue = !isNaN((_a = this.config) === null || _a === void 0 ? void 0 : _a.maxValue) ? this.config.maxValue : Number.MAX_VALUE;
    return {
      isValid: convertToNumber(String(input).replace(/,/g, '')) <= maxValue,
      message: convertToNumber(String(input).replace(/,/g, '')) <= maxValue
        ? ''
        : { key: 'The maximum input value is {0}', args: [maxValue] },
    };
  }
  /**
   * If the input is accepted and the status is not disabled and visible, then return true
   *
   * @param {unknown} input - The input to be evaluated.
   * @param {FormFieldStatusMeta} [status] - FormFieldStatusMeta
   * @returns {boolean} A boolean value.
   */
  canEvaluate(input, status) {
    return status
      ? this.isAcceptedInputType(input) && !status.disabled && status.visible
      : this.isAcceptedInputType(input);
  }
  /**
   * If the field is not disabled, visible, and has been touched or modified, then show the error
   *
   * @param {FormFieldStatusMeta} status - FormFieldStatusMeta
   * @returns {boolean} A boolean value.
   */
  shouldShowError(status) {
    return !status.disabled && status.visible && (status.touched || status.modified);
  }
  /**
   * 	The function returns true when the input can be interpreted as a number either by:
   *  - successful numeric conversion via `convertToNumber(input)` (i.e. not NaN), or
   *  - matching a "thousand-separated" numeric string pattern.
   *
   * @param {unknown} input - The input value to be converted.
   * @returns {boolean} a boolean value.
   */
  isAcceptedInputType(input) {
    const thousandCommaRegex = /^\s*[-+]?(\d{1,3})(,\d{3})*(\.\d*)?\s*$/;
    return !isNaN(convertToNumber(input)) || thousandCommaRegex.test(input);
  }
}
