<?php

namespace App\Domain\Identity\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

/**
 * A person's name must be at least four parts — رباعي.
 *
 * Egyptian records are keyed on the four-part name: the national ID, the birth
 * certificate, the federation card and the school file all carry it, and a
 * player registered as "محمد أحمد" cannot be matched against any of them. Two
 * players sharing a first and father's name are common enough that the third
 * and fourth parts are what actually tell them apart, which is why the desk is
 * held to it at entry rather than asked to repair it later.
 *
 * Four is a floor, not a target: five parts or more pass untouched.
 */
class FullName implements ValidationRule
{
    public const MINIMUM_PARTS = 4;

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!is_string($value)) {
            $fail('الاسم غير صالح');
            return;
        }

        if (count(self::parts($value)) < self::MINIMUM_PARTS) {
            $fail('يجب كتابة الاسم رباعياً على الأقل (٤ أسماء)');
        }
    }

    /**
     * The name broken into its parts.
     *
     * Splits on Unicode whitespace explicitly — `\s` under /u still only means
     * ASCII whitespace, and an Arabic keyboard produces non-breaking spaces and
     * direction marks that would otherwise glue two names into one token and
     * fail a name that is perfectly valid. Tatweel (ـ) is decoration and is
     * stripped rather than treated as a separator.
     *
     * @return array<int, string>
     */
    public static function parts(string $value): array
    {
        $normalised = preg_replace('/\x{0640}+/u', '', $value) ?? $value;
        $tokens = preg_split('/[\s\x{00A0}\x{200E}\x{200F}\x{202A}-\x{202E}]+/u', trim($normalised)) ?: [];

        return array_values(array_filter($tokens, fn ($t) => $t !== ''));
    }

    public static function isSatisfiedBy(?string $value): bool
    {
        return count(self::parts((string) $value)) >= self::MINIMUM_PARTS;
    }
}
