<?php

class Paginator {
    private $page;
    private $perPage;
    private $perPageOptions;
    private $total;

    public function __construct($page = 1, $perPage = 20, $perPageOptions = [10, 20, 50, 100]) {
        $this->page = max(1, (int)$page);
        $this->perPage = in_array($perPage, $perPageOptions) ? (int)$perPage : 20;
        $this->perPageOptions = $perPageOptions;
    }

    public static function fromRequest() {
        $page = $_GET['page'] ?? $_POST['page'] ?? 1;
        $perPage = $_GET['per_page'] ?? $_POST['per_page'] ?? 20;
        return new self($page, $perPage);
    }

    public function getOffset() {
        return ($this->page - 1) * $this->perPage;
    }

    public function getLimit() {
        return $this->perPage;
    }

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

    public function getPerPage() {
        return $this->perPage;
    }

    public function setTotal($total) {
        $this->total = $total;
    }

    public function getTotal() {
        return $this->total;
    }

    public function getTotalPages() {
        return (int)ceil($this->total / $this->perPage);
    }

    public function hasNextPage() {
        return $this->page < $this->getTotalPages();
    }

    public function hasPrevPage() {
        return $this->page > 1;
    }

    public function getNextPage() {
        return $this->page + 1;
    }

    public function getPrevPage() {
        return $this->page - 1;
    }

    public function toArray() {
        return [
            'page' => $this->page,
            'per_page' => $this->perPage,
            'total' => $this->total,
            'total_pages' => $this->getTotalPages(),
            'has_next' => $this->hasNextPage(),
            'has_prev' => $this->hasPrevPage(),
            'next_page' => $this->hasNextPage() ? $this->getNextPage() : null,
            'prev_page' => $this->hasPrevPage() ? $this->getPrevPage() : null
        ];
    }

    public function getLimitSql() {
        return "LIMIT {$this->perPage} OFFSET {$this->getOffset()}";
    }
}
