<?php

namespace App\Support;

use Illuminate\Pagination\LengthAwarePaginator;

class PaginationPresenter
{
    public int $total_pages;
    public int $active_page;
    public int $start;
    public int $end;
    public string $link_class;
    public bool $show_page_numbers;
    public bool $show_page_x_of_y;

    private string $baseUrl;
    private string $qs;

    /**
     * Static constructor: build a presenter from a Laravel paginator.
     */
    public static function fromPaginator(
        LengthAwarePaginator $paginator,
        string $baseUrl,
        array $queryParams = [],
        int $pagesToShow = 10,
        string $linkClass = 'page-link',
        bool $showPageNumbers = true,
        bool $showPageXofY = true,
        bool $showViewAll = true,
        int $viewAllPerPage = 99999
    ): self {
        $totalPages  = max(1, (int) $paginator->lastPage());
        $currentPage = max(1, (int) $paginator->currentPage());

        // window calc
        $pagesToShow = max(1, $pagesToShow);
        $half  = (int) floor($pagesToShow / 2);
        $start = max(1, $currentPage - $half);
        $end   = min($totalPages, $start + $pagesToShow - 1);
        $start = max(1, $end - $pagesToShow + 1);

        $queryParams = array_filter($queryParams, fn($v) => $v !== null && $v !== '');
        $qs = http_build_query($queryParams);

        $presenter = new self(
            $baseUrl,
            $qs,
            $currentPage,
            $totalPages,
            $start,
            $end,
            $linkClass,
            $showPageNumbers,
            $showPageXofY,
            $showViewAll,
            $viewAllPerPage
        );

        return $presenter;
    }

    private bool $show_view_all;
    private int $view_all_per_page;

    public function __construct(
        string $baseUrl,
        string $qs,
        int $activePage,
        int $totalPages,
        int $start,
        int $end,
        string $linkClass,
        bool $showPageNumbers,
        bool $showPageXofY,
        bool $showViewAll,
        int $viewAllPerPage
    ) {
        $this->baseUrl = $baseUrl;
        $this->qs = $qs;

        $this->active_page = $activePage;
        $this->total_pages = $totalPages;
        $this->start = $start;
        $this->end = $end;

        $this->link_class = $linkClass;
        $this->show_page_numbers = $showPageNumbers;
        $this->show_page_x_of_y = $showPageXofY;

        $this->show_view_all = $showViewAll;
        $this->view_all_per_page = $viewAllPerPage;
    }

    private function glue(string $url, array $params): string
    {
        $q = http_build_query($params);
        return $url . (str_contains($url, '?') ? '&' : '?') . $q;
    }

    public function pageUrl(int $page): string
    {
        $page = max(1, min($page, $this->total_pages));

        $params = [];
        if ($this->qs !== '') {
            parse_str($this->qs, $params);
        }

        $params['page'] = $page;
        return $this->glue($this->baseUrl, $params);
    }

    public function viewAllUrl(): string
    {
        $params = [];
        if ($this->qs !== '') {
            parse_str($this->qs, $params);
        }

        $params['per_page'] = $this->view_all_per_page;
        unset($params['page']);

        return $this->glue($this->baseUrl, $params);
    }

    public function showFirst(): bool   { return $this->active_page > 1; }
    public function showPrevious(): bool{ return $this->active_page > 1; }
    public function showNext(): bool    { return $this->active_page < $this->total_pages; }
    public function showLast(): bool    { return $this->active_page < $this->total_pages; }
    public function showViewAll(): bool { return $this->show_view_all; }
}
