<?php declare(strict_types=1);


namespace Newland\Toubiz\Sync\Neos\Tests\Unit\Orm\Uuid;


use Doctrine\Entity;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Neos\Flow\Tests\FunctionalTestCase;
use Newland\Toubiz\Sync\Neos\Orm\Uuid\UuidGenerator;
use Newland\Toubiz\Sync\Neos\Tests\Unit\Orm\Uuid\Fixtures\MockWithCustomUuidGeneration;
use Newland\Toubiz\Sync\Neos\Tests\Unit\Orm\Uuid\Fixtures\MockWithoutCustomUuidGeneration;
use Ramsey\Uuid\Uuid;

class UuidGeneratorTest extends FunctionalTestCase
{

    /** @var UuidGenerator */
    private $uuidGenerator;

    /** @var EntityManager */
    private $entityManager;

    public function setUp(): void
    {
        parent::setUp();
        $this->uuidGenerator = $this->objectManager->get(UuidGenerator::class);
        $this->entityManager = $this->objectManager->get(EntityManagerInterface::class);
    }

    public function testUsesUuidReturnedByGeneratorMethod(): void
    {
        $uuid = Uuid::uuid4();

        // Create one entity with this uuid
        $firstEntity = new MockWithCustomUuidGeneration();
        $firstEntity->uuidThatWillBeGenerated = $uuid;
        $firstGenerated = $this->uuidGenerator->generate($this->entityManager, $firstEntity);
        $this->assertTrue(Uuid::isValid($firstGenerated));
        $this->assertEquals($uuid->toString(), $firstGenerated);
        $this->assertEquals(1, $firstEntity->generateUuidCalls);

        // Create another one
        $secondEntity = new MockWithCustomUuidGeneration();
        $secondEntity->uuidThatWillBeGenerated = $uuid;
        $secondGenerated = $this->uuidGenerator->generate($this->entityManager, $secondEntity);
        $this->assertTrue(Uuid::isValid($secondGenerated));
        $this->assertEquals($uuid->toString(), $secondGenerated);
        $this->assertEquals(1, $secondEntity->generateUuidCalls);

        // It should be the same
        $this->assertEquals($firstGenerated, $secondGenerated);
    }

    public function testGeneratesRandomUuidIfNoneAvailable(): void
    {
        $firstGenerated = $this->uuidGenerator->generate($this->entityManager, new MockWithoutCustomUuidGeneration());
        $this->assertTrue(Uuid::isValid($firstGenerated));

        $secondGenerated = $this->uuidGenerator->generate($this->entityManager, new MockWithoutCustomUuidGeneration());
        $this->assertTrue(Uuid::isValid($secondGenerated));

        $this->assertNotEquals($firstGenerated, $secondGenerated);
    }

    public function testExposesStaticHelperForGeneratingReproducibleUuids(): void
    {
        $first = UuidGenerator::uuidFromProperties([ 'foo', 'bar' ])->toString();
        $this->assertTrue(Uuid::isValid($first));

        $second = UuidGenerator::uuidFromProperties([ 'foo', 'bar' ])->toString();
        $this->assertTrue(Uuid::isValid($second));

        $third = UuidGenerator::uuidFromProperties([ 'foo', 'bar', 'baz' ])->toString();
        $this->assertTrue(Uuid::isValid($third));

        $this->assertEquals($first, $second);
        $this->assertNotEquals($first, $third);
    }
}