<?php

namespace Velis\Mvc;

use Velis\Dto\Common\Result\PaginatedListResult;
use Velis\Dto\Common\Result\PaginationMetadata;
use Velis\Filter;
use Velis\Model\DataObject;

class Paginator
{
    private int $listItemsFound = 0;
    private int $defaultPerPage = 30;


    public function __construct(
        private readonly int $page = 1,
        private readonly ?int $perPage = null,
    ) {
        if (is_int($perPage) && $perPage <= 0) {
            $perPage = null;
        }
    }

    public function getList($class, $params = null, $order = null, $fields = null)
    {
        $result = $class::getList($this->page, $params, $order, $this->getPerPage(), $fields);
        $this->listItemsFound = $class::$listItemsFound ?: 0;
        return $result;
    }

    /**
     * @param array $allItems All items to be paginated
     * @return array Paginated list
     */
    public function getListFromArray(array $allItems)
    {
        $this->listItemsFound = count($allItems);
        return array_slice($allItems, ($this->page - 1) * $this->getPerPage(), $this->getPerPage());
    }

    public function paginate(array $data): PaginatedListResult
    {
        return PaginatedListResult::fromArray([
            'metadata' => PaginationMetadata::create($this->page, $this->getPerPage(), $this->listItemsFound),
            'data' => array_map(fn ($item) => $item instanceof DataObject ? $item->getArrayCopy() : $item, array_values($data)),
        ]);
    }

    public static function fromParams(Filter $params)
    {
        return new self(
            $params->getInt('page') ?: 1,
            $params->getInt('perPage')
        );
    }

    public function getPage(): int
    {
        return $this->page;
    }

    public function getPerPage(): int
    {
        return $this->perPage ?? $this->defaultPerPage;
    }

    public function setListItemsFound(int $listItemsFound): void
    {
        $this->listItemsFound = $listItemsFound;
    }

    public function setDefaultPerPage(int $defaultPerPage): void
    {
        $this->defaultPerPage = $defaultPerPage;
    }
}
