/**
 * useServerPagination composable
 *
 * Paginated server table with search debounce, page/perPage handlers.
 * Eliminates the identical pattern in ServersPage and DashboardPage.
 */
import { ref, watch, onUnmounted } from 'vue'
import type { ServerApiItem } from '@/types/api'
import { fetchPagePerPage } from '@/utils/paginatedFetch'
import { toServerApiSort, type TableSortItem } from '@/utils/serverTableSort'

export interface UseServerPaginationOptions {
  /** When set, passed as target_path_unset query param (true/false). Omit for no filter. */
  targetPathUnset?: boolean
}

export function useServerPagination(options?: UseServerPaginationOptions) {
  const targetPathUnset = options?.targetPathUnset

  const servers = ref<ServerApiItem[]>([])
  const loading = ref(false)
  const page = ref(1)
  const itemsPerPage = ref(20)
  const total = ref(0)
  const search = ref('')
  /** API category filter; empty string = all */
  const categoryFilter = ref('')
  /** null = all; true = online only; false = offline only */
  const isOnlineFilter = ref<boolean | null>(null)
  const sortBy = ref<TableSortItem[]>([])

  function listQueryParams(): Record<string, unknown> {
    const q = String(search.value ?? '').trim()
    // 有搜索词时全局检索：忽略分类/在线/路径分区，避免刚添加的机器搜不到
    const applyPathFilter = targetPathUnset !== undefined && !q
    return {
      search: q || undefined,
      ...(!q && categoryFilter.value ? { category: categoryFilter.value } : {}),
      ...(!q && isOnlineFilter.value !== null ? { is_online: isOnlineFilter.value } : {}),
      ...toServerApiSort(sortBy.value),
      ...(applyPathFilter ? { target_path_unset: targetPathUnset } : {}),
    }
  }

  async function loadServers(opts?: { silent?: boolean }) {
    if (!opts?.silent) loading.value = true
    try {
      const res = await fetchPagePerPage<ServerApiItem>(
        '/servers/',
        listQueryParams(),
        page.value,
        itemsPerPage.value,
      )
      servers.value = res.items
      total.value = res.total
      if (itemsPerPage.value === -1) {
        page.value = 1
      }
    } catch (e) {
      servers.value = []
      total.value = 0
      throw e  // Let callers handle the error display
    } finally {
      loading.value = false
    }
  }

  let searchTimer: ReturnType<typeof setTimeout>
  onUnmounted(() => clearTimeout(searchTimer))
  function onSearch() {
    clearTimeout(searchTimer)
    searchTimer = setTimeout(() => { page.value = 1; loadServers() }, 300)
  }

  function onPageChange(p: number) {
    page.value = p
    loadServers()
  }

  function onItemsPerPageChange(n: number) {
    itemsPerPage.value = n
    page.value = 1
    loadServers()
  }

  function onCategoryChange(category: string) {
    categoryFilter.value = category
    page.value = 1
    loadServers()
  }

  function onOnlineFilterChange(filter: boolean | null) {
    isOnlineFilter.value = filter
    page.value = 1
    loadServers()
  }

  function clearOnlineFilter() {
    if (isOnlineFilter.value === null) return
    isOnlineFilter.value = null
    page.value = 1
    loadServers()
  }

  watch(
    sortBy,
    () => {
      page.value = 1
      void loadServers()
    },
    { deep: true },
  )

  async function loadAllServers(): Promise<ServerApiItem[]> {
    const res = await fetchPagePerPage<ServerApiItem>(
      '/servers/',
      listQueryParams(),
      1,
      -1,
    )
    return res.items
  }

  return {
    servers, loading, page, itemsPerPage, total, search, categoryFilter, isOnlineFilter, sortBy,
    loadServers, onSearch, onPageChange, onItemsPerPageChange, onCategoryChange,
    onOnlineFilterChange, clearOnlineFilter,
    loadAllServers, listQueryParams,
  }
}
