<?php

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use Flowaxy\Support\Validation\Validator;
use Flowaxy\Support\Services\ValidationService;

use function count;
use function ctype_alnum;
use function ctype_alpha;
use function date_create;
use function explode;
use function filter_var;
use function in_array;
use function is_numeric;
use function is_string;
use function mb_strlen;
use function preg_match;
use function trim;
use const FILTER_VALIDATE_IP;

// Хелпер для валідації даних
final class ValidationHelper
{
    // Получение экземпляра ValidationService
    private static function getValidationService(): ValidationService
    {
        static $service = null;
        if ($service === null) {
            $service = new ValidationService();
        }
        return $service;
    }

    // Валідувати дані
    public static function validate(array $data, array $rules): array
    {
        $errors = [];
        $valid = true;

        foreach ($rules as $field => $fieldRules) {
            $value = $data[$field] ?? null;

            foreach ($fieldRules as $rule) {
                $ruleParts = explode(':', $rule);
                $ruleName = $ruleParts[0];
                $ruleValue = $ruleParts[1] ?? null;

                $isValid = match ($ruleName) {
                    'required' => self::validateRequired($value),
                    'email' => self::validateEmail($value),
                    'url' => self::validateUrl($value),
                    'ip' => self::validateIp($value),
                    'date' => self::validateDate($value),
                    'numeric' => self::validateNumeric($value),
                    'alpha' => self::validateAlpha($value),
                    'alpha_numeric' => self::validateAlphaNumeric($value),
                    'min' => self::validateMin($value, (int)$ruleValue),
                    'max' => self::validateMax($value, (int)$ruleValue),
                    'length' => self::validateLength($value, (int)$ruleValue),
                    'regex' => self::validateRegex($value, $ruleValue),
                    'in' => self::validateIn($value, explode(',', $ruleValue ?? '')),
                    'not_in' => self::validateNotIn($value, explode(',', $ruleValue ?? '')),
                    'between' => self::validateBetween($value, explode(',', $ruleValue ?? '')),
                    default => true,
                };

                if (!$isValid) {
                    $errors[$field][] = "Поле {$field} не пройшло валідацію: {$ruleName}";
                    $valid = false;
                }
            }
        }

        return [
            'valid' => $valid,
            'errors' => $errors,
        ];
    }

    // Валідація email
    public static function validateEmail(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        // Используем ValidationService как единую точку входа
        $result = self::getValidationService()->validateEmail((string)$value);
        return $result['valid'] ?? false;
    }

    // Валідація URL
    public static function validateUrl(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return Validator::validateUrl((string)$value);
    }

    // Валідація IP адреси
    public static function validateIp(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return filter_var($value, FILTER_VALIDATE_IP) !== false;
    }

    // Валідація дати
    public static function validateDate(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        $date = date_create($value);

        return $date !== false;
    }

    // Валідація числового значення
    public static function validateNumeric(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return is_numeric($value);
    }

    // Валідація тільки букв
    public static function validateAlpha(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return ctype_alpha((string)$value);
    }

    // Валідація букв та цифр
    public static function validateAlphaNumeric(mixed $value): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return ctype_alnum((string)$value);
    }

    // Валідація мінімального значення
    public static function validateMin(mixed $value, int $min): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        if (is_numeric($value)) {
            return (float)$value >= $min;
        }

        if (is_string($value)) {
            return mb_strlen($value, 'UTF-8') >= $min;
        }

        return false;
    }

    // Валідація максимального значення
    public static function validateMax(mixed $value, int $max): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        if (is_numeric($value)) {
            return (float)$value <= $max;
        }

        if (is_string($value)) {
            return mb_strlen($value, 'UTF-8') <= $max;
        }

        return false;
    }

    // Валідація довжини
    public static function validateLength(mixed $value, int $length): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        if (is_string($value)) {
            return mb_strlen($value, 'UTF-8') === $length;
        }

        return false;
    }

    // Валідація за регулярним виразом
    public static function validateRegex(mixed $value, ?string $pattern): bool
    {
        if ($value === null || $value === '' || $pattern === null) {
            return false;
        }

        return preg_match($pattern, (string)$value) === 1;
    }

    // Валідація входження в список
    public static function validateIn(mixed $value, array $list): bool
    {
        if ($value === null || $value === '') {
            return false;
        }

        return in_array($value, $list, true);
    }

    // Валідація невходження в список
    public static function validateNotIn(mixed $value, array $list): bool
    {
        return !self::validateIn($value, $list);
    }

    // Валідація діапазону
    public static function validateBetween(mixed $value, array $range): bool
    {
        if (count($range) !== 2) {
            return false;
        }

        $min = (float)$range[0];
        $max = (float)$range[1];

        if (is_numeric($value)) {
            return (float)$value >= $min && (float)$value <= $max;
        }

        if (is_string($value)) {
            $length = mb_strlen($value, 'UTF-8');

            return $length >= $min && $length <= $max;
        }

        return false;
    }

    // Валідація обов'язкового поля
    public static function validateRequired(mixed $value): bool
    {
        if (is_string($value)) {
            return trim($value) !== '';
        }

        return $value !== null && $value !== '';
    }

    // Валідація nullable поля
    public static function validateNullable(mixed $value): bool
    {
        return true; // Nullable завжди валідний
    }
}
