import { computed, onMounted, ref, watch } from 'vue'
import debounce from 'lodash/debounce'
import type { SortConfig } from '@/components/ui/usage/DataTable.vue'
import { useApiPagination } from '@/composables/useApiPagination'
import { getApiErrorMessage } from '@/core/utils/getApiErrorMessage'
import { getUserStats, listUsers } from '../services/user.service'
import type { UserListItem } from '../types/user.types'

export function useUserList() {
  const users = ref<UserListItem[]>([])
  const loading = ref(false)
  const statsLoading = ref(false)
  const error = ref<string | null>(null)
  const statsError = ref<string | null>(null)
  const search = ref('')
  const statusFilter = ref('')
  const joinDateFrom = ref('')
  const joinDateTo = ref('')
  const leaveDateFrom = ref('')
  const leaveDateTo = ref('')
  const unitFilter = ref('')
  const sortBy = ref<SortConfig[]>([{ key: 'name', order: 'asc' }])
  const page = ref(1)
  const itemsPerPage = ref(10)
  const stats = ref<{ total: number; joined_this_month: number }>({ total: 0, joined_this_month: 0 })

  const { pagination, applyPagination } = useApiPagination({ per_page: 10 })

  const hasJoinDateFilters = computed(() => Boolean(joinDateFrom.value || joinDateTo.value))
  const hasLeaveDateFilters = computed(() => Boolean(leaveDateFrom.value || leaveDateTo.value))

  function clearJoinDateFilters() {
    joinDateFrom.value = ''
    joinDateTo.value = ''
  }

  function clearLeaveDateFilters() {
    leaveDateFrom.value = ''
    leaveDateTo.value = ''
  }

  async function fetchUsers(requestPage = page.value) {
    loading.value = true
    error.value = null

    try {
      const activeSort = sortBy.value[0]
      const data = await listUsers({
        page: requestPage,
        per_page: itemsPerPage.value,
        sort_by: activeSort?.key ?? 'name',
        sort_order: activeSort?.order ?? 'asc',
        search: search.value.trim() || undefined,
        status: statusFilter.value.trim() || undefined,
        join_date_from: joinDateFrom.value || undefined,
        join_date_to: joinDateTo.value || undefined,
        leave_date_from: leaveDateFrom.value || undefined,
        leave_date_to: leaveDateTo.value || undefined,
        company_name: unitFilter.value.trim() || undefined,
      })

      users.value = data.data
      applyPagination(data.pagination)
      page.value = data.pagination.current_page
    } catch (err) {
      error.value = getApiErrorMessage(err, 'Gagal memuatkan senarai pengguna.')
    } finally {
      loading.value = false
    }
  }

  async function fetchStats() {
    statsLoading.value = true
    statsError.value = null

    try {
      const res = await getUserStats({
        search: search.value.trim() || undefined,
        status: statusFilter.value.trim() || undefined,
        join_date_from: joinDateFrom.value || undefined,
        join_date_to: joinDateTo.value || undefined,
        leave_date_from: leaveDateFrom.value || undefined,
        leave_date_to: leaveDateTo.value || undefined,
        company_name: unitFilter.value.trim() || undefined,
      })

      stats.value = res.data
    } catch (err) {
      statsError.value = getApiErrorMessage(err, 'Gagal memuatkan statistik pengguna.')
      stats.value = { total: 0, joined_this_month: 0 }
    } finally {
      statsLoading.value = false
    }
  }

  function handleSortUpdate(value: SortConfig[]) {
    sortBy.value = value
    fetchUsers(1)
  }

  const debouncedSearch = debounce(() => {
    fetchUsers(1)
    fetchStats()
  }, 400)

  watch(search, () => {
    debouncedSearch()
  })

  watch(statusFilter, () => {
    fetchUsers(1)
    fetchStats()
  })

  watch(unitFilter, () => {
    fetchUsers(1)
    fetchStats()
  })

  watch([joinDateFrom, joinDateTo, leaveDateFrom, leaveDateTo], () => {
    fetchUsers(1)
    fetchStats()
  })

  watch(page, (nextPage, previousPage) => {
    if (nextPage !== previousPage) {
      fetchUsers(nextPage)
    }
  })

  watch(itemsPerPage, (nextValue, previousValue) => {
    if (nextValue !== previousValue) {
      fetchUsers(1)
    }
  })

  onMounted(() => {
    fetchUsers(1)
    fetchStats()
  })

  return {
    users,
    loading,
    stats,
    statsLoading,
    statsError,
    error,
    search,
    statusFilter,
    joinDateFrom,
    joinDateTo,
    leaveDateFrom,
    leaveDateTo,
    unitFilter,
    hasJoinDateFilters,
    hasLeaveDateFilters,
    clearJoinDateFilters,
    clearLeaveDateFilters,
    sortBy,
    page,
    itemsPerPage,
    pagination,
    handleSortUpdate,
    fetchUsers,
    fetchStats,
  }
}
