<?php

namespace KupShop\ArticlesBundle\Wrapper;

use Doctrine\Common\Collections\ArrayCollection;
use KupShop\FeedsBundle\Utils\FeedUtils;
use KupShop\FeedsBundle\Wrapper\BaseWrapper;
use KupShop\FeedsBundle\Wrapper\BlockWrapper;
use KupShop\FeedsBundle\Wrapper\BlockWrapperFactory;
use KupShop\FeedsBundle\Wrapper\MultiWrapper;
use KupShop\FeedsBundle\Wrapper\PhotoWrapper;
use KupShop\FeedsBundle\Wrapper\PhotoWrapperFactory;
use KupShop\I18nBundle\Translations\ArticlesSectionsTranslation;
use KupShop\I18nBundle\Translations\ArticlesTagsTranslation;
use KupShop\KupShopBundle\Util\StringUtil;
use Query\Operator;
use Query\Translation;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Service\Attribute\Required;

class ArticleWrapper extends BaseWrapper
{
    /** @var ArrayCollection */
    protected $articles;

    /** @var array */
    protected $feedRow;

    /** @var MultiWrapper */
    protected $blocksWrapper;

    /** @var PhotoWrapper */
    protected $photoWrapper;

    /** @var MultiWrapper */
    protected $photosWrapper;

    protected FeedUtils $feedUtils;

    public function __construct(
        BlockWrapper $blockWrapper,
        BlockWrapperFactory $blockWrapperFactory,
        PhotoWrapper $photoWrapper,
        PhotoWrapperFactory $photoWrapperFactory,
        FeedUtils $feedUtils,
    ) {
        $this->blocksWrapper = new MultiWrapper($blockWrapper, $blockWrapperFactory);
        $this->photoWrapper = $photoWrapper;
        $this->photosWrapper = new MultiWrapper($photoWrapper, $photoWrapperFactory);
        $this->feedUtils = $feedUtils;
    }

    #[Required]
    public function setBlockWrapper(BlockWrapper $blockWrapper): void
    {
        $this->blockWrapper = $blockWrapper;
    }

    /**
     * @param array|null $feedRow
     *
     * @private
     */
    public function setFeedRow($feedRow)
    {
        $this->feedRow = $feedRow;
    }

    /**
     * @private
     */
    public function setArticles(ArrayCollection $articles)
    {
        $this->articles = $articles;
    }

    /** @var array */
    protected $object;

    /** ID článku */
    public function field_id()
    {
        return $this->object->id ?? null;
    }

    /** URL odkaz */
    public function field_link()
    {
        return path('kupshop_content_articles_article_1', [
            'IDa' => $this->object->id,
            'slug' => StringUtil::slugify($this->object->title),
        ], UrlGeneratorInterface::ABSOLUTE_URL);
    }

    /** Štítky */
    public function field_tags()
    {
        if (!isset($this->articles->_tags_fetched)) {
            $qb = sqlQueryBuilder()->select('atr.id_article, at.id, at.tag')->from('articles_tags_relation', 'atr')
                ->innerJoin('atr', 'articles_tags', 'at', 'at.id=atr.id_tag')
                ->where(Operator::inIntArray($this->articles->getKeys(), 'atr.id_article'))
                ->andWhere(Translation::coalesceTranslatedFields(ArticlesTagsTranslation::class))
                ->groupBy('atr.id_article, at.tag')
                ->orderBy('atr.id_article, at.tag');
            foreach ($qb->execute() as $row) {
                if (isset($this->articles[$row['id_article']])) {
                    $this->articles[$row['id_article']]->_tags = $this->articles[$row['id_article']]->_tags ?? [];
                    $this->articles[$row['id_article']]->_tags[$row['id']] = $row['tag'];
                }
            }
            $this->articles->_tags_fetched = true;
        }

        return $this->object->_tags ?? [];
    }

    /** Sekce článků */
    public function field_sections()
    {
        if (!isset($this->articles->_sections_fetched)) {
            $qb = sqlQueryBuilder()->select('ar.id_art AS id_article, ab.id, ab.name, ab.descr')->from('articles_relation', 'ar')
                ->innerJoin('ar', 'articles_branches', 'ab', 'ab.id=ar.id_branch')
                ->where(Operator::inIntArray($this->articles->getKeys(), 'ar.id_art'))
                ->andWhere(Translation::coalesceTranslatedFields(ArticlesSectionsTranslation::class))
                ->groupBy('ar.id_art, ab.id')
                ->orderBy('ar.id_art, ab.id');
            foreach ($qb->execute() as $row) {
                if (isset($this->articles[$row['id_article']])) {
                    $this->articles[$row['id_article']]->_sections = $this->articles[$row['id_article']]->_sections ?? [];
                    $this->articles[$row['id_article']]->_sections[$row['id']] = $row['name'];
                }
            }
            $this->articles->_sections_fetched = true;
        }

        return $this->object->_sections ?? [];
    }

    /** @private */
    protected function fetchPhotos()
    {
        $this->feedUtils->fetchPhotos($this->articles, 'photos_articles_relation', 'id_art', 'article_thumb');
    }

    /** Hlavní obrázek */
    public function field_main_photo()
    {
        $this->fetchPhotos();

        return ($this->object->_main_photo['src'] ?? false) ? $this->photoWrapper->setObject($this->object->_main_photo) : null;
    }

    /** Ostatní obrázky */
    public function field_photos()
    {
        $this->fetchPhotos();

        return $this->photosWrapper->setObject($this->object->_photos ?? []);
    }

    /** Název článku */
    public function field_title()
    {
        return $this->object->title ?? null;
    }

    /** Klíčová slova */
    public function field_keywords()
    {
        return $this->object->keywords ?? null;
    }

    /** Anotace */
    public function field_lead_in()
    {
        return $this->object->lead_in ?? null;
    }

    /** Publikováno.
     *
     * Y - Viditelné
     * N - Skryté
     */
    public function field_visibility()
    {
        return $this->object->figure ?? null;
    }

    /** Datum publikace */
    public function field_date()
    {
        return $this->object->date ?? '';
    }

    /** Datum poslední úpravy */
    public function field_last_change_date()
    {
        if (!isset($this->articles->_last_change_date_fetched)) {
            $qb = sqlQueryBuilder()->select('a.id AS id_article, MAX(bh.date) AS last_change_date')
                ->from('articles', 'a')
                ->innerJoin('a', 'blocks_history', 'bh', 'bh.id_root_block=a.id_block')
                ->where(Operator::inIntArray($this->articles->getKeys(), 'a.id'))
                ->groupBy('a.id')
                ->orderBy('a.id');
            foreach ($qb->execute() as $row) {
                if (isset($this->articles[$row['id_article']])) {
                    $this->articles[$row['id_article']]->_last_change_date = $row['last_change_date'];
                }
            }
            $this->articles->_last_change_date_fetched = true;
        }

        return $this->object->_last_change_date ?? '';
    }

    /** Bloky (obsah) */
    public function field_blocks()
    {
        $this->feedUtils->fetchCollectionBlocks($this->articles);

        return !empty($this->object->_raw_blocks) ? $this->blocksWrapper->setObject($this->object->_raw_blocks) : [];
    }
}
