<?php

declare(strict_types=1);

namespace KupShop\SellerBundle\SellerList;

use KupShop\SellerBundle\Translations\SellersTranslation;
use KupShop\SellerBundle\Utils\SellerUtil;
use Query\Operator;
use Query\QueryBuilder;
use Query\Translation;

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

    public function __construct(private SellerUtil $sellerUtil)
    {
    }

    public function getSellers(?int &$totalCount = null): SellerCollection
    {
        $useTotalCount = count(func_get_args());

        $qb = $this->createQueryBuilder();

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

        $result = $qb->execute();

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

        $sellers = [];
        foreach ($result as $item) {
            $sellers[$item['id']] = $this->sellerUtil->prepareSeller($item);
        }

        $sellerCollection = new SellerCollection($sellers);

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

        return $sellerCollection;
    }

    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;
    }

    protected function createQueryBuilder(): QueryBuilder
    {
        return sqlQueryBuilder()
            ->select('se.*, X(se.position) as x, Y(se.position) as y')
            ->from('sellers', 'se')
            ->andWhere(Operator::andX($this->specs))
            ->andWhere(Translation::coalesceTranslatedFields(
                translationClass: SellersTranslation::class,
                columns: function ($columns) {
                    $columns['data'] = 'data_translation';

                    return $columns;
                }));
    }
}
