<?php

namespace WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules;

/**
 * In Array Rule
 *
 * Validates that a value is in a list of allowed values.
 *
 * @package WPUltimateSecurity\UltimateSecurity\Support\Validation\Rules
 * @since 2.0.0
 */
class InArrayRule extends AbstractRule
{
    /**
     * Allowed values.
     *
     * @var array
     */
    private array $allowedValues;

    /**
     * Whether to use strict comparison.
     *
     * @var bool
     */
    private bool $strict = false;

    /**
     * Create a new rule instance.
     *
     * @param array $allowedValues The allowed values.
     */
    public function __construct(array $allowedValues = [])
    {
        $this->allowedValues = $allowedValues;
    }

    /**
     * Set allowed values.
     *
     * @param array $values Allowed values.
     *
     * @return static
     */
    public function values(array $values): static
    {
        $clone = clone $this;
        $clone->allowedValues = $values;

        return $clone;
    }

    /**
     * Use strict comparison.
     *
     * @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
    {
        if ($value === null) {
            return true;
        }

        return in_array($value, $this->allowedValues, $this->strict);
    }

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

    /**
     * {@inheritDoc}
     */
    protected function getDefaultMessage(string $field): string
    {
        $values = array_map(function ($v) {
            return is_string($v) ? "'{$v}'" : $v;
        }, $this->allowedValues);

        return sprintf(
            /* translators: 1: field name, 2: allowed values */
            __('The %1$s must be one of: %2$s.', 'ultimate-security'),
            $field,
            implode(', ', $values)
        );
    }
}
