<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Twig;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\ProductReviewSeoExtension;
use CpCreation\VitiCore\Marketing\ProductReviewConfigurationProvider;
use CpCreation\VitiCore\Marketing\ProductReviewRatingSummary;
use CpCreation\VitiCore\Marketing\PublishedProductReviewRatingProvider;
use CpCreation\VitiCore\Product\Model\Product;
use PHPUnit\Framework\TestCase;

final class ProductReviewSeoExtensionTest extends TestCase
{
    public function testBuildsAggregateRatingFromThePublishedReviewSummary(): void
    {
        $summary = new ProductReviewRatingSummary(reviewCount: 7, ratingValue: 4.428571);
        $extension = new ProductReviewSeoExtension(
            $this->providerReturning($summary),
            $this->configuration(enabled: true),
        );

        $schema = $extension->getAggregateRating(new Product());

        self::assertSame([
            '@type' => 'AggregateRating',
            'ratingValue' => 4.43,
            'reviewCount' => 7,
            'bestRating' => 5,
            'worstRating' => 1,
        ], $schema);
    }

    public function testDoesNotExposeAggregateRatingWithoutPublicReviews(): void
    {
        $extension = new ProductReviewSeoExtension(
            $this->providerReturning(null),
            $this->configuration(enabled: true),
        );

        self::assertNull($extension->getAggregateRating(new Product()));
    }

    public function testDoesNotExposeAggregateRatingWhenReviewsAreDisabled(): void
    {
        $extension = new ProductReviewSeoExtension(
            $this->providerReturning(new ProductReviewRatingSummary(reviewCount: 7, ratingValue: 4.5)),
            $this->configuration(enabled: false),
        );

        self::assertNull($extension->getAggregateRating(new Product()));
    }

    private function providerReturning(
        ?ProductReviewRatingSummary $summary,
    ): PublishedProductReviewRatingProvider {
        return new class ($summary) implements PublishedProductReviewRatingProvider {
            public function __construct(
                private readonly ?ProductReviewRatingSummary $summary,
            ) {}

            public function getPublishedRatingSummary(
                Product $product,
                ?\DateTimeImmutable $now = null,
            ): ?ProductReviewRatingSummary {
                return $this->summary;
            }
        };
    }

    private function configuration(bool $enabled): ProductReviewConfigurationProvider
    {
        return new class ($enabled) implements ProductReviewConfigurationProvider {
            public function __construct(private readonly bool $enabled) {}

            public function isEnabled(): bool
            {
                return $this->enabled;
            }

            public function isModerationRequired(): bool
            {
                return true;
            }
        };
    }
}
