import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "@xtablo/shared";
import { Event, EventAndTablo, EventInsert, EventUpdate } from "@xtablo/shared/types/events.types";
import { supabase } from "../lib/supabase";
import { useUser } from "../providers/UserStoreProvider";

// Fetch events for a specific tablo
export const useEventsByTablo = (tabloId: string | null) => {
  const key = tabloId ? ["events", tabloId] : ["events", "all"];
  return useQuery({
    queryKey: key,
    queryFn: async () => {
      if (!tabloId) {
        const { data, error } = await supabase
          .from("events_and_tablos")
          .select("*")
          .order("start_date", { ascending: false })
          .order("start_time", { ascending: false });

        if (error) throw error;
        return data as EventAndTablo[];
      }
      const { data, error } = await supabase
        .from("events_and_tablos")
        .select("*")
        .eq("tablo_id", tabloId)
        .order("start_date", { ascending: false })
        .order("start_time", { ascending: false });

      if (error) throw error;
      return data as EventAndTablo[];
    },
  });
};

// Fetch events for a specific date range
export const useEventsByDateRange = (tabloId: string, startDate: string, endDate: string) => {
  return useQuery({
    queryKey: ["events", tabloId, "dateRange", startDate, endDate],
    queryFn: async () => {
      const { data, error } = await supabase
        .from("events")
        .select("*")
        .eq("tablo_id", tabloId)
        .gte("start_date", startDate)
        .lte("start_date", endDate)
        .is("deleted_at", null)
        .order("start_date", { ascending: true })
        .order("start_time", { ascending: true });

      if (error) throw error;
      return data as Event[];
    },
    enabled: !!tabloId && !!startDate && !!endDate,
  });
};

// Fetch single event
export const useEvent = (eventId: string) => {
  return useQuery({
    queryKey: ["events", "single", eventId],
    queryFn: async () => {
      const { data, error } = await supabase
        .from("events")
        .select("*")
        .eq("id", eventId)
        .is("deleted_at", null)
        .single();

      if (error) throw error;
      return data as Event;
    },
    enabled: !!eventId,
  });
};

// Create new event
export const useCreateEvents = () => {
  const user = useUser();
  const queryClient = useQueryClient();

  const { mutate } = useMutation({
    mutationFn: async (events: EventInsert | EventInsert[]) => {
      const { data, error } = await supabase
        .from("events")
        .insert(
          Array.isArray(events)
            ? events.map((e) => ({
                ...e,
                created_by: user.id,
              }))
            : {
                ...events,
                created_by: user.id,
              }
        )
        .select();

      if (error) throw error;
      return data as Event[];
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ["events"] });
      const eventsCount = Array.isArray(data) ? data.length : 1;
      const pluralizeText =
        eventsCount === 1 ? "L'événement a été créé" : "Les événements ont été créés";
      toast.add(
        {
          title: `${eventsCount} événement(s) créé(s)`,
          description: `${pluralizeText} avec succès`,
          type: "success",
        },
        {
          timeout: 3000,
        }
      );
    },
    onError: (error) => {
      console.error("Error creating event:", error);
      toast.add(
        {
          title: "Erreur lors de la création",
          description: "Impossible de créer l'événement",
          type: "error",
        },
        {
          timeout: 5000,
        }
      );
    },
  });
  return mutate;
};

// Update event
export const useUpdateEvent = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async ({ id, ...updates }: EventUpdate & { id: string }) => {
      const { data, error } = await supabase
        .from("events")
        .update(updates)
        .eq("id", id)
        .select()
        .single();

      if (error) throw error;
      return data as Event;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["events"] });
      toast.add(
        {
          title: "Événement modifié",
          description: "L'événement a été modifié avec succès",
          type: "success",
        },
        {
          timeout: 3000,
        }
      );
    },
    onError: (error) => {
      console.error("Error updating event:", error);
      toast.add(
        {
          title: "Erreur lors de la modification",
          description: "Impossible de modifier l'événement",
          type: "error",
        },
        {
          timeout: 5000,
        }
      );
    },
  });
};

// Delete event (soft delete)
export const useDeleteEvent = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (eventId: string) => {
      const { data, error } = await supabase
        .from("events")
        .update({ deleted_at: new Date().toISOString() })
        .eq("id", eventId)
        .select()
        .single();

      if (error) throw error;
      return data as Event;
    },
    onSuccess: (data) => {
      queryClient.invalidateQueries({ queryKey: ["events", data.tablo_id] });
      queryClient.invalidateQueries({
        queryKey: ["events", "single", data.id],
      });
      toast.add(
        {
          title: "Événement supprimé",
          description: "L'événement a été supprimé avec succès",
          type: "success",
        },
        {
          timeout: 3000,
        }
      );
    },
    onError: (error) => {
      console.error("Error deleting event:", error);
      toast.add(
        {
          title: "Erreur lors de la suppression",
          description: "Impossible de supprimer l'événement",
          type: "error",
        },
        {
          timeout: 5000,
        }
      );
    },
  });
};

// Utility function to format date for database
export const formatDateForDB = (date: Date): string => {
  return date.toISOString().split("T")[0];
};

// Utility function to format time for database
export const formatTimeForDB = (date: Date): string => {
  return date.toTimeString().split(" ")[0].slice(0, 5);
};

// Utility function to combine date and time into a Date object
export const combineDateAndTime = (date: string, time: string): Date => {
  return new Date(`${date}T${time}:00`);
};
