'use client';

import React from 'react';

import { cn } from '../../../lib';
import { useIsMobile } from '../../../hooks';
import { useLocation, useQueryParams } from '../../../hooks/router';

import {
    Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink,
    PaginationNext, PaginationPrevious
} from './pagination';

interface SSRPaginationProps {
  currentPage: number;
  totalPages: number;
  totalItems: number;
  itemsPerPage: number;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
  className?: string;
  showInfo?: boolean;
  maxVisiblePages?: number;
  baseUrl?: string;
  pathname?: string;
  preserveQuery?: boolean;
}

function buildSearch(params: Record<string, string | string[]>, page: number, preserveQuery: boolean): string {
  const next = new URLSearchParams();
  if (preserveQuery) {
    for (const [key, value] of Object.entries(params)) {
      if (key === 'page') continue;
      if (Array.isArray(value)) {
        for (const v of value) next.append(key, v);
      } else {
        next.set(key, value);
      }
    }
  }
  if (page !== 1) next.set('page', page.toString());
  return next.toString();
}

export const SSRPagination: React.FC<SSRPaginationProps> = ({
  currentPage,
  totalPages,
  totalItems,
  itemsPerPage,
  hasNextPage,
  hasPreviousPage: _hasPreviousPage,
  className,
  showInfo = true,
  maxVisiblePages = 7,
  baseUrl,
  pathname: propPathname,
  preserveQuery = true,
}) => {
  const queryParams = useQueryParams();
  const { pathname } = useLocation();
  const isMobile = useIsMobile();

  const getCurrentPageFromUrl = (): number => {
    const pageParam = queryParams.get('page');
    if (pageParam) {
      const pageNum = parseInt(pageParam, 10);
      return isNaN(pageNum) ? 1 : pageNum;
    }
    return 1;
  };

  const actualCurrentPage = getCurrentPageFromUrl() || currentPage;
  const actualHasPreviousPage = actualCurrentPage > 1;

  const getPageUrl = (page: number): string => {
    if (baseUrl) {
      return `${baseUrl}?page=${page}`;
    }
    const queryString = buildSearch(queryParams.params, page, preserveQuery);
    const basePath = propPathname || pathname || '';
    return queryString ? `${basePath}?${queryString}` : basePath;
  };

  const getVisiblePages = (): (number | 'ellipsis')[] => {
    const mobileMaxVisible = 3;
    const effectiveMaxVisible = isMobile ? mobileMaxVisible : maxVisiblePages;

    if (totalPages <= effectiveMaxVisible) {
      return Array.from({ length: totalPages }, (_, i) => i + 1);
    }

    const pages: (number | 'ellipsis')[] = [];
    const halfVisible = Math.floor(effectiveMaxVisible / 2);

    if (isMobile) {
      if (actualCurrentPage > 1) pages.push(actualCurrentPage - 1);
      pages.push(actualCurrentPage);
      if (actualCurrentPage < totalPages) pages.push(actualCurrentPage + 1);
    } else {
      pages.push(1);

      let start = Math.max(2, actualCurrentPage - halfVisible);
      let end = Math.min(totalPages - 1, actualCurrentPage + halfVisible);

      if (actualCurrentPage <= halfVisible + 1) {
        end = Math.min(totalPages - 1, effectiveMaxVisible - 1);
      } else if (actualCurrentPage >= totalPages - halfVisible) {
        start = Math.max(2, totalPages - effectiveMaxVisible + 2);
      }

      if (start > 2) pages.push('ellipsis');
      for (let i = start; i <= end; i++) pages.push(i);
      if (end < totalPages - 1) pages.push('ellipsis');
      if (totalPages > 1) pages.push(totalPages);
    }

    return pages;
  };

  const visiblePages = getVisiblePages();
  const startItem = (actualCurrentPage - 1) * itemsPerPage + 1;
  const endItem = Math.min(actualCurrentPage * itemsPerPage, totalItems);

  if (totalItems === 0) {
    return null;
  }

  return (
    <div className={cn("space-y-4", className)}>
      {showInfo && (
        <div className="text-sm text-muted-foreground text-center">
          {isMobile ? (
            `Page ${actualCurrentPage} of ${totalPages}`
          ) : (
            `Showing ${startItem.toLocaleString()} to ${endItem.toLocaleString()} of ${totalItems.toLocaleString()} results`
          )}
        </div>
      )}

      <Pagination>
        <PaginationContent>
          <PaginationItem>
            <PaginationPrevious
              href={actualHasPreviousPage ? getPageUrl(actualCurrentPage - 1) : undefined}
              className={!actualHasPreviousPage ? "pointer-events-none opacity-50" : undefined}
            />
          </PaginationItem>

          {visiblePages.map((page, index) => (
            <PaginationItem key={index}>
              {page === 'ellipsis' ? (
                <PaginationEllipsis />
              ) : (
                <PaginationLink
                  href={getPageUrl(page)}
                  isActive={page === actualCurrentPage}
                >
                  {page}
                </PaginationLink>
              )}
            </PaginationItem>
          ))}

          <PaginationItem>
            <PaginationNext
              href={hasNextPage ? getPageUrl(actualCurrentPage + 1) : undefined}
              className={!hasNextPage ? "pointer-events-none opacity-50" : undefined}
            />
          </PaginationItem>
        </PaginationContent>
      </Pagination>
    </div>
  );
};

SSRPagination.displayName = 'SSRPagination';
