<?php

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Tests\Product\Model;

use CpCreation\VitiCore\Product\Model\ProductCollection;
use CpCreation\VitiCore\Product\Model\ProductCollectionItem;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class ProductCollectionTest extends TestCase
{
    public function testManualCollectionCanBeCreatedWithoutItems(): void
    {
        $collection = new ProductCollection();
        $collection->setName('Sélection à venir');

        self::assertCount(0, $this->createValidator()->validate($collection));
    }

    public function testPublicationPeriodIsOptional(): void
    {
        $collection = new ProductCollection();

        self::assertTrue($collection->isCurrentlyPublished(new \DateTimeImmutable('2026-07-22 12:00:00')));
    }

    public function testPublicationStartsAtConfiguredDate(): void
    {
        $collection = new ProductCollection();
        $collection->setPublishedAt(new \DateTimeImmutable('2026-07-22 12:00:00'));

        self::assertFalse($collection->isCurrentlyPublished(new \DateTimeImmutable('2026-07-22 11:59:59')));
        self::assertTrue($collection->isCurrentlyPublished(new \DateTimeImmutable('2026-07-22 12:00:00')));
    }

    public function testPublicationEndsAtConfiguredDate(): void
    {
        $collection = new ProductCollection();
        $collection->setUnPublishedAt(new \DateTimeImmutable('2026-07-22 18:00:00'));

        self::assertTrue($collection->isCurrentlyPublished(new \DateTimeImmutable('2026-07-22 18:00:00')));
        self::assertFalse($collection->isCurrentlyPublished(new \DateTimeImmutable('2026-07-22 18:00:01')));
    }

    public function testPublicationEndMustBeAfterStart(): void
    {
        $collection = new ProductCollection();
        $collection->setName('Sélection temporaire');
        $collection->setPublishedAt(new \DateTimeImmutable('2026-07-22 18:00:00'));
        $collection->setUnPublishedAt(new \DateTimeImmutable('2026-07-22 12:00:00'));

        $violations = $this->createValidator()->validate($collection);

        self::assertCount(1, $violations);
        self::assertSame('unPublishedAt', $violations[0]->getPropertyPath());
    }

    public function testItemPositionsAreNormalizedFromSubmittedOrder(): void
    {
        $collection = new ProductCollection();
        $first = new ProductCollectionItem();
        $first->setPosition(2);
        $second = new ProductCollectionItem();
        $second->setPosition(0);
        $third = new ProductCollectionItem();
        $third->setPosition(0);
        $last = new ProductCollectionItem();

        $collection->addItem($first);
        $collection->addItem($second);
        $collection->addItem($third);
        $collection->addItem($last);
        $collection->normalizeItemPositions();

        self::assertSame(2, $first->getPosition());
        self::assertSame(0, $second->getPosition());
        self::assertSame(1, $third->getPosition());
        self::assertSame(3, $last->getPosition());
    }

    private function createValidator(): ValidatorInterface
    {
        $uniqueEntityValidator = new class extends ConstraintValidator {
            public function validate(mixed $value, Constraint $constraint): void
            {
            }
        };

        return Validation::createValidatorBuilder()
            ->enableAttributeMapping()
            ->setConstraintValidatorFactory(new ConstraintValidatorFactory([
                new UniqueEntity(fields: 'code')->validatedBy() => $uniqueEntityValidator,
            ]))
            ->getValidator();
    }
}
