<?php

namespace Tests\Unit;

use App\Domain\Shared\Support\ArabicSearch;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

/**
 * Finding a child by name, the way people actually type it.
 *
 * Every pair below is a real name from a production academy and a search that
 * failed against it before this existed.
 */
class ArabicSearchTest extends TestCase
{
    private const NAME = 'عبدالله أحمد صلاح سيد';

    #[DataProvider('termsThatMustFind')]
    public function test_a_name_is_found_however_it_is_typed(string $term): void
    {
        $this->assertTrue(ArabicSearch::matches(self::NAME, $term), "[{$term}] should find the name");
    }

    public static function termsThatMustFind(): array
    {
        return [
            'exactly as stored' => ['عبدالله أحمد صلاح سيد'],
            'without the hamza' => ['عبدالله احمد'],
            'two words that are not adjacent' => ['عبدالله صلاح'],
            'the last two words' => ['صلاح سيد'],
            'one word' => ['صلاح'],
            'extra spaces' => ['  عبدالله    سيد '],
            'reversed order' => ['سيد عبدالله'],
        ];
    }

    public function test_a_different_child_is_not_found(): void
    {
        $this->assertFalse(ArabicSearch::matches(self::NAME, 'عبدالرحمن'));
        $this->assertFalse(ArabicSearch::matches(self::NAME, 'عبدالله فريد'));
    }

    #[DataProvider('spellingPairs')]
    public function test_spelling_variants_fold_together(string $a, string $b): void
    {
        $this->assertSame(ArabicSearch::normalise($a), ArabicSearch::normalise($b));
    }

    public static function spellingPairs(): array
    {
        return [
            'hamza on alef' => ['أحمد', 'احمد'],
            'hamza under alef' => ['إبراهيم', 'ابراهيم'],
            'madda' => ['آدم', 'ادم'],
            'ta marbuta' => ['حمزة', 'حمزه'],
            'alef maqsura' => ['يحيى', 'يحيي'],
            'hamza on ya' => ['سائد', 'سايد'],
            'tashkeel' => ['مُحَمَّد', 'محمد'],
            'arabic-indic digits' => ['٠١٠٠٣٠٥٥٥١', '0100305551'],
        ];
    }

    public function test_an_empty_term_matches_everything(): void
    {
        // An empty search box must not filter the list to nothing.
        $this->assertSame([], ArabicSearch::words(''));
        $this->assertTrue(ArabicSearch::matches(self::NAME, ''));
    }
}
