import { likeAPlaylist } from '@/web/api/playlist'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import useUser from './useUser'
import { IpcChannels } from '@/shared/IpcChannels'
import { CacheAPIs } from '@/shared/CacheAPIs'
import { fetchUserPlaylists } from '@/web/api/user'
import { FetchUserPlaylistsResponse, UserApiNames } from '@/shared/api/User'
import toast from 'react-hot-toast'
import reactQueryClient from '@/web/utils/reactQueryClient'
import { cloneDeep } from 'lodash-es'
import { FetchPlaylistResponse, PlaylistApiNames } from '@/shared/api/Playlists'

export default function useUserPlaylists() {
  const { data: user } = useUser()
  const uid = user?.profile?.userId ?? 0

  const params = {
    uid: uid,
    offset: 0,
    limit: 2000,
  }

  const key = [UserApiNames.FetchUserPlaylists, uid]

  return useQuery(
    key,
    async () => {
      if (!params.uid) {
        throw new Error('请登录后再请求用户收藏的歌单')
      }

      const existsQueryData = reactQueryClient.getQueryData(key)
      if (!existsQueryData) {
        window.ipcRenderer
          ?.invoke(IpcChannels.GetApiCache, {
            api: CacheAPIs.UserPlaylist,
            query: {
              uid: params.uid,
            },
          })
          .then(cache => {
            if (cache) reactQueryClient.setQueryData(key, cache)
          })
      }

      return fetchUserPlaylists(params)
    },
    {
      enabled: !!(!!params.uid && params.uid !== 0 && params.offset !== undefined),
      refetchOnWindowFocus: true,
    }
  )
}

export const useMutationLikeAPlaylist = () => {
  const { data: user } = useUser()
  const { data: userPlaylists } = useUserPlaylists()
  const uid = user?.account?.id ?? 0
  const key = [UserApiNames.FetchUserPlaylists, uid]

  return useMutation(
    async (playlistID: number) => {
      if (!playlistID || userPlaylists?.playlist === undefined) {
        throw new Error('playlist id is required or userPlaylists is undefined')
      }
      const response = await likeAPlaylist({
        id: playlistID,
        t: userPlaylists.playlist.findIndex(p => p.id === playlistID) > -1 ? 2 : 1,
      })
      if (response.code !== 200) throw new Error((response as any).msg)
      return response
    },
    {
      onMutate: async playlistID => {
        // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
        await reactQueryClient.cancelQueries(key)

        console.log(reactQueryClient.getQueryData(key))

        // 如果还未获取用户收藏的专辑列表，则获取一次
        if (!reactQueryClient.getQueryData(key)) {
          await reactQueryClient.fetchQuery(key)
        }

        // Snapshot the previous value
        const previousData = reactQueryClient.getQueryData(key) as FetchUserPlaylistsResponse

        const isLiked = !!previousData?.playlist.find(p => p.id === playlistID)
        const newPlaylists = cloneDeep(previousData!)

        console.log({ isLiked })

        if (isLiked) {
          newPlaylists.playlist = previousData.playlist.filter(p => p.id !== playlistID)
        } else {
          // 从react-query缓存获取歌单信息

          const playlistFromCache: FetchPlaylistResponse | undefined =
            reactQueryClient.getQueryData([PlaylistApiNames.FetchPlaylist, { id: playlistID }])

          // 从api获取歌单信息
          const playlist: FetchPlaylistResponse | undefined = playlistFromCache
            ? playlistFromCache
            : await reactQueryClient.fetchQuery([
                PlaylistApiNames.FetchPlaylist,
                { id: playlistID },
              ])

          if (!playlist?.playlist) {
            toast.error('Failed to like playlist: unable to fetch playlist info')
            throw new Error('unable to fetch playlist info')
          }
          newPlaylists.playlist.splice(1, 0, playlist.playlist)

          // Optimistically update to the new value
          reactQueryClient.setQueriesData(key, newPlaylists)
        }

        reactQueryClient.setQueriesData(key, newPlaylists)

        console.log({ newPlaylists })

        // Return a context object with the snapshotted value
        return { previousData }
      },
      // If the mutation fails, use the context returned from onMutate to roll back
      onSettled: (data, error, playlistID, context) => {
        if (data?.code !== 200) {
          reactQueryClient.setQueryData(key, (context as any).previousData)
          toast((error as any).toString())
        }
      },
    }
  )
}
