import { ref, computed, watch, readonly, type Ref } from 'vue'
import { refDebounced } from '@vueuse/core'
import type { PostalRegion } from '~/models/postal-region'
import type { SelectItem } from '~/components/pub/my-ui/form/select.vue'
import * as postalRegionService from '~/services/postal-region.service'

// Global cache untuk postal codes berdasarkan village code
const postalRegionCache = ref<Map<string, PostalRegion[]>>(new Map())
const loadingStates = ref<Map<string, boolean>>(new Map())
const errorStates = ref<Map<string, string | null>>(new Map())

export function usePostalRegion(villageCode: Ref<string | undefined> | string | undefined) {
  // Convert villageCode ke ref jika bukan ref
  const villageCodeRef = typeof villageCode === 'string' || villageCode === undefined ? ref(villageCode) : villageCode

  // Computed untuk mendapatkan postalRegion berdasarkan village code
  const postalRegion = computed(() => {
    const code = villageCodeRef.value
    if (!code) return []
    return postalRegionCache.value.get(code) || []
  })

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

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

  // Computed untuk format SelectItem
  const postalRegionOptions = computed<SelectItem[]>(() => {
    return postalRegion.value.map((postalRegion) => ({
      label: postalRegion.code,
      value: postalRegion.code,
      searchValue: postalRegion.code,
    }))
  })

  // Function untuk fetch postalRegion berdasarkan village code
  async function fetchpostalRegion(villageCodeParam?: string, forceRefresh = false, isUserAction = false) {
    const code = villageCodeParam || villageCodeRef.value
    if (!code) return

    // Jika user action atau force refresh, selalu fetch
    // Jika bukan user action dan sudah ada cache, skip
    if (!isUserAction && !forceRefresh && postalRegionCache.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 postalRegionService.getList({
        sort: 'code:asc',
        'village-code': code,
        'page-no-limit': true,
      })

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

  // Function untuk mencari postalRegion berdasarkan code
  function getpostalRegionByCode(code: string): PostalRegion | undefined {
    const villageCode = villageCodeRef.value
    if (!villageCode) return undefined

    const postalRegionForVillage = postalRegionCache.value.get(villageCode) || []
    return postalRegionForVillage.find((postalRegion) => postalRegion.code === code)
  }

  // Function untuk clear cache village tertentu
  function clearCache(villageCodeParam?: string) {
    const code = villageCodeParam || villageCodeRef.value
    if (code) {
      postalRegionCache.value.delete(code)
      loadingStates.value.delete(code)
      errorStates.value.delete(code)
    }
  }

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

  // Function untuk refresh data
  function refreshpostalRegion(villageCodeParam?: string) {
    const code = villageCodeParam || villageCodeRef.value
    if (code) {
      return fetchpostalRegion(code, true)
    }
  }

  // Debounced village code untuk mencegah multiple calls
  const debouncedVillageCode = refDebounced(villageCodeRef, 100)

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

  return {
    // Data
    postalRegion: readonly(postalRegion),
    postalRegionOptions,

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

    // Methods
    fetchpostalRegion,
    refreshpostalRegion,
    getpostalRegionByCode,
    clearCache,
    clearAllCache,
  }
}

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