import { ref, computed, watch } from 'vue'
import { refDebounced } from '@vueuse/core'
import type { Village } from '~/models/village'
import type { SelectItem } from '~/components/pub/my-ui/form/select.vue'
import { toTitleCase } from '~/lib/utils'
import * as villageService from '~/services/village.service'

// Global cache untuk villages berdasarkan district code
const villagesCache = ref<Map<string, Village[]>>(new Map())
const loadingStates = ref<Map<string, boolean>>(new Map())
const errorStates = ref<Map<string, string | null>>(new Map())

export function useVillages(districtCode: Ref<string | undefined> | string | undefined) {
  // Convert districtCode ke ref jika bukan ref
  const districtCodeRef =
    typeof districtCode === 'string' || districtCode === undefined ? ref(districtCode) : districtCode

  // Computed untuk mendapatkan villages berdasarkan district code
  const villages = computed(() => {
    const code = districtCodeRef.value
    if (!code) return []
    return villagesCache.value.get(code) || []
  })

  // Computed untuk loading state
  const isLoading = computed(() => {
    const code = districtCodeRef.value
    if (!code) return false
    return loadingStates.value.get(code) || false
  })

  // Computed untuk error state
  const error = computed(() => {
    const code = districtCodeRef.value
    if (!code) return null
    return errorStates.value.get(code) || null
  })

  // Computed untuk format SelectItem
  const villageOptions = computed<SelectItem[]>(() => {
    return villages.value.map((village) => ({
      label: toTitleCase(village.name),
      value: village.code,
      searchValue: `${village.code} ${village.name}`.trim(),
    }))
  })

  // Function untuk fetch villages berdasarkan district code
  async function fetchVillages(districtCodeParam?: string, forceRefresh = false, isUserAction = false) {
    const code = districtCodeParam || districtCodeRef.value
    if (!code) return

    // Jika user action atau force refresh, selalu fetch
    // Jika bukan user action dan sudah ada cache, skip
    if (!isUserAction && !forceRefresh && villagesCache.value.has(code)) {
      return
    }

    // Jika sedang loading, skip untuk mencegah duplicate calls
    if (loadingStates.value.get(code)) {
      return
    }

    // Tambahan: Cek apakah ada pending request untuk code yang sama
    const pendingKey = `pending_${code}`
    if (loadingStates.value.get(pendingKey)) {
      return
    }

    loadingStates.value.set(pendingKey, true)

    loadingStates.value.set(code, true)
    errorStates.value.set(code, null)

    try {
      const response = await villageService.getList({
        sort: 'name:asc',
        'district-code': code,
        'page-no-limit': true,
      })

      if (response.success) {
        const villagesData = response.body.data || []
        villagesCache.value.set(code, villagesData)
      } else {
        errorStates.value.set(code, 'Gagal memuat data kelurahan')
        console.error('Failed to fetch villages:', response)
      }
    } catch (err) {
      errorStates.value.set(code, 'Terjadi kesalahan saat memuat data kelurahan')
      console.error('Error fetching villages:', err)
    } finally {
      loadingStates.value.set(code, false)
      loadingStates.value.delete(pendingKey)
    }
  }

  // Function untuk mencari village berdasarkan code
  function getVillageByCode(code: string): Village | undefined {
    const districtCode = districtCodeRef.value
    if (!districtCode) return undefined

    const villagesForDistrict = villagesCache.value.get(districtCode) || []
    return villagesForDistrict.find((village) => village.code === code)
  }

  // Function untuk mencari village berdasarkan name
  function getVillageByName(name: string): Village | undefined {
    const districtCode = districtCodeRef.value
    if (!districtCode) return undefined

    const villagesForDistrict = villagesCache.value.get(districtCode) || []
    return villagesForDistrict.find((village) => village.name.toLowerCase() === name.toLowerCase())
  }

  // Function untuk clear cache district tertentu
  function clearCache(districtCodeParam?: string) {
    const code = districtCodeParam || districtCodeRef.value
    if (code) {
      villagesCache.value.delete(code)
      loadingStates.value.delete(code)
      errorStates.value.delete(code)
    }
  }

  // Function untuk clear semua cache
  function clearAllCache() {
    villagesCache.value.clear()
    loadingStates.value.clear()
    errorStates.value.clear()
  }

  // Function untuk refresh data
  function refreshVillages(districtCodeParam?: string) {
    const code = districtCodeParam || districtCodeRef.value
    if (code) {
      return fetchVillages(code, true)
    }
  }

  // Debounced district code untuk mencegah multiple calls
  const debouncedDistrictCode = refDebounced(districtCodeRef, 100)

  // Watch perubahan district code untuk auto fetch
  watch(
    debouncedDistrictCode,
    (newCode, oldCode) => {
      if (newCode && newCode !== oldCode) {
        // Jika ada oldCode berarti user action (ganti pilihan)
        const isUserAction = !!oldCode
        fetchVillages(newCode, false, isUserAction)
      }
    },
    { immediate: true },
  )

  return {
    // Data
    villages: readonly(villages),
    villageOptions,

    // State
    isLoading: readonly(isLoading),
    error: readonly(error),

    // Methods
    fetchVillages,
    refreshVillages,
    getVillageByCode,
    getVillageByName,
    clearCache,
    clearAllCache,
  }
}

// Export untuk direct access ke cached data (jika diperlukan)
export const useVillagesCache = () => ({
  villagesCache: readonly(villagesCache),
  loadingStates: readonly(loadingStates),
  errorStates: readonly(errorStates),
})
