import { AuthState } from "@/utils/features/auth/authSlice"
import { Challenge } from "@/utils/features/challenges/challengesSlice"
import { useMutation } from "@tanstack/react-query"

type ErrorResponse = {
  error: string
  message: string
  statusCode: number
}

type onPostSuccessFunc = () => void
type ErrorFuncProps = { response?: ErrorResponse, error?: Error }
type onErrorFunc = (props: ErrorFuncProps) => void

type ChallengeActionProps = {
  auth: AuthState
  onPostSuccess?: onPostSuccessFunc
  onError?: onErrorFunc
}

type ChallengeProps = {
  auth: AuthState
  onPostSuccess?: onPostSuccessFunc
  onError?: onErrorFunc
}

export const useDrawRandomChallengeMutation = ({ auth, onPostSuccess, onError }: ChallengeActionProps) => {
  return useMutation({
    mutationFn: async () => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenges/draw-random/`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
      }).then(resp => resp.json())
    },
    onSuccess: async (data) => {
      if (data.statusCode) {
        if (onError)
          onError({ response: data })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useEndChallenge = ({ auth, onPostSuccess, onError }: ChallengeActionProps) => {
  return useMutation({
    mutationFn: async ({ success }: { success: boolean }) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenge-actions/end-current/`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          success: success,
        })
      }).then(resp => resp.json())
    },
    onSuccess: async (data) => {
      if (data.statusCode) {
        if (onError)
          onError({ response: data })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useAttachNewChallenge = ({ auth, onPostSuccess, onError }: ChallengeActionProps) => {
  return useMutation({
    mutationFn: async ({ challengeActionId, newChallengeId }: { challengeActionId: number, newChallengeId: number }) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenge-actions/${challengeActionId}/`, {
        method: "PATCH",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          challengeId: newChallengeId,
        })
      }).then(resp => resp.json())
    },
    onSuccess: async (data) => {
      if (data.statusCode) {
        if (onError)
          onError({ response: data })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useDeleteChallengeActionMutation = ({ auth, onPostSuccess, onError }: ChallengeActionProps) => {
  return useMutation({
    mutationFn: async (challengeActionId: number) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenge-actions/${challengeActionId}/`, {
        method: "DELETE",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
      })
    },
    onSuccess: async (resp) => {
      if (resp.status >= 400) {
        if (onError)
          onError({ response: await resp.json() })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useAddChallengeMutation = ({ auth, onPostSuccess, onError }: ChallengeProps) => {
  return useMutation({
    mutationFn: async (challenge: Omit<Challenge, 'id'>) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenges/`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          title: challenge.title,
          description: challenge.description,
          reward: challenge.reward,
        })
      }).then(resp => resp.json())
    },
    onSuccess: async (data) => {
      if (data.statusCode) {
        if (onError)
          onError({ response: data })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useEditChallengeMutation = ({ auth, onPostSuccess, onError }: ChallengeProps) => {
  return useMutation({
    mutationFn: async (challenge: Challenge) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenges/${challenge.id}/`, {
        method: "PATCH",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          title: challenge.title,
          description: challenge.description,
          reward: challenge.reward,
        })
      }).then(resp => resp.json())
    },
    onSuccess: async (data) => {
      if (data.statusCode) {
        if (onError)
          onError({ response: data })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}

export const useDeleteChallengeMutation = ({ auth, onPostSuccess, onError }: ChallengeProps) => {
  return useMutation({
    mutationFn: async (challenge: Challenge) => {
      return fetch(`${process.env.EXPO_PUBLIC_TRAINTRAPE_MOI_SERVER}/challenges/${challenge.id}/`, {
        method: "DELETE",
        headers: {
          "Authorization": `Bearer ${auth.token}`,
          "Content-Type": "application/json",
        },
      })
    },
    onSuccess: async (resp) => {
      if (resp.status >= 400) {
        if (onError)
          onError({ response: await resp.json() })
        return
      }
      if (onPostSuccess)
        onPostSuccess()
    },
    onError: async (error: Error) => {
      if (onError)
        onError({ error: error })
    }
  })
}