<?php

namespace WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules;

/**
 * Integer Rule
 *
 * Validates that a value is an integer.
 *
 * @package WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules
 * @since 2.0.0
 */
class IntegerRule extends AbstractRule
{
    /**
     * Minimum value.
     *
     * @var int|null
     */
    private ?int $min = null;

    /**
     * Maximum value.
     *
     * @var int|null
     */
    private ?int $max = null;

    /**
     * Whether to allow string representations.
     *
     * @var bool
     */
    private bool $strict = false;

    /**
     * Set minimum value.
     *
     * @param int $min Minimum value.
     *
     * @return static
     */
    public function min(int $min): static
    {
        $clone = clone $this;
        $clone->min = $min;

        return $clone;
    }

    /**
     * Set maximum value.
     *
     * @param int $max Maximum value.
     *
     * @return static
     */
    public function max(int $max): static
    {
        $clone = clone $this;
        $clone->max = $max;

        return $clone;
    }

    /**
     * Set both min and max.
     *
     * @param int $min Minimum value.
     * @param int $max Maximum value.
     *
     * @return static
     */
    public function between(int $min, int $max): static
    {
        return $this->min($min)->max($max);
    }

    /**
     * Require strict integer type (no string representations).
     *
     * @return static
     */
    public function strict(): static
    {
        $clone = clone $this;
        $clone->strict = true;

        return $clone;
    }

    /**
     * {@inheritDoc}
     */
    public function validate(mixed $value, string $field, array $data = []): bool
    {
        // Allow null values (use RequiredRule if field is required)
        if ($value === null) {
            return true;
        }

        // Check if it's a valid integer
        if ($this->strict) {
            if (!is_int($value)) {
                return false;
            }
        } else {
            // Allow numeric strings
            if (!is_numeric($value) || (int) $value != $value) {
                return false;
            }
            $value = (int) $value;
        }

        // Check min/max bounds
        if ($this->min !== null && $value < $this->min) {
            return false;
        }

        if ($this->max !== null && $value > $this->max) {
            return false;
        }

        return true;
    }

    /**
     * {@inheritDoc}
     */
    public function getName(): string
    {
        return 'integer';
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultMessage(string $field): string
    {
        if ($this->min !== null && $this->max !== null) {
            return sprintf(
                /* translators: 1: field name, 2: min value, 3: max value */
                __('The %1$s must be between %2$d and %3$d.', 'ultimate-security'),
                $field,
                $this->min,
                $this->max
            );
        }

        if ($this->min !== null) {
            return sprintf(
                /* translators: 1: field name, 2: min value */
                __('The %1$s must be at least %2$d.', 'ultimate-security'),
                $field,
                $this->min
            );
        }

        if ($this->max !== null) {
            return sprintf(
                /* translators: 1: field name, 2: max value */
                __('The %1$s must not exceed %2$d.', 'ultimate-security'),
                $field,
                $this->max
            );
        }

        return sprintf(
            /* translators: %s: field name */
            __('The %s must be an integer.', 'ultimate-security'),
            $field
        );
    }
}
