import type { SurveyBasicInfo, SurveyDetailInfo, SurveyDetailRequest, SurveyDetailCoverRequest, SurveyRegistRequest } from '@/types/Survey'
import { useMemo } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
import { useSessionStore } from '@/store/session'
import { useAxios } from './useAxios'
import { queryStringFormatter } from '@/utils/common-utils'

export const requiredFields = [
  {
    field: 'installationSystem',
    name: '設置希望システム',
  },
  {
    field: 'constructionYear',
    name: '建築年数',
  },
  {
    field: 'rafterSize',
    name: '垂木サイズ',
  },
  {
    field: 'rafterPitch',
    name: '垂木傾斜',
  },
  {
    field: 'waterproofMaterial',
    name: '防水材',
  },
  {
    field: 'insulationPresence',
    name: '断熱材有無',
  },
  {
    field: 'structureOrder',
    name: '屋根構造の順序',
  },
]

interface ZipCodeResponse {
  status: number
  message: string | null
  results: ZipCode[] | null
}

type ZipCode = {
  zipcode: string
  prefcode: string
  address1: string
  address2: string
  address3: string
  kana1: string
  kana2: string
  kana3: string
}

export function useServey(id?: number): {
  surveyList: { data: SurveyBasicInfo[]; count: number } | {}
  surveyDetail: SurveyBasicInfo | null
  isLoadingSurveyList: boolean
  isLoadingSurveyDetail: boolean
  isCreatingSurvey: boolean
  isUpdatingSurvey: boolean
  isDeletingSurvey: boolean
  createSurvey: (survey: SurveyRegistRequest) => Promise<number>
  createSurveyDetail: (params: { surveyId: number; surveyDetail: SurveyDetailCoverRequest }) => void
  updateSurvey: ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => void
  deleteSurvey: () => Promise<boolean>
  submitSurvey: (params: { saveId?: number; targetId?: string; storeId?: string; srlNo?: string }) => void
  validateSurveyDetail: (surveyDetail: SurveyDetailRequest) => string
  getZipCode: (zipCode: string) => Promise<ZipCode[] | null>
  refetchSurveyList: () => void
} {
  const queryClient = useQueryClient()
  const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
  const { session } = useSessionStore()
  const { axiosInstance } = useAxios()

  const {
    data: surveyListData,
    isLoading: isLoadingSurveyList,
    refetch: refetchSurveyList,
  } = useQuery({
    queryKey: ['survey', 'list', keyword, searchOption, isMySurvey, sort, offset, session?.storeNm, session?.builderNo, session?.role],
    queryFn: async () => {
      const resp = await axiosInstance(null).get<{ data: SurveyBasicInfo[]; count: number }>('/api/survey-sales', {
        params: {
          keyword,
          searchOption,
          isMySurvey,
          sort,
          offset,
          store: session?.storeNm,
          builderNo: session?.builderNo,
          role: session?.role,
        },
      })
      return resp.data
    },
    enabled: session?.isLoggedIn,
  })
  const surveyData = useMemo(() => {
    if (!surveyListData) return { count: 0, data: [] }
    return {
      ...surveyListData,
    }
  }, [surveyListData])

  const { data: surveyDetail, isLoading: isLoadingSurveyDetail } = useQuery({
    queryKey: ['survey', id],
    queryFn: async () => {
      if (id === undefined) throw new Error('id is required')
      if (id === null || isNaN(id)) return null
      const resp = await axiosInstance(null).get<SurveyBasicInfo>(`/api/survey-sales/${id}`)
      return resp.data
    },
    enabled: id !== undefined,
  })

  const { mutateAsync: createSurvey, isPending: isCreatingSurvey } = useMutation({
    mutationFn: async (survey: SurveyRegistRequest) => {
      const resp = await axiosInstance(null).post<SurveyBasicInfo>('/api/survey-sales', { survey: survey, storeId: session?.storeId ?? null })
      return resp.data.id ?? 0
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
      queryClient.invalidateQueries({ queryKey: ['survey', id] })
      return data
    },
  })

  const { mutate: updateSurvey, isPending: isUpdatingSurvey } = useMutation({
    mutationFn: async ({ survey, isTemporary, storeId }: { survey: SurveyRegistRequest; isTemporary: boolean; storeId?: string }) => {
      console.log('updateSurvey, survey:: ', survey)
      if (id === undefined) throw new Error('id is required')
      const resp = await axiosInstance(null).put<SurveyRegistRequest>(`/api/survey-sales/${id}`, {
        survey: survey,
        isTemporary: isTemporary,
        storeId: storeId,
      })
      return resp.data
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['survey', id] })
      queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
    },
  })

  const { mutateAsync: deleteSurvey, isPending: isDeletingSurvey } = useMutation({
    mutationFn: async () => {
      if (id === null) throw new Error('id is required')
      const resp = await axiosInstance(null).delete<boolean>(`/api/survey-sales/${id}`)
      return resp.data
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
      queryClient.invalidateQueries({ queryKey: ['survey', id] })
    },
  })

  const { mutateAsync: createSurveyDetail } = useMutation({
    mutationFn: async ({ surveyId, surveyDetail }: { surveyId: number; surveyDetail: SurveyDetailCoverRequest }) => {
      const resp = await axiosInstance(null).patch<SurveyDetailInfo>(`/api/survey-sales/${surveyId}`, surveyDetail)
      return resp.data
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
      queryClient.invalidateQueries({ queryKey: ['survey', id] })
    },
  })

  const { mutateAsync: submitSurvey } = useMutation({
    mutationFn: async ({ saveId, targetId, storeId, srlNo }: { saveId?: number; targetId?: string; storeId?: string; srlNo?: string }) => {
      const submitId = saveId ?? id
      if (!submitId) throw new Error('id is required')
      const resp = await axiosInstance(null).patch<boolean>(`/api/survey-sales/${submitId}`, {
        targetId,
        storeId,
        srlNo,
      })
      return resp.data
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
      queryClient.invalidateQueries({ queryKey: ['survey', id] })
    },
  })

  const validateSurveyDetail = (surveyDetail: SurveyDetailRequest) => {
    const etcFields = [
      'installationSystem',
      'constructionYear',
      'rafterSize',
      'rafterPitch',
      'waterproofMaterial',
      'structureOrder',
      'insulationPresence',
    ] as const

    const emptyField = requiredFields.find((field) => {
      if (etcFields.includes(field.field as (typeof etcFields)[number])) {
        return (
          surveyDetail[field.field as keyof SurveyDetailRequest] === null &&
          (surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest] === null ||
            surveyDetail[`${field.field}Etc` as keyof SurveyDetailRequest]?.toString().trim() === '')
        )
      } else {
        return surveyDetail[field.field as keyof SurveyDetailRequest] === null
      }
    })

    const contractCapacity = surveyDetail.contractCapacity
    if (contractCapacity && contractCapacity.trim() !== '' && contractCapacity.split(' ')?.length === 1) {
      return 'contractCapacityUnit'
    }

    return emptyField?.field || ''
  }

  const getZipCode = async (zipCode: string): Promise<ZipCode[] | null> => {
    try {
      const { data } = await axiosInstance(null).get<ZipCodeResponse>(
        `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter({ zipcode: zipCode.trim() })}`,
      )
      return data.results
    } catch (e) {
      console.error('Failed to fetch zipcode data:', e)
      throw new Error('Failed to fetch zipcode data')
    }
  }

  return {
    surveyList: surveyData.data,
    surveyDetail: surveyDetail as SurveyBasicInfo | null,
    isLoadingSurveyList,
    isLoadingSurveyDetail,
    isCreatingSurvey,
    isUpdatingSurvey,
    isDeletingSurvey,
    createSurvey,
    updateSurvey,
    deleteSurvey,
    createSurveyDetail,
    submitSurvey,
    validateSurveyDetail,
    getZipCode,
    refetchSurveyList,
  }
}
