<?php declare(strict_types=1);

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

use Neos\Flow\Tests\FunctionalTestCase;
use Newland\Toubiz\Sync\Neos\Domain\Model\Event;
use Newland\Toubiz\Sync\Neos\Tests\Factory\EventDateFactory;
use Newland\Toubiz\Sync\Neos\Tests\Factory\EventFactory;

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

    /** @var bool */
    protected $initialized;

    /** @var Event */
    protected $event;

    public function setUp(): void
    {
        parent::setUp();
        if (!$this->initialized) {
            $this->event = (new EventFactory($this->objectManager))->create([ 'client' => 'san flamingo' ]);
        }
    }

    /**
     * @dataProvider provideDeterministicIds
     * @param string $expectedId
     * @param array $properties
     */
    public function testDeterministicIdsAreGeneratedCorrectly(string $expectedId, array $properties): void
    {
        $properties['event'] = $this->event;

        self::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 {
        $properties['event'] = $this->event;
        $eventDate = (new EventDateFactory($this->objectManager))->create($properties);

        self::assertEquals(
            $expectedId,
            $eventDate->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($eventDate);
        $this->persistenceManager->persistAll();
    }

    public function provideDeterministicIds(): array
    {
        return [
            'baseDate' => [
                '824be231-8afc-5d6d-ac61-7f4d295f7ca4',
                [
                    'language' => 'de',
                    'originalId' => 'lalala',
                    'note' => 'First note',
                ],
            ],
            'sameAsBaseButDifferentNote: Should have same identifier' => [
                '824be231-8afc-5d6d-ac61-7f4d295f7ca4',
                [
                    'language' => 'de',
                    'originalId' => 'lalala',
                    'note' => 'Same basic event date as before but with different note.',
                ],
            ],
            'languageChanged' => [
                'ebe78761-c5c5-5ea2-b63a-2311c907bb93',
                [
                    'language' => 'en',
                    'originalId' => 'lalala',
                ],
            ],
            'originalIdChanged' => [
                'a79b685e-502c-5c8c-bcab-4506d228a939',
                [
                    'language' => 'de',
                    'originalId' => 'blablabla',
                ],
            ],
            'orignalIdChanged' => [
                '6fc311c5-0cf9-5dd4-a82e-972246a255cc',
                [
                    '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 ],
        ];
    }
}
