<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\Tests\Repository\Identifier;

use Chill\PersonBundle\Entity\Identifier\PersonIdentifier;
use Chill\PersonBundle\Entity\Identifier\PersonIdentifierDefinition;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\PersonIdentifier\Identifier\StringIdentifier;
use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface;
use Chill\PersonBundle\Repository\Identifier\PersonIdentifierRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @internal
 *
 * @coversNothing
 */
class PersonIdentifierRepositoryTest extends KernelTestCase
{
    public function testFindByDefinitionAndCanonical(): void
    {
        self::bootKernel();
        $container = self::getContainer();
        /** @var PersonIdentifierManagerInterface $personIdentifierManager */
        $personIdentifierManager = $container->get(PersonIdentifierManagerInterface::class);

        /** @var EntityManagerInterface $em */
        $em = $container->get(EntityManagerInterface::class);

        // Get a random existing person from fixtures
        /** @var Person|null $person */
        $person = $em->getRepository(Person::class)->findOneBy([]);
        self::assertNotNull($person, 'An existing Person is required for this integration test.');

        // Create a definition
        $definition = new PersonIdentifierDefinition(['en' => 'Test Identifier'], StringIdentifier::NAME);
        $em->persist($definition);
        $em->flush();

        // Create an identifier attached to the person
        $value = ['content' => 'ABC-'.bin2hex(random_bytes(4))];
        $identifier = new PersonIdentifier($definition);
        $identifier->setPerson($person);
        $identifier->setValue($value);
        $identifier->setCanonical($personIdentifierManager->buildWorkerByPersonIdentifierDefinition($definition)->canonicalizeValue($identifier->getValue()));
        $em->persist($identifier);
        $em->flush();

        // Use the repository to find by definition and value
        /** @var PersonIdentifierRepository $repo */
        $repo = $container->get(PersonIdentifierRepository::class);
        $results = $repo->findByDefinitionAndCanonical($definition, $value);

        self::assertNotEmpty($results, 'Repository should return at least one result.');
        self::assertContainsOnlyInstancesOf(PersonIdentifier::class, $results);
        self::assertTrue(in_array($identifier->getId(), array_map(static fn (PersonIdentifier $pi) => $pi->getId(), $results), true));

        // Cleanup
        foreach ($results as $res) {
            $em->remove($res);
        }
        $em->flush();
        $em->remove($definition);
        $em->flush();
    }
}
