import { ApiError, SinglePayment, useApi } from "@/api";
import { User } from "@/api/resources/User";
import { AuthToken } from "@/api/types";
import { productUrls } from "@/data/products";
import routes from "@/routes";
import { getZodiacSignByDate } from "@/services/zodiac-sign";
import { selectors } from "@/store";
import { useCallback, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";

interface ICreateSinglePaymentProps {
  user: User;
  token: AuthToken;
  targetProductKey: string;
  returnUrl: string;
}

interface IErrorSinglePayment {
  error?: string;
}

export const useSinglePayment = () => {
  const api = useApi();
  const navigate = useNavigate();
  const [paymentIntent, setPaymentIntent] =
    useState<SinglePayment.ResponsePost>();
  const [product, setProduct] = useState<SinglePayment.ResponseGet>();
  const [error, setError] = useState<IErrorSinglePayment>(
    {} as IErrorSinglePayment
  );
  const [isLoading, setIsLoading] = useState(false);
  const { gender } = useSelector(selectors.selectQuestionnaire);
  const birthday = useSelector(selectors.selectBirthday);

  const getCurrentProduct = useCallback(
    async (token: AuthToken, targetProductKey: string) => {
      const productsSinglePayment = await api.getSinglePaymentProducts({
        token,
      });
      const currentProduct = productsSinglePayment.find(
        (product) => product.key === targetProductKey
      );
      return currentProduct;
    },
    [api]
  );

  const handlerPaymentIntentResult = useCallback(
    (paymentIntent: SinglePayment.ResponsePost, type: string) => {
      if (!("payment" in paymentIntent)) return;
      let status = "failed";
      if (paymentIntent.payment.status === "paid") {
        status = "succeeded";
      }
      return navigate(
        `${routes.client.paymentResult()}?redirect_status=${status}&redirect_type=${type}`
      );
    },
    [navigate]
  );

  const checkProductPurchased = useCallback(
    async (productKey: string, token: AuthToken) => {
      try {
        const purchased = await api.checkProductPurchased({
          productKey,
          token,
        });

        if ("active" in purchased && purchased.active) {
          return true;
        }
        return false;
      } catch (error) {
        console.error(error);
        return false;
      }
    },
    [api]
  );

  const createSinglePayment = useCallback(
    async ({
      user,
      token,
      targetProductKey,
      returnUrl,
    }: ICreateSinglePaymentProps) => {
      setIsLoading(true);
      const product = await getCurrentProduct(token, targetProductKey);
      if (!product) {
        setError({ error: "Product not found" });
        setIsLoading(false);
        return;
      }
      setProduct(product);
      const isPurchased = await checkProductPurchased(
        targetProductKey,
        token
      );
      if (isPurchased && productUrls[targetProductKey]?.length) {
        return navigate(productUrls[targetProductKey]);
      }

      let _gender = "male";
      if (gender.length) {
        _gender = gender;
      }
      if (user.profile.gender?.length) {
        _gender = user.profile.gender;
      }
      const paymentIntent = await api.createSinglePayment({
        token,
        data: {
          user: {
            id: `${user?.id}`,
            email: user?.email,
            name: user.username || "",
            sign:
              user?.profile?.sign?.sign ||
              getZodiacSignByDate(user.profile.birthday || birthday || ""),
            age: user?.profile?.age?.years || 1,
            gender: _gender,
          },
          partner: {
            sign: null,
            age: null,
          },
          paymentInfo: {
            productId: product?._id || "",
            key: product?.key || "",
          },
          return_url: returnUrl,
        },
      }).catch((error: ApiError<SinglePayment.ResponsePost>) => {
        if (error.responseData && "message" in error.responseData) {
          setError({ error: error.responseData.message });
        } else {
          setError({ error: error.message });
        }
        setIsLoading(false);
        return;
      });
      if (typeof paymentIntent !== "object") {
        return;
      }
      if ("message" in paymentIntent) {
        setError({ error: paymentIntent.message });
        setIsLoading(false);
        return;
      }
      handlerPaymentIntentResult(paymentIntent, targetProductKey);
      setPaymentIntent(paymentIntent);
      setIsLoading(false);
      return paymentIntent;
    },
    [
      api,
      birthday,
      checkProductPurchased,
      gender,
      getCurrentProduct,
      handlerPaymentIntentResult,
      navigate,
    ]
  );

  return useMemo(
    () => ({
      product,
      paymentIntent,
      createSinglePayment,
      checkProductPurchased,
      isLoading,
      error,
    }),
    [product, paymentIntent, createSinglePayment, checkProductPurchased, isLoading, error]
  );
};
