import { useInfiniteQuery } from '@tanstack/react-query'
import { transformObjectKeys } from '@/libs/axios'
import { useSuitableStore } from '@/store/useSuitableStore'
import { useAxios } from './useAxios'
import { useCommCode } from './useCommCode'
import { SUITABLE_HEAD_CODE, type Suitable, type SuitableDetail, type SuitableIds } from '@/types/Suitable'

export function useSuitable() {
  const { axiosInstance } = useAxios()
  const { getCommCode } = useCommCode()
  const { itemPerPage, selectedCategory, searchValue, suitableCommCode, setSuitableCommCode, isSearch, selectedItems } = useSuitableStore()

  const getSuitables = async ({
    pageNumber,
    category,
    keyword,
  }: {
    pageNumber?: number
    category?: string
    keyword?: string
  }): Promise<Suitable[]> => {
    try {
      const params: Record<string, string | number> = {
        pageNumber: pageNumber || 1,
        itemPerPage: itemPerPage,
      }
      if (category) params.category = category
      if (keyword) params.keyword = keyword

      const response = await axiosInstance(null).get<Suitable[]>('/api/suitable/list', { params })
      return response.data
    } catch (error) {
      console.error('지붕재 데이터 로드 실패:', error)
      return []
    }
  }

  const getSuitableIds = async (): Promise<SuitableIds[]> => {
    try {
      const params: Record<string, string> = {}
      if (selectedCategory) params.category = selectedCategory
      if (searchValue) params.keyword = searchValue
      const response = await axiosInstance(null).get<SuitableIds[]>('/api/suitable/pick', { params })
      return response.data
    } catch (error) {
      console.error('지붕재 아이디 로드 실패:', error)
      return []
    }
  }

  const getSuitableDetails = async (ids: string, detailIds?: string): Promise<Suitable[]> => {
    try {
      const params: Record<string, string> = { ids: ids }
      if (detailIds) params.detailIds = detailIds
      const response = await axiosInstance(null).get<Suitable[]>('/api/suitable', { params })
      return response.data
    } catch (error) {
      console.error('지붕재 상세 데이터 로드 실패:', error)
      return []
    }
  }

  const getSuitableCommCode = () => {
    const headCodes = Object.values(SUITABLE_HEAD_CODE) as SUITABLE_HEAD_CODE[]
    for (const code of headCodes) {
      getCommCode(code).then((res) => {
        setSuitableCommCode(code, res)
      })
    }
  }

  const toCodeName = (headCode: string, code: string): string => {
    const commCode = suitableCommCode.get(headCode)
    return commCode?.find((item) => item.code === code)?.codeJp || ''
  }

  const toSuitableDetail = (suitableDetailString: string): SuitableDetail[] => {
    try {
      const suitableDetailArray = transformObjectKeys(JSON.parse(suitableDetailString)) as SuitableDetail[]
      if (!Array.isArray(suitableDetailArray)) {
        throw new Error('suitableDetailArray is not an array')
      }
      return suitableDetailArray
    } catch (error) {
      console.error('지붕재 데이터 파싱 실패:', error)
      return []
    }
  }

  const toSuitableDetailIds = (suitableDetailString: string): Set<number> => {
    try {
      return new Set<number>(JSON.parse(suitableDetailString).map(({ id }: { id: number }) => id))
    } catch (error) {
      console.error('지붕재 데이터 파싱 실패:', error)
      return new Set()
    }
  }

  const {
    data: suitables,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading,
    isError,
    error,
  } = useInfiniteQuery<Suitable[]>({
    queryKey: ['suitables', 'list', selectedCategory, isSearch],
    queryFn: async (context) => {
      const pageParam = context.pageParam as number
      return await getSuitables({
        pageNumber: pageParam,
        ...(selectedCategory && { category: selectedCategory }),
        ...(isSearch && { keyword: searchValue }),
      })
    },
    getNextPageParam: (lastPage: Suitable[], allPages: Suitable[][]) => {
      return lastPage.length === itemPerPage ? allPages.length + 1 : undefined
    },
    initialPageParam: 1,
    staleTime: 1000 * 60 * 10,
    gcTime: 1000 * 60 * 10,
  })

  const serializeSelectedItems = (): Map<string, string> => {
    const ids: string[] = []
    const detailIds: string[] = []
    for (const [key, value] of selectedItems) {
      ids.push(String(key))
      for (const id of value) detailIds.push(String(id))
    }
    return new Map<string, string>([
      ['ids', ids.join(',')],
      ['detailIds', detailIds.join(',')],
    ])
  }

  return {
    getSuitables,
    getSuitableIds,
    getSuitableDetails,
    getSuitableCommCode,
    toCodeName,
    toSuitableDetail,
    toSuitableDetailIds,
    suitables,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
    isLoading,
    serializeSelectedItems,
  }
}
