<?php

namespace WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules;

/**
 * String Rule
 *
 * Validates that a value is a string.
 *
 * @package WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules
 * @since 2.0.0
 */
class StringRule extends AbstractRule
{
    /**
     * Minimum length.
     *
     * @var int|null
     */
    private ?int $minLength = null;

    /**
     * Maximum length.
     *
     * @var int|null
     */
    private ?int $maxLength = null;

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

        return $clone;
    }

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

        return $clone;
    }

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

    /**
     * {@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;
        }

        if (!is_string($value)) {
            return false;
        }

        $length = strlen($value);

        if ($this->minLength !== null && $length < $this->minLength) {
            return false;
        }

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

        return true;
    }

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

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

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

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

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