import { ref } from 'vue'

import type { ApiEnvelope } from '@/lib/http'
import type { AdminPagination } from '@/types/admin'

export interface AdminListPageData<TItem> {
  items: TItem[]
  pagination: AdminPagination
}

export interface UseAdminListPageOptions<TItem> {
  defaultErrorMessage: string
  pageSize?: number
  fetchPage: (page: number, pageSize: number) => Promise<ApiEnvelope<AdminListPageData<TItem>>>
}

export function useAdminListPage<TItem>(options: UseAdminListPageOptions<TItem>) {
  const loading = ref(true)
  const errorMessage = ref('')
  const items = ref<TItem[]>([])
  const pagination = ref<AdminPagination>({
    page: 1,
    pageSize: options.pageSize ?? 20,
    total: 0,
  })
  let latestRequestId = 0

  async function loadPage(page = pagination.value.page) {
    const requestId = ++latestRequestId
    loading.value = true
    errorMessage.value = ''

    try {
      const response = await options.fetchPage(page, pagination.value.pageSize)

      if (requestId !== latestRequestId) {
        return
      }

      items.value = response.data.items
      pagination.value = response.data.pagination
    } catch (error) {
      if (requestId !== latestRequestId) {
        return
      }

      errorMessage.value = error instanceof Error ? error.message : options.defaultErrorMessage
    } finally {
      if (requestId === latestRequestId) {
        loading.value = false
      }
    }
  }

  return {
    loading,
    errorMessage,
    items,
    pagination,
    loadPage,
  }
}
