<?php

namespace App\Tests\Shared;

use App\Auth\Entity\User;
use App\Doctor\Entity\Doctor;
use App\Secretary\Entity\DoctorSecretary;
use App\Shared\Util\PersianText;
use App\Tests\ApiTestCase;

/**
 * Persian/Arabic digits sent by any client must never reach the database.
 * The admin SPA normalizes at the input, but nobat724_front and clinic-pro-tauri
 * hit the same endpoints, so the request layer is the real guarantee.
 */
class NumericFieldNormalizerTest extends ApiTestCase
{
    public function testDigitsHelperTranslatesWithoutStripping(): void
    {
        self::assertSame('09123456789', PersianText::digits('۰۹۱۲۳۴۵۶۷۸۹'));
        self::assertSame('0912', PersianText::digits('٠٩١٢'));
        self::assertSame('IR12-34', PersianText::digits('IR۱۲-۳۴'), 'letters and separators survive');
        self::assertSame('', PersianText::digits(''));
    }

    public function testSecretaryCreatedWithPersianDigitsIsStoredLatin(): void
    {
        $owner    = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
        $doctor   = new Doctor($owner, 'دکتر تست');
        $this->em->persist($doctor);
        $this->em->flush();

        // db_test پاک نمی‌شود؛ شماره باید تازه باشد وگرنه endpoint با «تکراری» رد می‌کند.
        do {
            $persianMobile = '۰۹' . str_pad((string) random_int(0, 999_999_999), 9, '۰', STR_PAD_LEFT);
            $latinMobile   = PersianText::digits($persianMobile);
        } while ($this->em->getRepository(User::class)->findOneBy(['mobileNumber' => $latinMobile]) !== null);

        $this->authJson('POST', '/api/v1/secretary', $owner, [
            'doctor_uuid'   => $doctor->getUuid(),
            'mobile_number' => $persianMobile,
            'name'          => 'منشی تست',
            'national_code' => '۰۰۱۲۳۴۵۶۷۸',
        ]);

        self::assertSame(201, $this->responseCode(), 'Persian digits must not break validation');

        $this->em->clear();
        $created = $this->em->getRepository(User::class)->findOneBy(['mobileNumber' => $latinMobile]);
        self::assertNotNull($created, 'user is stored under the latin mobile');

        $rel = $this->em->getRepository(DoctorSecretary::class)->findOneBy(['secretary' => $created]);
        self::assertSame('0012345678', $rel->getNationalCode());
    }

    public function testNestedArraysAreNormalized(): void
    {
        $user = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);

        $this->authJson('PUT', '/api/v1/insurance-pricing', $user, [
            'free_visit_price_rials' => '۵۰۰۰۰۰',
            'insurances'             => [
                ['insurance_id' => 1, 'patient_share_rials' => '۱۲۳۴۵'],
            ],
        ]);

        // پروفایل پزشک ممکن است بیمه‌ای نداشته باشد؛ مهم این است که ارقام فارسی
        // باعث خطای اعتبارسنجی یا NaN نشوند.
        self::assertNotSame(500, $this->responseCode(), 'nested persian digits must not blow up');
    }

    public function testNonNumericKeysKeepPersianDigits(): void
    {
        $owner  = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
        $doctor = new Doctor($owner, 'دکتر تست');
        $this->em->persist($doctor);
        $this->em->flush();

        $mobile = '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT);

        $this->authJson('POST', '/api/v1/secretary', $owner, [
            'doctor_uuid'   => $doctor->getUuid(),
            'mobile_number' => $mobile,
            'name'          => 'منشی شماره ۲',
        ]);
        self::assertSame(201, $this->responseCode());

        $this->em->clear();
        $created = $this->em->getRepository(User::class)->findOneBy(['mobileNumber' => $mobile]);
        self::assertStringContainsString('۲', $created->getRealName(), 'name is not a numeric field');
    }
}
