import { QueryKey, useMutation, useQuery } from "@tanstack/react-query";
import { queryClient, toast } from "@xtablo/shared";
import { Tables } from "@xtablo/shared/types/database.types";
import { useEffect, useState } from "react";
import { supabase } from "../lib/supabase";
import { useUser } from "../providers/UserStoreProvider";

type IntroductionConfig = {
  intro_email: string;
};

type Introduction = Tables<"user_introductions"> & {
  config: IntroductionConfig;
};

export const useIntroduction = (): {
  introduction: IntroductionConfig;
  setDraftIntroduction: (cfg: IntroductionConfig) => void;
  updateIntroduction: (cfg: IntroductionConfig) => void;
  isPending: boolean;
} => {
  const { data, isPending } = useFetchIntroduction();
  const { mutate: updateIntroduction, isPending: updateIntroductionPending } =
    useUpsertIntroduction();

  const [draftIntroduction, setDraftIntroduction] = useState<IntroductionConfig | null>(null);

  useEffect(() => {
    if (data) {
      setDraftIntroduction(data.config as IntroductionConfig);
    } else {
      setDraftIntroduction({
        intro_email: "",
      });
    }
  }, [data]);
  return {
    introduction: draftIntroduction ?? {
      intro_email: "",
    },
    setDraftIntroduction,
    updateIntroduction: (cfg: IntroductionConfig) =>
      updateIntroduction({ introEmail: cfg.intro_email }),
    isPending: updateIntroductionPending || isPending,
  };
};

/**
 * Hook to fetch user's introduction email
 */
export function useFetchIntroduction() {
  const user = useUser();

  const { data, isPending } = useQuery<Introduction>({
    queryKey: ["introduction", user.id] as QueryKey,
    queryFn: async () => {
      const { data, error } = await supabase
        .from("user_introductions")
        .select("*")
        .eq("user_id", user.id)
        .single();

      if (error && error.code !== "PGRST116") {
        // PGRST116 is "not found" error, which is ok
        throw new Error(error.message);
      }

      return data;
    },
    enabled: !!user.id,
  });
  return { data, isPending };
}

/**
 * Hook to upsert user's introduction email
 * Creates a new introduction or updates existing one
 */
export function useUpsertIntroduction() {
  const user = useUser();

  const { mutate, isPending } = useMutation({
    mutationFn: async ({ introEmail }: { introEmail: string }) => {
      const { error } = await supabase.from("user_introductions").upsert(
        {
          user_id: user.id,
          config: { intro_email: introEmail },
        },
        {
          onConflict: "user_id",
        }
      );

      if (error) {
        throw new Error(error.message);
      }
      return {};
    },
    onSuccess: () => {
      toast.add({
        title: "Introduction mise à jour avec succès",
        description: "Votre email d'introduction a été mis à jour",
        type: "success",
        position: "top-center",
      });
      queryClient.invalidateQueries({
        queryKey: ["introduction", user.id] as QueryKey,
      });
    },
    onError: () => {
      toast.add({
        title: "Erreur",
        description: "Une erreur est survenue lors de la mise à jour de votre introduction",
        type: "error",
        position: "top-center",
      });
    },
  });
  return { mutate, isPending };
}

/**
 * Hook to delete user's introduction email
 */
export function useDeleteIntroduction() {
  const user = useUser();

  const { mutate, isPending } = useMutation({
    mutationFn: async () => {
      const { error } = await supabase.from("user_introductions").delete().eq("user_id", user.id);

      if (error) {
        throw new Error(error.message);
      }
      return {};
    },
    onSuccess: () => {
      toast.add({
        title: "Introduction supprimée",
        description: "Votre email d'introduction a été supprimé",
        type: "success",
        position: "top-center",
      });
      queryClient.invalidateQueries({
        queryKey: ["introduction", user.id] as QueryKey,
      });
    },
    onError: () => {
      toast.add({
        title: "Erreur",
        description: "Une erreur est survenue lors de la suppression de votre introduction",
        type: "error",
        position: "top-center",
      });
    },
  });
  return { mutate, isPending };
}
