import { useMutation, useQuery } from "@tanstack/react-query"
import { fetchAppointments, fetchAppointmentById, modifyAppointmentDetails, getAppointments, getAppointmentById, modifyAppointment, fetchStylistAppointments, getStylistAppointments, markAsNoShow, getCancelledVacationAppointments, fetchCancelledVacationAppointments } from "../queries/appointments"
import type { GetAppointmentsParams, AppointmentsArrayResponse, Appointment, GetStylistAppointmentsParams, StylistAppointmentsResponse, CancelledAppointment } from "@/types/appointments"
import type { ModifyAppointmentPayload } from "../queries/appointments"
import type { CreateBookingPayload } from "@/types/bookings"
import { useToaster } from "@/context/ToasterContext"
import { queryClient } from "../client"
import { api } from "@/lib/api"

export function useGetAppointments(params: GetAppointmentsParams = {}) {
  return useQuery<AppointmentsArrayResponse>({
    queryKey: [...getAppointments, params],
    queryFn: () => fetchAppointments(params)
  })
}

export function useGetAppointmentById(id: string) {
  return useQuery<Appointment>({
    queryKey: getAppointmentById(id),
    queryFn: () => fetchAppointmentById(id),
    enabled: !!id
  })
}

import { transformAvailabilityToSuggestions } from "@/lib/utils"

export function useModifyAppointment() {
  const toast = useToaster()

  return useMutation({
    mutationFn: async (payload: ModifyAppointmentPayload) => {
      const { data } = await api.patch("/appointments/modify", payload)
      // Check for slot availability in successful (200 OK) response
      if (data.reason === "SLOT_NOT_AVAILABLE" && data.availability) {
        return {
          ...data,
          suggestions: transformAvailabilityToSuggestions(data.availability),
          message: "The requested slot is not available. Please choose from the following suggestions."
        }
      }

      // If the backend returns success: false in a 200 OK response, throw to trigger onError
      if (data.success === false) {
        throw { response: { data } }
      }

      return data
    },
    onSuccess: (data, variables) => {
      // Check if this is a "time not available" response (already transformed in mutationFn or old format)
      if (data.suggestions) {
        // Return suggestions for the component to handle
        return data
      }

      if (variables.delete) {
        toast.showSuccess("Appointment cancelled successfully!")
      } else {
        toast.showSuccess("Appointment updated successfully!")
      }
      // Invalidate appointments queries to refresh the data
      queryClient.invalidateQueries({ queryKey: getAppointments })
      // Also invalidate stylist appointments queries
      queryClient.invalidateQueries({ queryKey: ["appointments", "stylist"] })
    },
    onError: (error: any, variables) => {
      console.error("Appointment modification failed:", error)
      const data = error.response?.data
      if (data?.reason === "SLOT_NOT_AVAILABLE" && data?.availability) {
        // The component will handle this via its own onError
        return
      }

      const errorMessage = data?.reason || data?.message ||
        (variables.delete ? "Failed to cancel appointment. Please try again." : "Failed to update appointment. Please try again.")

      toast.showError(errorMessage)
    }
  })
}

export function useGetStylistAppointments(params: GetStylistAppointmentsParams) {
  return useQuery<StylistAppointmentsResponse>({
    queryKey: [...getStylistAppointments(params.stylistId), params.page, params.limit],
    queryFn: () => fetchStylistAppointments(params),
    enabled: !!params.stylistId
  })
}

export function useMarkAsNoShow() {
  const toast = useToaster()

  return useMutation({
    mutationFn: (id: string) => markAsNoShow(id),
    onSuccess: () => {
      toast.showSuccess("Appointment marked as no-show!")
      queryClient.invalidateQueries({ queryKey: getAppointments })
      queryClient.invalidateQueries({ queryKey: ["appointments", "stylist"] })
      queryClient.invalidateQueries({ queryKey: ["clients", "appointments"] })
    },
    onError: (error: any) => {
      const data = error.response?.data
      toast.showError(data?.reason || data?.message || "Failed to mark appointment as no-show.")
    }
  })
}

export function useGetCancelledVacationAppointments(stylistId: string) {
  return useQuery<CancelledAppointment[]>({
    queryKey: getCancelledVacationAppointments(stylistId),
    queryFn: () => fetchCancelledVacationAppointments(stylistId),
    enabled: !!stylistId
  })
}
export function useRescheduleAppointment() {
  const toast = useToaster()

  return useMutation({
    mutationFn: async ({ oldId, payload }: { oldId: string; payload: CreateBookingPayload }) => {
      const { data } = await api.post(`/appointments/reschedule/${oldId}`, payload)
      // Check for slot availability in successful (200 OK) response
      if (data.reason === "SLOT_NOT_AVAILABLE" && data.availability) {
        return {
          ...data,
          suggestions: transformAvailabilityToSuggestions(data.availability),
          message: "The requested slot is not available. Please choose from the following suggestions."
        }
      }

      // If the backend returns success: false in a 200 OK response, throw to trigger onError
      if (data.success === false) {
        throw { response: { data } }
      }

      return data
    },
    onSuccess: (data) => {
      // Check if this is a "time not available" response (already transformed in mutationFn or old format)
      if (data.suggestions) {
        // This is the time not available case - don't invalidate queries or show success
        return data
      }

      // Normal success case
      toast.showSuccess(data?.message || "Appointment rescheduled successfully!")
      queryClient.invalidateQueries({ queryKey: getAppointments })
      queryClient.invalidateQueries({ queryKey: ["appointments", "stylist"] })
      return data
    },
    onError: (error: any) => {
      console.error("Appointment rescheduling failed:", error)
      const data = error.response?.data
      if (data?.reason === "SLOT_NOT_AVAILABLE" && data?.availability) {
        // The component will handle this via its own onError
        return
      }
      toast.showError(data?.reason || data?.message || "Failed to reschedule appointment. Please try again.")
    }
  })
}
