<script setup lang="ts">
import axios from 'axios'
import type { PaginatedType } from 'nocodb-sdk'

interface Props {
  paginationData: PaginatedType
  changePage: (page: number) => void
  alignCountOnRight?: boolean
  hidePagination?: boolean
  hideSidebars?: boolean
  customLabel?: string
  fixedSize?: number
  extraStyle?: string
  alignLeft?: boolean
  showSizeChanger?: boolean
  isAddNewRecordGridMode?: boolean
  selectedCellCount?: number
}

const props = defineProps<Props>()

const emits = defineEmits(['update:paginationData'])

const { locale } = useI18n()

const vPaginationData = useVModel(props, 'paginationData', emits)

const { isMobileMode } = useGlobal()

const { alignCountOnRight, customLabel, changePage } = props

const { isAddNewRecordGridMode, fixedSize, extraStyle } = toRefs(props)

const isGroupBy = inject(IsGroupByInj, ref(false))

const alignLeft = computed(() => props.alignLeft ?? false)

const { isViewDataLoading, isPaginationLoading } = storeToRefs(useViewsStore())

const count = computed(() => vPaginationData.value?.totalRows ?? Infinity)

const page = computed({
  get: () => vPaginationData?.value?.page ?? 1,
  set: async (p) => {
    isPaginationLoading.value = true
    try {
      await changePage?.(p)
      isPaginationLoading.value = false
    } catch (e) {
      if (axios.isCancel(e)) {
        return
      }
      isPaginationLoading.value = false
    }
  },
})

const size = computed({
  get: () => vPaginationData.value?.pageSize ?? 25,
  set: (size: number) => {
    if (vPaginationData.value) {
      // if there is no change in size then return
      if (vPaginationData.value?.pageSize && vPaginationData.value?.pageSize === size) {
        return
      }

      vPaginationData.value.pageSize = size

      if (vPaginationData.value.totalRows && page.value * size < vPaginationData.value.totalRows) {
        changePage?.(page.value)
      } else {
        changePage?.(1)
      }
    }
  },
})

const isRTLLanguage = computed(() => isRtlLang(locale.value as keyof typeof Language))

const renderAltOrOptlKey = () => {
  return isMac() ? '⌥' : 'ALT'
}

const tempPageVal = ref(page.value)
</script>

<template>
  <div
    class="flex items-center bg-nc-bg-default border-nc-border-gray-medium nc-grid-pagination-wrapper"
    :class="{ 'border-t-1': !isGroupBy, 'h-13': isMobileMode, 'h-10': !isMobileMode }"
    :style="`${fixedSize ? `width: ${fixedSize}px;` : ''}${
      isGroupBy ? 'margin-top:1px; border-radius: 0 0 8px 8px !important;' : ''
    } ${extraStyle}`"
  >
    <div
      class="flex items-center"
      :class="{
        'flex-1': !alignLeft,
        'left-0 sticky': alignLeft,
      }"
    >
      <slot name="add-record" />
      <span
        v-if="!alignCountOnRight && count !== null && count !== Infinity"
        class="caption ml-2.5 text-nc-content-gray-muted text-xs"
        data-testid="grid-pagination"
      >
        {{ count }} {{ customLabel ? customLabel : count !== 1 ? $t('objects.records') : $t('objects.record') }}
      </span>
    </div>

    <div
      v-if="!hidePagination"
      class="transition-all ml-2 sticky left-0 duration-350"
      :class="{
        'ml-8': alignLeft,
        'left-[159px]': isGroupBy && $slots['add-record'] && isAddNewRecordGridMode,
        'left-[199px]': isGroupBy && $slots['add-record'] && !isAddNewRecordGridMode,
        'left-[32px]': isGroupBy && !$slots['add-record'],
      }"
    >
      <div v-if="isViewDataLoading" class="nc-pagination-skeleton flex flex-row justify-center item-center min-h-10 min-w-42">
        <a-skeleton :active="true" :title="true" :paragraph="false" class="-mt-1 max-w-60" />
      </div>
      <NcPagination
        v-else-if="count !== Infinity"
        v-model:current="page"
        v-model:page-size="size"
        class="xs:(mr-2)"
        :class="{ 'rtl-pagination': isRTLLanguage }"
        :total="+count"
        entity-name="grid"
        :prev-page-tooltip="`${renderAltOrOptlKey()}+←`"
        :next-page-tooltip="`${renderAltOrOptlKey()}+→`"
        :first-page-tooltip="`${renderAltOrOptlKey()}+↓`"
        :last-page-tooltip="`${renderAltOrOptlKey()}+↑`"
        :show-size-changer="showSizeChanger"
      />
      <div v-else class="mx-auto flex items-center mt-n1" style="max-width: 250px">
        <span class="text-xs" style="white-space: nowrap"> Change page:</span>
        <a-input
          v-model:value="tempPageVal"
          size="small"
          class="ml-1 !text-xs"
          type="number"
          @keydown.enter="changePage(tempPageVal)"
          @blur="tempPageVal = page"
        >
          <template #suffix>
            <component :is="iconMap.returnKey" class="mt-1" @click="changePage(page)" />
          </template>
        </a-input>
      </div>
    </div>
    <div v-if="!isMobileMode" class="flex-1 flex justify-end items-center">
      <div class="text-right">
        <span
          v-if="alignCountOnRight && count !== Infinity"
          class="caption nc-grid-row-count mr-2.5 text-nc-content-gray-muted text-xs"
          data-testid="grid-pagination"
        >
          {{ selectedCellCount && selectedCellCount > 1 ? selectedCellCount : count }}
          {{
            selectedCellCount && selectedCellCount > 1
              ? $t('labels.cellsSelected')
              : customLabel
              ? customLabel
              : count !== 1
              ? $t('objects.records')
              : $t('objects.record')
          }}
        </span>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.nc-grid-pagination-wrapper {
  .ant-pagination-item-active {
    a {
      @apply text-sm !text-nc-content-gray-subtle !hover:text-nc-content-gray;
    }
  }
}
</style>

<style scoped>
:deep(.ant-pagination-item a) {
  @apply text-sm !leading-[21px] !no-underline;
}

:deep(.nc-pagination .ant-pagination-item) {
  @apply !border-0 !pt-0.25;
}

:deep(.ant-pagination-item:not(.ant-pagination-item-active) a) {
  line-height: 21px !important;
  @apply text-sm !text-nc-content-gray-disabled;
}

:deep(.ant-pagination-item-link) {
  @apply text-nc-content-gray flex items-center justify-center;
}

:deep(.ant-pagination-item.ant-pagination-item-active) {
  @apply !bg-transparent;
}

:deep(.rtl-pagination .ant-pagination-prev .ant-pagination-item-link),
:deep(.rtl-pagination .ant-pagination-next .ant-pagination-item-link) {
  @apply transform rotate-180;
}
</style>
