import { InquiryList, Inquiry, InquirySaveResponse, CommonCode } from '@/types/Inquiry'
import { useAxios } from '@/hooks/useAxios'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useInquiryFilterStore } from '@/store/inquiryFilterStore'
import { useMemo } from 'react'
import { useRouter } from 'next/navigation'
import { useAlertMsg } from '@/hooks/useAlertMsg'


/**
 * @description 문의사항 관련 기능을 제공하는 커스텀 훅
 *
 * @param {number} [qnoNo] 문의사항 번호
 * @param {string} [compCd] 회사 코드
 * @returns {Object} 문의사항 관련 기능과 데이터
 * @returns {InquiryList[]} inquiryList - 문의사항 목록
 * @returns {boolean} isLoadingInquiryList - 문의사항 목록 로딩 상태
 * @returns {Inquiry|null} inquiryDetail - 문의사항 상세 정보
 * @returns {boolean} isLoadingInquiryDetail - 문의사항 상세 정보 로딩 상태
 * @returns {boolean} isSavingInquiry - 문의사항 저장 중 상태
 * @returns {Function} saveInquiry - 문의사항 저장 함수
 * @returns {Function} downloadFile - 파일 다운로드 함수
 * @returns {CommonCode[]} commonCodeList - 공통 코드 목록
 */
export function useInquiry(
  qnoNo?: number,
  isList?: boolean,
): {
  inquiryList: InquiryList[]
  isLoadingInquiryList: boolean
  inquiryDetail: Inquiry | null
  isLoadingInquiryDetail: boolean
  isSavingInquiry: boolean
  saveInquiry: (formData: FormData) => Promise<InquirySaveResponse>
  downloadFile: (encodeFileNo: number, srcFileNm: string) => Promise<Blob | null>
  commonCodeList: CommonCode[]
} {
  const queryClient = useQueryClient()
  const { inquiryListRequest, offset, isMyInquiry } = useInquiryFilterStore()
  const { axiosInstance } = useAxios()
  const router = useRouter()
  const { showErrorAlert } = useAlertMsg()
  /**
   * @description API 에러 처리 및 라우팅
   *
   * @param {any} error 에러 객체
   * @returns {void} 라우팅 처리
   */
  const handleError = (error: any, isThrow?: boolean) => {
    const status = error.response?.status
    const errorMsg = error.response?.data.error
    console.error('❌ AXIOS INSTANCE ERROR : ', error)
    if (errorMsg) {
      showErrorAlert(errorMsg)
    }
    if (isThrow) {
      throw new Error(error)
    }
    switch (status) {
      // session 없는 경우
      case 401:
        router.replace('/login')
        break
      // 조회 권한 없는 경우
      case 403:
        router.replace('/inquiry/list')
        break
      // 데이터 DB상 존재하지 않는 경우
      case 404:
        router.replace('/inquiry/list')
        break
      // 서버 오류
      case 500:
        router.back()
        break
      default:
        break
    }
  }

  /**
   * @description 비동기 함수 try-catch 처리 함수
   * @param {() => Promise<any>} func 비동기 함수
   * @param {boolean} isList 목록 조회 여부
   * @param {boolean} isThrow 에러 던지기 여부
   * @returns {Promise<any>} 함수 결과 또는 빈 데이터
   */
  const tryFunction = async (func: () => Promise<any>, isList?: boolean, isThrow?: boolean): Promise<any> => {
    try {
      return await func()
    } catch (error) {
      handleError(error, isThrow)
      if (isList) {
        return { data: [], count: 0 }
      }
      return null
    }
  }

  /**
   * @description 문의사항 목록 조회
   *
   * @returns {Object} 문의사항 목록 데이터
   * @returns {InquiryList[]} data - 문의사항 목록
   * @returns {boolean} isLoading - 문의사항 목록 로딩 상태
   */
  const { data: inquiryList, isLoading: isLoadingInquiryList } = useQuery({
    queryKey: ['inquiryList', inquiryListRequest.loginId, inquiryListRequest.schTitle, inquiryListRequest.schAnswerYn, offset, isMyInquiry],
    queryFn: async () => {
      const isListQuery = true
      const shouldThrowError = false

      const resp = await tryFunction(
        () =>
          axiosInstance(null).get<{ data: InquiryList[] }>(`/api/qna/list`, {
            params: { inquiryListRequest, startRow: offset, endRow: offset + 9, schRegId: isMyInquiry },
          }),
        isListQuery,
        shouldThrowError,
      )
      return resp.data
    },
    enabled: isList,
  })

  /**
   * @description 문의사항 목록 데이터 메모이제이션
   *
   * @returns {Object} 메모이제이션된 문의사항 목록 데이터
   * @returns {InquiryList[]} inquiryList - 문의사항 목록
   */
  const inquriyListData = useMemo(() => {
    if (isLoadingInquiryList) {
      return { inquiryList: [] }
    }
    return {
      inquiryList: inquiryList ?? [],
    }
  }, [inquiryList, isLoadingInquiryList])

  /**
   * @description 문의사항 상세 정보 조회
   *
   * @returns {Object} 문의사항 상세 정보 데이터
   * @returns {Inquiry|null} data - 문의사항 상세 정보
   * @returns {boolean} isLoading - 문의사항 상세 정보 로딩 상태
   */
  const { data: inquiryDetail, isLoading: isLoadingInquiryDetail } = useQuery({
    queryKey: ['inquiryDetail', qnoNo],
    queryFn: async () => {
      const isListQuery = false
      const shouldThrowError = false

      const resp = await tryFunction(
        () =>
          axiosInstance(null).get<{ data: Inquiry }>(`/api/qna/detail`, {
            params: { qnoNo, compCd: '5200', langCd: 'JA' },
          }),
        isListQuery,
        shouldThrowError,
      )
      return resp?.data ?? null
    },
    enabled: qnoNo !== undefined,
  })

  /**
   * @description 문의사항 저장
   *
   * @param {FormData} formData 저장할 문의사항 데이터
   * @returns {Promise<InquirySaveResponse>} 저장된 문의사항 응답 데이터
   */
  const { mutateAsync: saveInquiry, isPending: isSavingInquiry } = useMutation({
    mutationFn: async (formData: FormData) => {
      const isListQuery = false
      const shouldThrowError = true

      const resp = await tryFunction(
        () => axiosInstance(null).post<{ data: InquirySaveResponse }>('/api/qna/save', formData),
        isListQuery,
        shouldThrowError,
      )
      return resp?.data ?? null
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['inquiryList'] })
    },
    onError: (error: any) => {
      handleError(error, true)
    },
  })

  /**
   * @description 파일 다운로드
   *
   * @param {number} encodeFileNo 인코딩된 파일 번호
   * @param {string} srcFileNm 원본 파일명
   * @returns {Promise<Blob|null>} 다운로드된 파일 데이터 또는 null
   */
  const downloadFile = async (encodeFileNo: number, srcFileNm: string) => {
    const isListQuery = false
    const shouldThrowError = true

    const resp = await tryFunction(() => fetch(`/api/qna/file?encodeFileNo=${encodeFileNo}&srcFileNm=${srcFileNm}`), isListQuery, shouldThrowError)
    const blob = await resp.blob()
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = srcFileNm
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)

    return blob
  }

  /**
   * @description 공통 코드 목록 조회
   *
   * @returns {Object} 공통 코드 목록 데이터
   * @returns {CommonCode[]} data - 공통 코드 목록
   * @returns {boolean} isLoading - 공통 코드 목록 로딩 상태
   */
  const { data: commonCodeList, isLoading: isLoadingCommonCodeList } = useQuery({
    queryKey: ['commonCodeList'],
    queryFn: async () => {
      const isListQuery = false
      const shouldThrowError = false

      const resp = await tryFunction(
        () => axiosInstance(null).get<CommonCode[]>('/api/comm-code', { params: { headId: 'QNA_CD' } }),
        isListQuery,
        shouldThrowError,
      )
      return resp?.data ?? []
    },
    staleTime: Infinity,
    gcTime: Infinity,
  })

  return {
    inquiryList: inquriyListData.inquiryList,
    inquiryDetail: inquiryDetail ?? null,
    isLoadingInquiryList,
    isLoadingInquiryDetail,
    isSavingInquiry,
    saveInquiry,
    downloadFile,
    commonCodeList: commonCodeList ?? [],
  }
}
