<?php

namespace App\Tests\Shared;

use App\Auth\Entity\User;
use App\Tests\ApiTestCase;
use Doctrine\ORM\EntityManagerInterface;

/**
 * ساختِ کاربر آزمون پس از تصادم شمارهٔ موبایل باید سالم ادامه بدهد.
 *
 * `db_test` هرگز ریست نمی‌شود و ده‌ها هزار کاربر دارد، پس قرعهٔ تصادفی گاهی تکراری
 * می‌شود. INSERT شکست‌خورده EntityManager را **می‌بندد**، و گرفتن دوبارهٔ آن از
 * کانتینر همان نمونهٔ بسته را برمی‌گرداند — تا وقتی رجیستری ریست نشود.
 *
 * تا پیش از این اصلاح، همین باعث می‌شد اجرای کامل به‌صورت متناوب روی یک تستِ
 * **بی‌ربط** با «EntityManager is closed» بیفتد.
 */
class UserCollisionRetryTest extends ApiTestCase
{
    public function testAClosedManagerIsReplacedNotReused(): void
    {
        $before = $this->em;

        // بستن عمدی: درج تکراری روی کلید یکتای موبایل.
        $existing = $this->createUser(['ROLE_USER']);

        try {
            $clash = new User($existing->getMobileNumber());
            $clash->setRoles(['ROLE_USER']);
            $clash->setStatus(1);
            $this->em->persist($clash);
            $this->em->flush();

            self::fail('درج تکراری باید شکست بخورد');
        } catch (\Throwable) {
            // همان چیزی که در قرعهٔ تصادفی اتفاق می‌افتد.
        }

        self::assertFalse($before->isOpen(), 'INSERT شکست‌خورده باید EntityManager را ببندد');

        static::getContainer()->get('doctrine')->resetManager();
        $this->em = static::getContainer()->get(EntityManagerInterface::class);

        // کانتینر یک proxy برمی‌گرداند، پس هویت شیء عوض نمی‌شود؛ چیزی که اهمیت دارد
        // این است که پشتِ همان proxy یک EntityManager **باز** نشسته باشد.
        self::assertTrue($this->em->isOpen(), 'پس از ریست رجیستری باید مدیر باز باشد');

        // و کار عادی باید ادامه پیدا کند.
        $fresh = $this->createUser(['ROLE_USER']);
        self::assertNotNull($fresh->getId());
    }
}
