<template>
  <div>
    <div class="flex flex-wrap items-center justify-between mb-2 gap-3 text-sm">
      <span> Showing {{ firstRow }}–{{ lastRow }} of {{ rows.length }} records </span>

      <label class="flex items-center gap-1">
        <span>Rows&nbsp;per&nbsp;page</span>
        <Select v-model.number="internalPageSize">
          <SelectTrigger>
            <SelectValue placeholder="Rows per page" />
          </SelectTrigger>
          <SelectContent>
            <SelectItem v-for="opt in pageSizes" :key="opt" :value="opt">
              {{ opt }}
            </SelectItem>
          </SelectContent>
        </Select>
      </label>
    </div>
    <Card class="rounded-[8px] py-0">
      <Table>
        <TableCaption v-if="title">{{ title }}</TableCaption>
        <TableHeader>
          <TableRow>
            <TableHead v-for="col in columns" :key="col.name">
              {{ col.label }}
            </TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          <TableRow v-for="row in paginatedRows" :key="row.id ?? row.name">
            <TableCell v-for="col in columns" :key="col.name">
              {{ row[col.name] }}
            </TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </Card>
    <nav v-if="totalPages > 1" class="flex items-center justify-end mt-4 gap-2 select-none">
      <Button variant="ghost" :disabled="currentPage === 1" @click="goTo(currentPage - 1)">
        <i class="dku-icon-chevron-left-16"></i>
        Previous
      </Button>
      <div class="flex items-center gap-1">
        <span v-if="showLeftEllipsis" class="py-1">...</span>
        <template v-for="page in visiblePages" :key="page">
          <Button v-if="page !== currentPage" variant="ghost" @click="goTo(page)">
            {{ page }}
          </Button>
          <Button v-else variant="outline">
            {{ page }}
          </Button>
        </template>
        <span v-if="showRightEllipsis" class="py-1">...</span>
      </div>
      <Button variant="ghost" :disabled="currentPage === totalPages" @click="goTo(currentPage + 1)">
        Next
        <i class="dku-icon-chevron-right-16"></i>
      </Button>
    </nav>
  </div>
</template>

<script setup lang="ts">
import {
  Table,
  TableCaption,
  TableHeader,
  TableBody,
  TableRow,
  TableHead,
  TableCell,
} from '@/components/ui/table'
import { Card } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from '@/components/ui/select'
import { ref, computed, watch, withDefaults, defineProps, defineEmits } from 'vue'

const props = withDefaults(
  defineProps<{
    title?: string
    columns: Record<string, any>[]
    rows: Record<string, any>[]

    pageSize?: number
    pageSizes?: number[]
    modelValue?: number
  }>(),
  {
    pageSize: 5,
    pageSizes: () => [5, 10, 20, 30, 50],
    modelValue: 1,
  }
)

const emit = defineEmits<{
  (e: 'update:modelValue', value: number): void
  (e: 'update:pageSize', value: number): void
}>()

const currentPage = ref(props.modelValue)
const internalPageSize = ref(props.pageSize)

watch(
  () => props.modelValue,
  (v) => (currentPage.value = v)
)
watch(currentPage, (v) => emit('update:modelValue', v))

watch(
  () => props.pageSize,
  (v) => (internalPageSize.value = v)
)
watch(internalPageSize, (v) => {
  emit('update:pageSize', v)
  if (currentPage.value > totalPages.value) currentPage.value = totalPages.value
})

const totalPages = computed(() =>
  Math.max(1, Math.ceil(props.rows.length / internalPageSize.value))
)

const paginatedRows = computed(() => {
  const start = (currentPage.value - 1) * internalPageSize.value
  return props.rows.slice(start, start + internalPageSize.value)
})

const firstRow = computed(() =>
  props.rows.length === 0 ? 0 : (currentPage.value - 1) * internalPageSize.value + 1
)
const lastRow = computed(() =>
  Math.min(currentPage.value * internalPageSize.value, props.rows.length)
)

const maxVisiblePages = 3

const visiblePages = computed(() => {
  const current = currentPage.value
  const total = totalPages.value
  let start = Math.max(1, current - Math.floor(maxVisiblePages / 2))
  let end = Math.min(total, start + maxVisiblePages - 1)
  if (end - start + 1 < maxVisiblePages) {
    start = Math.max(1, end - maxVisiblePages + 1)
  }
  return Array.from({ length: end - start + 1 }, (_, i) => start + i)
})

const showLeftEllipsis = computed(() => visiblePages.value[0] > 1)

const showRightEllipsis = computed(
  () => visiblePages.value[visiblePages.value.length - 1] < totalPages.value
)

function goTo(page: number) {
  if (page >= 1 && page <= totalPages.value) currentPage.value = page
}
</script>
