<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Marketing;

use CpCreation\VitiCore\Marketing\Model\ProductReview;
use CpCreation\VitiCore\Marketing\ProductReviewConfigurationProvider;
use CpCreation\VitiCore\Marketing\ProductReviewRatingSummary;
use CpCreation\VitiCore\Marketing\Repository\ProductReviewRepository;
use CpCreation\VitiCore\Product\Model\Product;
use Knp\Component\Pager\Pagination\PaginationInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('marketing:ProductReviews', template: '@components/marketing/ProductReviews.html.twig')]
final class ProductReviews
{
    public Product $product;

    public int $page = 1;

    public bool $livePagination = false;

    /** @var PaginationInterface<int, ProductReview>|null */
    private ?PaginationInterface $reviews = null;

    private bool $ratingSummaryLoaded = false;

    private ?ProductReviewRatingSummary $ratingSummary = null;

    public function __construct(
        private readonly ProductReviewRepository $reviewRepository,
        private readonly ProductReviewConfigurationProvider $configurationProvider,
        private readonly PaginatorInterface $paginator,
        private readonly RequestStack $requestStack,
    ) {}

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

    /** @return PaginationInterface<int, ProductReview> */
    public function getReviews(): PaginationInterface
    {
        if (null !== $this->reviews) {
            return $this->reviews;
        }

        $page = $this->livePagination
            ? max(1, $this->page)
            : max(1, $this->requestStack->getMainRequest()?->query->getInt('review_page', 1) ?? 1);

        return $this->reviews = $this->paginator->paginate(
            $this->reviewRepository->createPublishedByProductQueryBuilder(
                $this->product,
                new \DateTimeImmutable(),
            )->orderBy('review.publishedAt', 'DESC'),
            $page,
            10,
            ['pageParameterName' => 'review_page'],
        );
    }

    public function getAverageRating(): ?float
    {
        return $this->getRatingSummary()?->ratingValue;
    }

    public function getReviewCount(): int
    {
        return $this->getRatingSummary()?->reviewCount ?? 0;
    }

    /** @return array<int, int> */
    public function getRatingCounts(): array
    {
        return $this->getRatingSummary()?->ratingCounts ?? [];
    }

    public function isModerationEnabled(): bool
    {
        return $this->configurationProvider->isModerationRequired();
    }

    private function getRatingSummary(): ?ProductReviewRatingSummary
    {
        if (!$this->ratingSummaryLoaded) {
            $this->ratingSummary = $this->reviewRepository->getPublishedRatingSummary($this->product);
            $this->ratingSummaryLoaded = true;
        }

        return $this->ratingSummary;
    }
}
