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 { listRoles } from '../services/role.service'
import type { RoleListItem } from '../types/role.types'

function getSortValue(item: RoleListItem, key: string): string {
  if (key === 'permissions') {
    return item.permissions?.map((permission) => permission.name).join(', ') ?? ''
  }

  const value = item[key as keyof RoleListItem]
  return value == null ? '' : String(value)
}

export function useRoleList() {
  const allRoles = ref<RoleListItem[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)
  const search = ref('')
  const sortBy = ref<SortConfig[]>([{ key: 'name', order: 'asc' }])
  const page = ref(1)
  const itemsPerPage = ref(10)

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

  const sortedRoles = computed(() => {
    const activeSort = sortBy.value[0]
    const sorted = [...allRoles.value]

    if (!activeSort?.key) {
      return sorted
    }

    return sorted.sort((left, right) => {
      const comparison = getSortValue(left, activeSort.key).localeCompare(
        getSortValue(right, activeSort.key),
      )

      return activeSort.order === 'desc' ? -comparison : comparison
    })
  })

  const roles = computed(() => {
    const start = (page.value - 1) * itemsPerPage.value
    return sortedRoles.value.slice(start, start + itemsPerPage.value)
  })

  function updatePagination() {
    const total = sortedRoles.value.length
    const lastPage = Math.max(1, Math.ceil(total / itemsPerPage.value))
    const currentPage = Math.min(page.value, lastPage)
    const from = total === 0 ? null : (currentPage - 1) * itemsPerPage.value + 1
    const to = total === 0 ? null : Math.min(currentPage * itemsPerPage.value, total)

    applyPagination({
      current_page: currentPage,
      per_page: itemsPerPage.value,
      total,
      last_page: lastPage,
      from,
      to,
      has_more_pages: currentPage < lastPage,
    })
  }

  async function fetchRoles() {
    loading.value = true
    error.value = null

    try {
      const response = await listRoles({
        search: search.value.trim() || undefined,
      })
      allRoles.value = response.data
    } catch (err) {
      error.value = getApiErrorMessage(err, 'Gagal memuatkan senarai peranan.')
      allRoles.value = []
    } finally {
      loading.value = false
      updatePagination()
    }
  }

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

  const debouncedSearch = debounce(() => {
    page.value = 1
    fetchRoles()
  }, 400)

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

  watch([sortedRoles, page, itemsPerPage], () => {
    updatePagination()
  })

  watch(itemsPerPage, () => {
    page.value = 1
  })

  onMounted(() => {
    fetchRoles()
  })

  return {
    roles,
    loading,
    error,
    search,
    sortBy,
    page,
    itemsPerPage,
    pagination,
    handleSortUpdate,
    fetchRoles,
  }
}
