<?php declare(strict_types=1);


namespace Newland\Toubiz\Sync\Neos\Tests\Unit\Domain\Model;


use Neos\Flow\Tests\FunctionalTestCase;
use Newland\Toubiz\Sync\Neos\Tests\Factory\EventDateFactory;

class EventDateTest extends FunctionalTestCase
{
    protected static $testablePersistenceEnabled = true;

    /**
     * @dataProvider provideDeterministicIds
     * @param string $expectedId
     * @param array $properties
     */
    public function testDeterministicIdsAreGeneratedCorrectly(string $expectedId, array $properties): void
    {
        $this->assertEquals(
            $expectedId,
            (new EventDateFactory($this->objectManager))->make($properties)->generateUuid()->toString(),
            'persistence object identifier should be stable: If this test fails then the'
            . ' way ids are being generated has probably changed and old identifiers need to be migrated'
            . ' to this new style.'
        );
    }

    /**
     * @dataProvider provideDeterministicIds
     * @param string $expectedId
     * @param array $properties
     */
    public function testDeterministicIdsAreAutomaticallyGeneratedWhenStoringInDatabase(
        string $expectedId,
        array $properties
    ): void {
        /** @var Event $event */
        $event = (new EventDateFactory($this->objectManager))->create($properties);

        $this->assertEquals(
            $expectedId,
            $event->getPersistenceObjectIdentifier(),
            'persistence object identifier should be stable: If this test fails then the'
            . ' way ids are being generated has probably changed and old identifiers need to be migrated'
            . ' to this new style.'
        );

        // Entity is explicitly deleted to avoid id collisions.
        $this->persistenceManager->remove($event);
        $this->persistenceManager->persistAll();
    }

    /**
     * @dataProvider provideAllDayTimes
     */
    public function testIfEventIsAllDay(\DateTime $beginsAt, \DateTime $endsAt, bool $allDay): void
    {
        $eventDate = (new EventDateFactory($this->objectManager))->create(
            [
                'beginsAt' => $beginsAt,
                'endsAt' => $endsAt,
            ]
        );

        $this->assertEquals($allDay, $eventDate->isAllDay());
    }

    public function provideDeterministicIds(): array
    {
        return [
            'baseDate' => [
                'd8dfa07e-568d-575b-888a-277a603eaa7a',
                [
                    'language' => 'de',
                    'originalId' => 'lalala',
                    'note' => 'First note',
                ],
            ],
            'sameAsBaseButDifferentNote: Should have same identifier' => [
                'd8dfa07e-568d-575b-888a-277a603eaa7a',
                [
                    'language' => 'de',
                    'originalId' => 'lalala',
                    'note' => 'Same basic event date as before but with different note.',
                ],
            ],
            'languageChanged' => [
                '12530010-5515-5d6f-9b1f-cf98a4b53d6e',
                [
                    'language' => 'en',
                    'originalId' => 'lalala',
                ],
            ],
            'originalIdChanged' => [
                '6e468d94-973c-5b7b-bad9-fd8a36a1375d',
                [
                    'language' => 'de',
                    'originalId' => 'blablabla',
                ],
            ],
            'orignalIdChanged' => [
                '5b71f71f-459c-5bb3-afad-5adc9ff42ac1',
                [
                    'language' => 'fr',
                    'originalId' => 'foooooo',
                ],
            ],
        ];
    }

    public function provideAllDayTimes(): array
    {
        return [
            [ new \DateTime('2018-01-01 00:00:00'), new \DateTime('2018-01-01 00:00:00'), true ],
            [ new \DateTime('2018-01-01 00:00:00'), new \DateTime('2018-01-02 00:00:00'), true ],
            [ new \DateTime('2018-01-01 00:00:00'), new \DateTime('2018-01-01 00:01:00'), false ],
            [ new \DateTime('2018-01-01 00:01:00'), new \DateTime('2018-01-02 00:00:00'), false ],
            // Multi-day events with specific start or end times are _not_ considered all-day events.
            [ new \DateTime('2018-01-01 15:00:00'), new \DateTime('2018-01-03 23:00:00'), false ],
        ];
    }
}
