<?php

namespace KupShop\ComponentsBundle\Twig\Components\Product;

use KupShop\CDNBundle\CDN;
use KupShop\ComponentsBundle\Entity\Thumbnail;
use KupShop\ComponentsBundle\GTM\PostMount\GTMClickData;
use KupShop\ComponentsBundle\Interfaces\GalleryPhoto;
use KupShop\ComponentsBundle\Interfaces\Microdata;
use KupShop\ComponentsBundle\Twig\BaseComponent;
use KupShop\ComponentsBundle\Twig\DataProvider\MicrodataProvider;
use KupShop\ComponentsBundle\Twig\DataProvider\ProductDataTrait;
use KupShop\ContentBundle\Util\ImageLocator;
use KupShop\I18nBundle\Translations\PhotosTranslation;
use KupShop\KupShopBundle\Util\System\UrlFinder;
use Query\Operator;
use Query\Translation;
use Symfony\Contracts\Service\Attribute\Required;

class Gallery extends BaseComponent implements Microdata
{
    use ProductDataTrait;
    use GTMClickData;

    #[Required]
    public \KupShop\ComponentsBundle\GTM\Events\ProductPhotoClick $gtmClass;

    public bool $isOld = false;

    /** @var GalleryPhoto[] */
    protected array $photos;

    public function __construct(
        protected ImageLocator $imageLocator,
        protected CDN $cdn,
        protected readonly UrlFinder $urlFinder,
    ) {
    }

    /** @return GalleryPhoto[] */
    public function getPhotos()
    {
        return $this->fetchPhotos();
    }

    /** @return GalleryPhoto */
    public function getMainPhoto(): array
    {
        $photos = $this->fetchPhotos();

        return reset($photos);
    }

    /** @return GalleryPhoto[] */
    public function getOtherPhotos(): array
    {
        $photos = $this->fetchPhotos();

        return array_slice($photos, 1);
    }

    public function fetchThumbnailLargeUrl(Thumbnail $thumbnail): string
    {
        return $this->imageLocator->getThumbnailUrl($thumbnail, 'product_large', 'desktop');
    }

    public function fetchThumbnailUrl(Thumbnail $thumbnail): string
    {
        return $this->imageLocator->getThumbnailUrl($thumbnail, 'product_gallery_thumb', 'desktop');
    }

    public function fetchVideoLargeUrl(string $id_video, bool $autoplay = true): string
    {
        return $this->cdn->getIframeUrl($id_video, $autoplay);
    }

    /** @return GalleryPhoto[] */
    protected function fetchPhotos(): array
    {
        if (!isset($this->photos)) {
            $qb = sqlQueryBuilder()
                ->select('ph.id, ph.descr, ph.date_update, MAX(ppr.show_in_lead) as show_in_lead')
                ->from('photos_products_relation', 'ppr')
                ->leftJoin('ppr', 'photos', 'ph', 'ppr.id_photo = ph.id')
                ->andWhere(Translation::coalesceTranslatedFields(PhotosTranslation::class, ['descr']))
                ->andWhere(Operator::equals([
                    'ppr.id_product' => $this->product->id,
                    'ppr.active' => 'Y',
                ]))
                ->groupBy('ph.id')
                ->setParameter('id_product', $this->product->id)
                ->orderBy('position', 'ASC');

            if (findModule(\Modules::PRODUCTS_VARIATIONS_PHOTOS)) {
                $qb->addSelect('JSON_OBJECTAGG(ppr.id_variation, ppr.show_in_lead) as variations');
            }

            if (findModule(\Modules::VIDEOS)) {
                $qb->addSelect('id_cdn id_video')
                    ->leftJoin('ph', 'videos', 'v', 'v.id_photo = ph.id');
            }

            $this->photos = [];
            foreach ($qb->execute() as $row) {
                $this->photos[] = [
                    'thumbnail' => new Thumbnail(
                        $row['id'],
                        $row['descr'],
                        $row['date_update'],
                    ),
                    'variations' => $row['variations'] ?? null,
                    'kind' => $row['show_in_lead'],
                    'id_video' => $row['id_video'] ?? null,
                ];
            }
        }

        $product = $this->provider->getProduct($this->product->id);
        if ($this->photos[0] ?? false) {
            $product->thumbnail = $this->photos[0]['thumbnail'];
        }

        return $this->photos;
    }

    public function initMicrodata(): array
    {
        if (!$this->getPhotos()) {
            return [];
        }

        return [
            MicrodataProvider::PRODUCT => [
                'image' => array_map(function ($photo) {
                    return $this->urlFinder->shopUrlAbsolute(getImagePath($photo['thumbnail']->id, 'producer'));
                }, $this->getPhotos()),
            ],
        ];
    }
}
