import { defineStore } from 'pinia'
import { ref, reactive } from 'vue'
import { useGlobalDataStore } from '@/stores/globalDataStore'
import { useGlobalStore } from '@/stores/globalStore'
import { useToastStore } from '@/components/global/toastStore'
import axios from 'axios'

export const useDataStore = defineStore('dataStore', () => {
  const globalDataStore = useGlobalDataStore()
  const globalStore = useGlobalStore()
  const toastStore = useToastStore()

  const siteBase = ref<string>(import.meta.env.VITE_API_URL)
  const apiBase = ref<string>('api/')
  const panelData = reactive<Record<string, any>>({})
  const pageData = reactive<Record<string, any>>({})
  const panelDataChanged = ref<boolean>(false)
  const pageDataChanged = ref<boolean>(false)
  const pageDataUpdate = ref<boolean>(false)
  const isLoading = ref<boolean>(false)

  const dataGet = async (
    api: string,
    data: {
      data?: any
      params?: Record<string, any>
      headers?: Record<string, any>
      options?: Record<string, any>
      toast?: Record<string, any>
      full?: boolean
      /** Bu status kodları için CheckApiError atlanır, hata objesi döner */
      skipErrorForStatuses?: number[]
    } = {}
  ) => {
    try {
      const sendData: Record<string, any> = {}

      if (data.options !== undefined) Object.assign(sendData, data.options)
      if (data.data !== undefined) sendData.data = data.data
      if (data.params !== undefined) sendData.params = data.params
      if (data.headers !== undefined) sendData.headers = data.headers

      const response = await axios.get(apiBase.value + api, sendData)

      if (import.meta.env.DEV) {
        console.log('response --', api, response)
      }

      if (data.toast !== undefined) {
        toastStore.AddToast(data.toast.toast, data.toast.type, data.toast.timeout)
      }

      if (data.full !== undefined && data.full) {
        return response
      } else {
        return response.data
      }
    } catch (error: any) {
      const status = error.response?.status
      if (data.skipErrorForStatuses?.includes(status)) {
        return { _error: true, status, data: error.response?.data }
      }
      CheckApiError(status, error.response?.data)
      console.error('Hata oluştu -:', error)
      return 'errorfalse'
    }
  }

  const dataPost = async (
    api: string,
    data: {
      data?: any
      params?: Record<string, any>
      headers?: Record<string, any>
      options?: Record<string, any>
      toast?: Record<string, any>
      full?: boolean
      /** Bu status kodları için CheckApiError atlanır, hata objesi döner */
      skipErrorForStatuses?: number[]
    } = {}
  ): Promise<any> => {
    try {
      const sendData: Record<string, any> = {}
      const postData = data.data || {}

      if (data.options !== undefined) Object.assign(sendData, data.options)
      if (data.params !== undefined) sendData.params = data.params
      if (data.headers !== undefined) sendData.headers = data.headers

      const response = await axios.post(apiBase.value + api, postData, sendData)

      if (data.toast !== undefined) {
        toastStore.AddToast(data.toast.toast, data.toast.type, data.toast.timeout)
      }

      if (data.full !== undefined && data.full) {
        return response
      } else {
        return response.data
      }
    } catch (error: any) {
      const status = error.response?.status
      if (data.skipErrorForStatuses?.includes(status)) {
        return { _error: true, status, data: error.response?.data }
      }
      CheckApiError(status, error.response?.data)
      console.error('Hata oluştu:', error)
      return Promise.resolve('errorfalse')
    }
  }

  const dataPut = async (
    api: string,
    data: {
      data?: any
      params?: Record<string, any>
      headers?: Record<string, any>
      options?: Record<string, any>
      toast?: Record<string, any>
      full?: boolean
    } = {}
  ): Promise<any> => {
    try {
      const sendData: Record<string, any> = {}
      const postData = data.data || {}

      if (data.options !== undefined) Object.assign(sendData, data.options)
      if (data.params !== undefined) sendData.params = data.params
      if (data.headers !== undefined) sendData.headers = data.headers

      const response = await axios.put(apiBase.value + api, postData, sendData)
      
      if (data.toast !== undefined) {
        toastStore.AddToast(data.toast.toast, data.toast.type, data.toast.timeout)
      }

      if (data.full !== undefined && data.full) {
        return response
      } else {
        return response.data
      }
    } catch (error: any) {
      CheckApiError(error.response?.status, error.response?.data)
      console.error('Hata oluştu:', error)
      return Promise.resolve('errorfalse')
    }
  }

  const dataDelete = async (
    api: string,
    data: {
      data?: object
      params?: Record<string, any>
      headers?: Record<string, any>
      options?: Record<string, any>
      toast?: Record<string, any>
      full?: boolean
    } = {}
  ): Promise<any> => {
    try {
      const sendData: Record<string, any> = {}

      if (data.options !== undefined) Object.assign(sendData, data.options)
      if (data.params !== undefined) sendData.params = data.params
      if (data.headers !== undefined) sendData.headers = data.headers

      const response = await axios.delete(apiBase.value + api, sendData)
      
      if (data.toast !== undefined) {
        toastStore.AddToast(data.toast.toast, data.toast.type, data.toast.timeout)
      }

      if (data.full !== undefined && data.full) {
        return response
      } else {
        return response.data
      }
    } catch (error: any) {
      CheckApiError(error.response?.status, error.response?.data)
      console.error('Hata oluştu:', error)
      return Promise.resolve('errorfalse')
    }
  }

  const CheckApiError = (status?: number, data?: Record<string, any>) => {
    if (status === undefined) {
      toastStore.AddToast("Bağlantı hatası. İnternet bağlantınızı kontrol edin.", "alert", 8000);
      return;
    }
    if (status === 401) return; // Axios interceptor login'e yönlendirir
    if (status === 400) {
      const errorKey = typeof data === "string" ? data : data?.hata || data?.errors;
      if (errorKey !== undefined) {
        if (Array.isArray(errorKey)) {
          errorKey.forEach((el: string) => {
            toastStore.AddToast(el, "alert");
          });
        } else if (typeof errorKey === "string") {
          toastStore.AddToast(errorKey, "alert");
        } else {
          toastStore.AddToast("Bir hata oluştu.", "alert");
        }
      } else {
        toastStore.AddToast("Bir hata oluştu.", "alert");
      }
      return;
    }
    const httpErrorMessages: Record<number, string> = {
      413: "Dosya boyutu çok büyük. Lütfen daha küçük bir dosya yükleyin veya sunucu limitlerini kontrol edin.",
      404: "İstenen kaynak bulunamadı.",
      500: "Sunucu hatası oluştu. Lütfen daha sonra tekrar deneyin.",
      502: "Sunucu geçici olarak yanıt vermiyor. Lütfen daha sonra tekrar deneyin.",
      503: "Servis şu an kullanılamıyor. Lütfen daha sonra tekrar deneyin.",
      504: "İstek zaman aşımına uğradı. Lütfen tekrar deneyin.",
      408: "İstek zaman aşımına uğradı. Lütfen tekrar deneyin."
    };
    const message = httpErrorMessages[status] || `Beklenmeyen hata (${status}). Lütfen tekrar deneyin.`;
    toastStore.AddToast(message, "alert", 8000);
  };

  const GetCustomerTipList = async () => {
    if (globalDataStore.customerTips.length === 0) {
      let list = await dataGet('Auth/uyetipiList')

      if (list !== 'errorfalse') globalDataStore.customerTips = list
    }
  }

  const normalizeLocationKey = (value: string | number | null | undefined): string => {
    return globalStore.trToEngLower(String(value ?? '').trim())
  }

  const setLocationLookupMaps = (list: Record<string, any>[]) => {
    Object.keys(globalDataStore.ilMapById).forEach((key) => {
      delete globalDataStore.ilMapById[key]
    })
    Object.keys(globalDataStore.ilMapByAd).forEach((key) => {
      delete globalDataStore.ilMapByAd[key]
    })

    list.forEach((item: Record<string, any>) => {
      globalDataStore.ilMapById[String(item.id)] = item
      globalDataStore.ilMapByAd[normalizeLocationKey(item.ad)] = item
    })
  }

  const GetIlList = async () => {
    if (globalDataStore.ilList.length === 0) {
      const start = performance.now()
      let list = await dataGet('Il/summary')

      if (list !== 'errorfalse') {
        globalDataStore.ilList = list
        setLocationLookupMaps(list)
        globalDataStore.locationPerfStats.ilListCount = list.length
        globalDataStore.locationPerfStats.ilListRequestMs = Math.round(performance.now() - start)
      }
    }
  }

  const GetIlcelerByIlId = async (ilId: string | number | null | undefined) => {
    if (ilId === null || ilId === undefined || ilId === '') return []

    const cacheKey = String(ilId)
    const cachedList = globalDataStore.ilcelerByIlId[cacheKey]
    if (cachedList !== undefined) return cachedList

    const start = performance.now()
    const list = await dataGet(`Il/${ilId}/ilceler`)
    if (list === 'errorfalse') return []

    globalDataStore.ilcelerByIlId[cacheKey] = list
    globalDataStore.locationPerfStats.ilceRequestMs = Math.round(performance.now() - start)
    return list
  }

  const GetMahallelerByIlceId = async (ilceId: string | number | null | undefined) => {
    if (ilceId === null || ilceId === undefined || ilceId === '') return []

    const cacheKey = String(ilceId)
    const cachedList = globalDataStore.mahallelerByIlceId[cacheKey]
    if (cachedList !== undefined) return cachedList

    const start = performance.now()
    const list = await dataGet(`Ilce/${ilceId}/mahalleler`)
    if (list === 'errorfalse') return []

    globalDataStore.mahallelerByIlceId[cacheKey] = list
    globalDataStore.locationPerfStats.mahalleRequestMs = Math.round(
      performance.now() - start
    )
    return list
  }

  const GetIlById = (ilId: string | number | null | undefined) => {
    if (ilId === null || ilId === undefined || ilId === '') return undefined
    return globalDataStore.ilMapById[String(ilId)]
  }

  const GetIlByName = (ilName: string | null | undefined) => {
    if (ilName === null || ilName === undefined || ilName === '') return undefined
    return globalDataStore.ilMapByAd[normalizeLocationKey(ilName)]
  }

  return {
    isLoading,
    siteBase,
    apiBase,
    panelData,
    pageData,
    panelDataChanged,
    pageDataChanged,
    pageDataUpdate,
    dataGet,
    dataPost,
    dataPut,
    dataDelete,
    GetCustomerTipList,
    GetIlList,
    GetIlcelerByIlId,
    GetMahallelerByIlceId,
    GetIlById,
    GetIlByName
  }
})
