<?php

declare(strict_types=1);

namespace KupShop\ContentBundle\Page;

use KupShop\KupShopBundle\Util\Entity\EntityUtil;
use Query\Operator;
use Query\QueryBuilder;

class SystemPageList
{
    private array $specs = [];
    private array $resultModifiers = [];

    public function __construct(
        protected readonly EntityUtil $entityUtil,
    ) {
    }

    public function getPages(?int &$totalCount = null): SystemPageCollection
    {
        $useTotalCount = (bool) count(func_get_args());

        $qb = $this->createQueryBuilder($useTotalCount);
        $result = $qb->execute();

        if ($useTotalCount) {
            $totalCount = (int) sqlFetchAssoc(sqlQuery('SELECT FOUND_ROWS() as total_count'))['total_count'];
        }

        $pages = [];
        foreach ($result as $item) {
            $pages[$item['id']] = $item;
        }

        $pageCollection = new SystemPageCollection($pages);

        foreach ($this->resultModifiers as $callback) {
            $callback($pageCollection);
        }

        return $pageCollection;
    }

    public function orderBy(string $sort, ?string $order = null): self
    {
        $this->andSpec(function (QueryBuilder $qb) use ($sort, $order) {
            $qb->orderBy($sort, $order);
        });

        return $this;
    }

    public function limit(int $count, ?int $offset = null): self
    {
        $this->andSpec(function (QueryBuilder $qb) use ($count, $offset) {
            if (isset($offset)) {
                $qb->setFirstResult($offset);
            }
            $qb->setMaxResults($count);
        });

        return $this;
    }

    public function addResultModifiers(callable $resultModifier): self
    {
        $this->resultModifiers[] = $resultModifier;

        return $this;
    }

    public function andSpec(?callable $spec = null): self
    {
        $this->specs[] = $spec;

        return $this;
    }

    public function getQueryBuilder(): QueryBuilder
    {
        return $this->createQueryBuilder(false);
    }

    protected function createQueryBuilder(bool $useTotalCount = true): QueryBuilder
    {
        $qb = sqlQueryBuilder()
            ->select('p.*')
            ->from('pages', 'p');

        if ($useTotalCount) {
            $qb->addCalcRows();
        }

        $qb->andWhere(Operator::andX($this->specs));

        return $qb;
    }
}
