<script lang="ts">
    interface Props {
        currentPage: number
        totalPages: number
        onPageChange: (page: number) => void
        /** Maximum number of visible page buttons (excluding prev/next) */
        maxVisiblePages?: number
    }

    let { currentPage, totalPages, onPageChange, maxVisiblePages = 7 }: Props = $props()

    /**
     * Calculate visible page numbers with ellipsis.
     * Always shows first and last page, with a range around the current page.
     */
    const getVisiblePages = (): (number | "ellipsis")[] => {
        if (totalPages <= maxVisiblePages) {
            return Array.from({ length: totalPages }, (_, i) => i + 1)
        }

        const pages: (number | "ellipsis")[] = []
        const halfVisible = Math.floor((maxVisiblePages - 3) / 2)

        // Always first page
        pages.push(1)

        let rangeStart = Math.max(2, currentPage - halfVisible)
        let rangeEnd = Math.min(totalPages - 1, currentPage + halfVisible)

        if (currentPage <= halfVisible + 2) {
            rangeEnd = Math.min(totalPages - 1, maxVisiblePages - 2)
        } else if (currentPage >= totalPages - halfVisible - 1) {
            rangeStart = Math.max(2, totalPages - maxVisiblePages + 3)
        }

        if (rangeStart > 2) {
            pages.push("ellipsis")
        }

        for (let i = rangeStart; i <= rangeEnd; i++) {
            pages.push(i)
        }

        if (rangeEnd < totalPages - 1) {
            pages.push("ellipsis")
        }

        if (totalPages > 1) {
            pages.push(totalPages)
        }

        return pages
    }

    let visiblePages = $derived(getVisiblePages())
</script>

{#if totalPages > 1}
    <nav class="flex items-center justify-center gap-1 sm:gap-2 mt-8" aria-label="Pagination">
        <!-- Previous button -->
        <button
            type="button"
            class="
                flex items-center justify-center
                w-10 h-10 sm:w-12 sm:h-12
                rounded-md
                text-gray-900
                transition-colors
                {currentPage === 1 ? 'opacity-40 cursor-not-allowed' : 'hover:bg-blue-600/10 cursor-pointer'}
            "
            disabled={currentPage === 1}
            onclick={() => onPageChange(currentPage - 1)}
            aria-label="Previous page"
        >
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
            </svg>
        </button>

        <!-- Page numbers -->
        <div class="flex items-center gap-1">
            {#each visiblePages as page, index (index)}
                {#if page === "ellipsis"}
                    <span class="w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center text-gray-900/50"> … </span>
                {:else}
                    <button
                        type="button"
                        class="
                            flex items-center justify-center
                            w-10 h-10 sm:w-12 sm:h-12
                            rounded-md
                            font-semibold text-sm sm:text-base
                            transition-colors
                            {page === currentPage ? 'bg-blue-600 text-white' : 'text-gray-900 hover:bg-blue-600/10'}
                        "
                        aria-current={page === currentPage ? "page" : undefined}
                        aria-label={page === currentPage ? `Page ${page}, current page` : `Go to page ${page}`}
                        onclick={() => onPageChange(page)}
                    >
                        {page}
                    </button>
                {/if}
            {/each}
        </div>

        <!-- Next button -->
        <button
            type="button"
            class="
                flex items-center justify-center
                w-10 h-10 sm:w-12 sm:h-12
                rounded-md
                text-gray-900
                transition-colors
                {currentPage === totalPages ? 'opacity-40 cursor-not-allowed' : 'hover:bg-blue-600/10 cursor-pointer'}
            "
            disabled={currentPage === totalPages}
            onclick={() => onPageChange(currentPage + 1)}
            aria-label="Next page"
        >
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
            </svg>
        </button>
    </nav>
{/if}
