<?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\Bridge\Symfony\Bundle\Twig\Components\News;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\Components\Behavior\HasTemplateOverride;
use CpCreation\VitiCore\Media\Model\Image;
use CpCreation\VitiCore\News\Model\News;
use CpCreation\VitiCore\News\Repository\NewsRepository;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\Query\Expr\Join;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Exception\ExceptionInterface as RoutingExceptionInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;

#[AsTwigComponent('news:Detail', template: '@components/news/Detail.html.twig')]
final class Detail
{
    use HasTemplateOverride;

    public ?News $news = null;
    public ?string $slug = null;
    public ?string $backRoute = 'news';

    private bool $resolved = false;
    private ?News $resolvedNews = null;

    public function __construct(
        private readonly NewsRepository $newsRepository,
        private readonly RequestStack $requestStack,
        private readonly UrlGeneratorInterface $urlGenerator,
    ) {
    }

    public function getItem(): ?News
    {
        if ($this->resolved) {
            return $this->resolvedNews;
        }

        $this->resolved = true;

        if (null !== $this->news) {
            return $this->resolvedNews = $this->news;
        }

        $slug = $this->slug ?? $this->requestStack->getCurrentRequest()?->attributes->getString('slug');

        if (null === $slug || '' === mb_trim($slug)) {
            return null;
        }

        $queryBuilder = $this->newsRepository
            ->createQueryBuilder('news')
            ->addSelect('translation')
            ->innerJoin('news.translations', 'translation', Join::WITH, 'translation.translatable = news.id')
            ->andWhere('translation.slug = :slug')
            ->andWhere('news.unPublishedAt >= :date OR news.unPublishedAt IS NULL')
            ->andWhere('news.publishedAt <= :date OR news.publishedAt IS NULL')
            ->andWhere('news.disabled = FALSE')
            ->setMaxResults(1)
            ->setParameter('slug', $slug)
            ->setParameter('date', new \DateTimeImmutable());

        try {
            $news = $queryBuilder->getQuery()->getOneOrNullResult();
        } catch (NonUniqueResultException) {
            $news = null;
        }

        return $this->resolvedNews = $news instanceof News ? $news : null;
    }

    public function getPrimaryImage(): ?Image
    {
        $news = $this->getItem();

        if (null === $news) {
            return null;
        }

        foreach ($news->getImages() as $newsImage) {
            $image = $newsImage->getImage();

            if (null !== $image && null !== $image->getPath()) {
                return $image;
            }
        }

        return null;
    }

    public function getBackUrl(): ?string
    {
        if (null === $this->backRoute || '' === mb_trim($this->backRoute)) {
            return null;
        }

        try {
            return $this->urlGenerator->generate($this->backRoute);
        } catch (RoutingExceptionInterface) {
            return null;
        }
    }
}
