<?php

namespace lib\Core\Utils;

class Pagination
{
  public int $currentPage;
  public int $perPage;
  public int $totalItems;
  public int $totalPages;
  public int $groupSize = 10;
  public int $start;
  public int $end;

  public function __construct(int $totalItems, int $currentPage = 1, int $perPage = 10)
  {
    $this->totalItems = $totalItems;
    $this->perPage = $perPage;
    $this->currentPage = max(1, $currentPage);
    $this->totalPages = (int)ceil($totalItems / $perPage);
    $this->start = ($this->currentPage - 1) * $perPage;
    $this->end = min($this->start + $perPage, $totalItems);
    $this->groupSize  = intval(APP_VIEW_LIST_PAGINATION_GROUPSIZE);
  }

  public function hasPrevious(): bool
  {
    return $this->currentPage > 1;
  }

  public function hasNext(): bool
  {
    return $this->currentPage < $this->totalPages;
  }

  public function previousPage(): int
  {
    return max(1, $this->currentPage - 1);
  }

  public function nextPage(): int
  {
    return min($this->totalPages, $this->currentPage + 1);
  }

  public function getOffset(): int
  {
    return $this->start;
  }

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

  public function toArray(): array
  {
    return [
      'current_page' => $this->currentPage,
      'per_page' => $this->perPage,
      'total_items' => $this->totalItems,
      'total_pages' => $this->totalPages,
      'has_previous' => $this->hasPrevious(),
      'has_next' => $this->hasNext(),
      'previous_page' => $this->previousPage(),
      'next_page' => $this->nextPage(),
      'offset' => $this->getOffset(),
      'limit' => $this->getLimit(),
    ];
  }

  public function render(string $baseUrl = '', array $query = []): string
  {
    if ($this->totalPages <= 1) {
      return '';
    }

    $html = '<nav><ul class="pagination">';
    $currentGroup = (int)floor(($this->currentPage - 1) / $this->groupSize);
    $startPage = $currentGroup * $this->groupSize + 1;
    $endPage = min($startPage + $this->groupSize - 1, $this->totalPages);

    // << 그룹 이전
    if ($startPage > 1) {
      $prevGroupPage = max(1, $startPage - 1);
      $html .= $this->pageLink($prevGroupPage, '&laquo;', $baseUrl, $query);
    } else {
      $html .= '<li class="page-item disabled"><span class="page-link">&laquo;</span></li>';
    }

    // 페이지 번호들
    for ($i = $startPage; $i <= $endPage; $i++) {
      if ($i === $this->currentPage) {
        $html .= '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
      } else {
        $html .= $this->pageLink($i, (string)$i, $baseUrl, $query);
      }
    }

    // >> 그룹 다음
    if ($endPage < $this->totalPages) {
      $nextGroupPage = $endPage + 1;
      $html .= $this->pageLink($nextGroupPage, '&raquo;', $baseUrl, $query);
    } else {
      $html .= '<li class="page-item disabled"><span class="page-link">&raquo;</span></li>';
    }

    $html .= '</ul></nav>';
    return $html;
  }
  private function pageLink(int $page, string $label, string $baseUrl, array $query): string
  {
    $query['curPage'] = $page;
    $url = $baseUrl . '?' . http_build_query($query);
    return '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($url) . '">' . $label . '</a></li>';
  }
}
