import { useApolloClient } from "@apollo/client";
import {
  PostDocument,
  type PostFragment,
  useCreatePostMutation,
  usePostLazyQuery
} from "@hey/indexer";
import type { ApolloClientError } from "@hey/types/errors";
import { useCallback } from "react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import useTransactionLifecycle from "./useTransactionLifecycle";
import useWaitForTransactionToComplete from "./useWaitForTransactionToComplete";

interface CreatePostProps {
  commentOn?: PostFragment;
  onCompleted: () => void;
  onError: (error: ApolloClientError) => void;
}

const useCreatePost = ({
  commentOn,
  onCompleted,
  onError
}: CreatePostProps) => {
  const navigate = useNavigate();
  const handleTransactionLifecycle = useTransactionLifecycle();
  const waitForTransactionToComplete = useWaitForTransactionToComplete();
  const [getPost] = usePostLazyQuery();
  const { cache } = useApolloClient();
  const isComment = Boolean(commentOn);

  const updateCache = useCallback(
    async (txHash: string, toastId: string | number) => {
      const { data } = await getPost({
        fetchPolicy: "cache-and-network",
        variables: { request: { txHash } }
      });

      if (!data?.post) {
        return;
      }

      const type = isComment ? "Comment" : "Post";

      toast.success(`${type} created successfully!`, {
        action: {
          label: "View",
          onClick: () => navigate(`/posts/${data.post?.slug}`)
        },
        id: toastId
      });
      cache.modify({
        fields: {
          [isComment ? "postReferences" : "posts"]: () => {
            cache.writeQuery({ data: data.post, query: PostDocument });
          }
        }
      });
    },
    [getPost, cache, navigate, isComment]
  );

  const onCompletedWithTransaction = useCallback(
    (hash: string) => {
      const toastId = toast.loading(
        `${isComment ? "Comment" : "Post"} processing...`
      );
      waitForTransactionToComplete(hash).then(() => updateCache(hash, toastId));
      return onCompleted();
    },
    [waitForTransactionToComplete, updateCache, onCompleted, isComment]
  );

  // Onchain mutations
  const [createPost] = useCreatePostMutation({
    onCompleted: async ({ post }) => {
      if (post.__typename === "PostResponse") {
        return onCompletedWithTransaction(post.hash);
      }

      return await handleTransactionLifecycle({
        onCompleted: onCompletedWithTransaction,
        onError,
        transactionData: post
      });
    },
    onError
  });

  return { createPost };
};

export default useCreatePost;
