<template>
  <div class="pagination-bar">
    <div class="pagination-summary">显示第 {{ startItem }} 条 - 第 {{ endItem }} 条，共 {{ total }} 条</div>
    <div class="pagination-actions">
      <span class="pagination-total-pages">总页数：{{ pageCount }}</span>
      <button class="pagination-arrow" type="button" :disabled="currentPage <= 1" aria-label="上一页" @click="goPage(currentPage - 1)">
        ‹
      </button>
      <template v-for="item in visiblePages" :key="`${item.type}-${item.value}`">
        <span v-if="item.type === 'ellipsis'" class="pagination-ellipsis">...</span>
        <button
          v-else
          class="pagination-page"
          :class="{ 'pagination-page-active': item.value === currentPage }"
          type="button"
          @click="goPage(item.value)"
        >
          {{ item.value }}
        </button>
      </template>
      <button
        class="pagination-arrow"
        type="button"
        :disabled="currentPage >= pageCount"
        aria-label="下一页"
        @click="goPage(currentPage + 1)"
      >
        ›
      </button>
      <label class="pagination-size-field">
        <span>每页条数：</span>
        <select :value="pageSize" @change="changePageSize">
          <option v-for="option in pageSizeOptions" :key="option" :value="option">{{ option }}</option>
        </select>
      </label>
    </div>
  </div>
</template>

<script setup>
import { computed } from "vue";

import { PAGE_SIZE_OPTIONS } from "../utils/pagination";

const props = defineProps({
  page: {
    type: Number,
    required: true
  },
  pageSize: {
    type: Number,
    default: 10
  },
  total: {
    type: Number,
    required: true
  },
  pageSizeOptions: {
    type: Array,
    default: () => PAGE_SIZE_OPTIONS
  }
});

const emit = defineEmits(["update:page", "update:pageSize"]);
const pageCount = computed(() => Math.max(1, Math.ceil(props.total / props.pageSize)));
const currentPage = computed(() => Math.min(Math.max(1, props.page), pageCount.value));
const startItem = computed(() => (props.total > 0 ? (currentPage.value - 1) * props.pageSize + 1 : 0));
const endItem = computed(() => Math.min(props.total, currentPage.value * props.pageSize));
const visiblePages = computed(() => {
  const count = pageCount.value;
  const page = currentPage.value;
  const pages = new Set([1, count, page, page - 1, page + 1]);

  if (page <= 3) {
    pages.add(2);
    pages.add(3);
    pages.add(4);
  }

  if (page >= count - 2) {
    pages.add(count - 1);
    pages.add(count - 2);
    pages.add(count - 3);
  }

  const normalizedPages = Array.from(pages)
    .filter((item) => item >= 1 && item <= count)
    .sort((left, right) => left - right);

  return normalizedPages.reduce((items, value, index) => {
    const previous = normalizedPages[index - 1];
    if (index > 0 && value - previous > 1) {
      items.push({ type: "ellipsis", value: `${previous}-${value}` });
    }
    items.push({ type: "page", value });
    return items;
  }, []);
});

function changePageSize(event) {
  emit("update:pageSize", Number(event.target.value || props.pageSize));
  emit("update:page", 1);
}

function goPage(nextPage) {
  const normalizedPage = Math.min(Math.max(1, nextPage), pageCount.value);
  if (normalizedPage !== props.page) {
    emit("update:page", normalizedPage);
  }
}
</script>
