<?php

namespace Velis\Api\Query;

use Velis\Filter;

abstract class AbstractQueryBuilder implements QueryBuilderInterface
{
    protected SortOrderParser $sortOrderParser;

    public function __construct(protected readonly Filter $filter)
    {
        $this->sortOrderParser = $this->createSortOrderParser();
    }

    private function createSortOrderParser(): SortOrderParser
    {
        return new SortOrderParser($this->filter, $this->getSupportedFields(), $this->getOverriddenFields());
    }

    /**
     * @return array<string>
     */
    abstract protected function getSupportedFields(): array;

    protected function getOverriddenFields(): array
    {
        return [];
    }

    public function getPage(): int
    {
        if (!$this->filter->hasValue('page')) {
            return 1;
        }

        return $this->filter->getInt('page');
    }

    public function getOrder(): array
    {
        $order = $this->sortOrderParser->parseIntoArray();

        if (!empty($order)) {
            return $order;
        }

        return $this->getDefaultOrder();
    }

    /**
     * @return array<string,string>
     */
    abstract protected function getDefaultOrder(): array;

    public function getOrderString(): string
    {
        $orderArray = [];

        foreach ($this->getOrder() as $field => $direction) {
            $orderArray[] = $field . ' ' . $direction;
        }

        return implode(', ', $orderArray);
    }

    public function getPerPage(): int
    {
        if ($this->filter->hasValue('per_page')) {
            return $this->filter->getInt('per_page');
        }

        return $this->getDefaultPerPage();
    }

    abstract protected function getDefaultPerPage(): int;

    public function getOffset(): int
    {
        $page = $this->getPage();
        $perPage = $this->getPerPage();

        return ($page - 1) * $perPage;
    }
}
