<?php

declare(strict_types=1);

namespace KupShop\ArticlesBundle\Twig\Components;

use KupShop\ArticlesBundle\Twig\Components\Articles\Utils\ArticleTrait;
use KupShop\ComponentsBundle\Attributes\Component;
use KupShop\ComponentsBundle\Attributes\Version;
use KupShop\ComponentsBundle\Twig\BaseComponent;
use KupShop\ContentBundle\Util\ArticleList;
use KupShop\ContentBundle\Util\ArticlesUtil;
use Query\Operator;
use Query\QueryBuilder;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
use Symfony\UX\TwigComponent\Attribute\PostMount;

#[AsTwigComponent(template: '@Articles/components/ArticlesList/ArticlesList.1.html.twig')]
#[Component(1, [
    new Version(1, newJs: null),
])]
class ArticlesList extends BaseComponent
{
    use ArticleTrait {
        getTopArticles as getBaseTopArticles;
    }

    public ?string $title = null;
    public int $limit = 0;
    public int $offset = 0;
    public bool $loadTopArticles = false;
    public bool $loadRelatedArticles = false;
    public ?int $idArticleSection = null;
    public ?int $idArticle = null;
    public ?string $title_class = 'h2';
    public ?int $id_branch = null;
    public ?int $id_tag = null;
    public ?\Pager $pager = null;

    protected array $specs;
    protected array $articles;
    protected ?array $settings_branch = null;

    public function __construct(protected ArticleList $articleList, private readonly ArticlesUtil $articlesUtil)
    {
    }

    public function getArticles(): array
    {
        if (!isset($this->articles)) {
            if ($this->loadTopArticles) {
                $this->articles = $this->getTopArticles()['articles'];
            } else {
                $this->articleList->setImage('photo');
                $this->articles = $this->articleList->getArticles(Operator::andX($this->getSpecs()));
            }
        }

        return $this->articles;
    }

    public function addSpec($spec): void
    {
        $this->specs[] = $spec;
    }

    public function getSpecs(): array
    {
        if (!isset($this->specs)) {
            $this->specs = [];
            $this->addLimitOffsetSpec();
            $this->addOrderSpec();
            $this->addBehaviourSpecs();
            $this->addTagSpec();
            $this->addFilterRelatedSpec();
        }

        return $this->specs;
    }

    public function addFilterRelatedSpec(): array
    {
        if ($this->loadRelatedArticles) {
            $this->addSpec(function (QueryBuilder $qb) {
                $relatedArticlesIds = sqlQueryBuilder()
                    ->select('id_article_related, position')
                    ->from('articles_related')
                    ->andWhere(Operator::equals(['id_article' => $this->idArticle]))
                    ->orderBy('position', 'ASC');
                $qb->leftJoinSubQuery('a', $relatedArticlesIds, 'arel', 'arel.id_article_related = a.id')
                    ->andWhere('arel.id_article_related IS NOT NULL')
                    ->orderBy('arel.position', 'ASC')
                    ->setMaxResults($this->limit);
            });
        }

        return $this->specs;
    }

    protected function addOrderSpec(): array
    {
        $this->addSpec(function (QueryBuilder $qb) {
            $qb->orderBy('date', 'DESC');
        });

        return $this->specs;
    }

    private function addSectionSpec(): array
    {
        if (!empty($this->id_branch)) {
            $this->addSpec(function (QueryBuilder $qb) {
                $qb->andWhere('ar.id_branch = :idBranch');
                $qb->setParameter('idBranch', $this->id_branch);
            });
        }

        return $this->specs;
    }

    private function addTagSpec(): array
    {
        if (!empty($this->id_tag)) {
            $this->addSpec(function (QueryBuilder $qb) {
                $qb->andWhere('atr.id_tag = :idTag');
                $qb->setParameter('idTag', $this->id_tag);
            });
        }

        return $this->specs;
    }

    private function addBehaviourSpecs(): void
    {
        if (empty($this->settings_branch)) {
            $this->addSectionSpec();

            return;
        }

        switch ($this->settings_branch['behaviour'] ?? false) {
            case '1': // ZOBRAZENÍ Z KONKRÉTNÍ SEKCE
                $this->addSectionSpec();
                break;
            case '2': // ZOBRAZOVANI CLANKU V TETO SEKCI A JEJICH DCERINYCH SEKCICH
                $this->addSpec(function (QueryBuilder $qb) {
                    $cats = $this->from_cat($this->id_branch);
                    $qb->andWhere(Operator::inIntArray($cats, 'ar.id_branch'));
                });
                break;
            case '3': // ZOBRAZENÍ VŠECH ČLÁNKŮ
                $this->addSpec(function (QueryBuilder $qb) {
                    $qb->andWhere(1);
                });
                break;
        }
    }

    protected function addLimitOffsetSpec(): array
    {
        if ($this->pager) {
            $this->addSpec($this->pager->getSpec());
        }

        return $this->specs;
    }

    public function getTopArticles(): ?array
    {
        if (empty($this->idArticle)) {
            return $this->getBaseTopArticles($this->limit, 'date', 'DESC', 'all', $this->idArticleSection);
        }

        return $this->getBaseTopArticles($this->limit, 'date', 'DESC', 'all', $this->idArticleSection, [$this->idArticle]);
    }

    #[PostMount]
    public function loadBranchSettings(): void
    {
        if (!empty($this->id_branch)) {
            $this->settings_branch = $this->articleList->getSection(function (QueryBuilder $qb) {
                $qb->andWhere(Operator::equals(['ab.id' => $this->id_branch]));
            });
        }
    }
}
