<?php

namespace Tests\Feature;

use App\Domain\Identity\Rules\FullName;
use App\Livewire\Receptionist\NewRegistrationWizard;
use App\Models\User;
use Illuminate\Support\Facades\Validator;
use PHPUnit\Framework\Attributes\DataProvider;
use Livewire\Livewire;
use Tests\TestCase;

/**
 * Everybody entered into the system carries a four-part name.
 *
 * The rule itself is exercised directly — including the Arabic typing that
 * naive splitting gets wrong — and then at the one screen that creates the most
 * people, to prove the rule is actually wired to the step and not merely
 * defined.
 */
class FullNameRuleTest extends TestCase
{
    /** @return array<string, array{0: string, 1: bool}> */
    public static function names(): array
    {
        return [
            'two parts' => ['محمد أحمد', false],
            'three parts' => ['محمد أحمد علي', false],
            'four parts' => ['محمد أحمد علي حسن', true],
            'five parts' => ['محمد أحمد علي حسن إبراهيم', true],
            'four parts, padded' => ['  محمد   أحمد  علي حسن  ', true],
            'latin four parts' => ['Mohamed Ahmed Ali Hassan', true],
            'empty' => ['', false],
            'one long part' => ['محمدأحمدعليحسن', false],
        ];
    }

    #[DataProvider('names')]
    public function test_the_rule_counts_name_parts(string $name, bool $expected): void
    {
        $this->assertSame($expected, FullName::isSatisfiedBy($name), $name);
    }

    public function test_a_non_breaking_space_still_separates_two_names(): void
    {
        // An Arabic keyboard produces U+00A0, and \s under /u does not match it.
        // Glued together, a perfectly valid four-part name would be rejected.
        $name = "محمد\u{00A0}أحمد علي حسن";

        $this->assertCount(4, FullName::parts($name));
        $this->assertTrue(FullName::isSatisfiedBy($name));
    }

    public function test_tatweel_is_decoration_not_a_separator(): void
    {
        $this->assertCount(4, FullName::parts('محمـــد أحمد علي حسن'));
    }

    public function test_the_rule_fails_with_an_arabic_message(): void
    {
        $validator = Validator::make(
            ['name' => 'محمد أحمد'],
            ['name' => [new FullName]]
        );

        $this->assertTrue($validator->fails());
        $this->assertStringContainsString('رباعي', $validator->errors()->first('name'));
    }

    public function test_the_registration_wizard_refuses_a_three_part_player_name(): void
    {
        if (config('database.default') !== 'pgsql') {
            $this->markTestSkipped('Needs a restored Postgres tenant.');
        }

        $academy = \App\Domain\Shared\Models\Academy::query()->first();
        if (! $academy) {
            $this->markTestSkipped('No academy in the restored tenant.');
        }
        app()->instance('current_academy', $academy);

        $owner = User::withoutGlobalScopes()
            ->whereHas('primaryRole', fn ($q) => $q->where('slug', 'academy_owner'))
            ->first();

        if (! $owner) {
            $this->markTestSkipped('No academy_owner in the restored tenant.');
        }

        Livewire::actingAs($owner)
            ->test(NewRegistrationWizard::class)
            ->set('participant_name_ar', 'محمد أحمد علي')
            ->set('participant_date_of_birth', '2015-01-01')
            ->set('participant_gender', 'male')
            ->set('membership_type', 'non_member')
            ->call('nextStep')
            ->assertHasErrors('participant_name_ar')
            ->assertSet('currentStep', 1);
    }
}
