import EmailInput from "@/components/EmailEnterPage/EmailInput";
import styles from "./styles.module.css";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { actions, selectors } from "@/store";
import { useDispatch, useSelector } from "react-redux";
import MainButton from "@/components/MainButton";
import Loader, { LoaderColor } from "@/components/Loader";
import { useAuth } from "@/auth";
import { ApiError, extractErrorMessage, useApi } from "@/api";
import { getClientTimezone } from "@/locales";
import ErrorText from "@/components/ErrorText";
import Title from "@/components/Title";
import NameInput from "@/components/EmailEnterPage/NameInput";
import {
  ResponseGet,
  ResponsePost,
  ResponsePostExistPaymentData,
} from "@/api/resources/SinglePayment";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import PaymentForm from "./PaymentForm";
import { getPriceCentsToDollars } from "@/services/price";
import { createSinglePayment } from "@/services/singlePayment";

function PaymentWithEmailPage() {
  const { t, i18n } = useTranslation();
  const tokenFromStore = useSelector(selectors.selectToken);
  const { signUp, user: userFromStore } = useAuth();
  const api = useApi();
  const navigate = useNavigate();
  const timezone = getClientTimezone();
  const dispatch = useDispatch();
  const birthday = useSelector(selectors.selectBirthday);
  const { gender } = useSelector(selectors.selectQuestionnaire);
  const locale = i18n.language;
  const [email, setEmail] = useState("");
  const [name, setName] = useState("");
  const [isValidEmail, setIsValidEmail] = useState(false);
  const [isValidName, setIsValidName] = useState(true);
  const [isDisabled, setIsDisabled] = useState(true);
  const [isLoading, setIsLoading] = useState(false);
  const [isLoadingPage, setIsLoadingPage] = useState(false);
  const [isAuth, setIsAuth] = useState(false);
  const [apiError, setApiError] = useState<ApiError | null>(null);
  const [error, setError] = useState<boolean>(false);
  const [paymentIntent, setPaymentIntent] = useState<
    ResponsePost | ResponsePostExistPaymentData | null
  >(null);
  const [currentProduct, setCurrentProduct] = useState<ResponseGet>();
  const returnUrl = `${window.location.protocol}//${window.location.host}/payment/result/?type=epe`;

  useEffect(() => {
    if (isValidName && isValidEmail) {
      setIsDisabled(false);
    } else {
      setIsDisabled(true);
    }
  }, [isValidEmail, email, isValidName, name]);

  const handleValidEmail = (email: string) => {
    dispatch(actions.form.addEmail(email));
    setEmail(email);
    setIsValidEmail(true);
  };

  const handleValidName = (name: string) => {
    setName(name);
    setIsValidName(true);
  };

  const authorization = async () => {
    try {
      setIsLoading(true);
      const auth = await api.auth({ email, timezone, locale });
      const {
        auth: { token, user },
      } = auth;
      signUp(token, user);
      const payload = {
        user: {
          profile_attributes: {
            birthday,
            full_name: name,
          },
        },
        token,
      };
      const updatedUser = await api.updateUser(payload).catch((error) => {
        console.log("Error: ", error);
      });

      if (updatedUser?.user) {
        dispatch(actions.user.update(updatedUser.user));
      }
      if (name) {
        dispatch(
          actions.user.update({
            username: name,
          })
        );
      }
      dispatch(actions.status.update("registred"));
      setIsAuth(true);
      const userUpdated = await api.getUser({ token });
      return { user: userUpdated?.user, token };
    } catch (error) {
      console.error(error);
      if (error instanceof ApiError) {
        setApiError(error as ApiError);
      } else {
        setError(true);
      }
    }
  };

  const getCurrentProduct = async (token: string) => {
    const productsSinglePayment = await api.getSinglePaymentProducts({
      token,
    });
    const currentProduct = productsSinglePayment.find(
      (product) => product.key === "moons.pdf.aura"
    );
    return currentProduct;
  };

  const handleClick = async () => {
    const authData = await authorization();
    if (!authData) {
      return;
    }
    const { user, token } = authData;

    const currentProduct = await getCurrentProduct(token);
    if (!currentProduct) {
      setError(true);
      return;
    }
    setCurrentProduct(currentProduct);

    const { productId, key } = currentProduct;
    const paymentInfo = {
      productId,
      key,
    };
    const paymentIntent = await createSinglePayment(
      user,
      paymentInfo,
      token,
      email,
      name,
      birthday,
      returnUrl,
      api,
      gender
    );
    setPaymentIntent(paymentIntent);
    setIsLoading(false);
    if ("payment" in paymentIntent) {
      if (paymentIntent.payment.status === "paid")
        return navigate(routes.client.epeSuccessPayment());
      return navigate(routes.client.epeFailPayment());
    }
  };

  const handleAuthUser = useCallback(async () => {
    if (!tokenFromStore.length || !userFromStore) {
      return;
    }
    setIsLoadingPage(true);
    const currentProduct = await getCurrentProduct(tokenFromStore);
    if (!currentProduct) {
      setError(true);
      return;
    }
    setCurrentProduct(currentProduct);

    const { productId, key } = currentProduct;
    const paymentInfo = {
      productId,
      key,
    };
    const paymentIntent = await createSinglePayment(
      userFromStore,
      paymentInfo,
      tokenFromStore,
      userFromStore.email,
      userFromStore.profile.full_name,
      userFromStore.profile.birthday,
      returnUrl,
      api,
      gender
    );
    setPaymentIntent(paymentIntent);
    setIsLoadingPage(false);
    setIsLoading(false);
    if ("payment" in paymentIntent) {
      if (paymentIntent.payment.status === "paid")
        return navigate(routes.client.epeSuccessPayment());
      return navigate(routes.client.epeFailPayment());
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    handleAuthUser();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className={`${styles.page} page`}>
      {isLoadingPage && <Loader color={LoaderColor.Black} />}
      {!isLoadingPage &&
        paymentIntent &&
        "paymentIntent" in paymentIntent &&
        !!tokenFromStore.length && (
          <>
            <Title variant="h1" className={styles.title}>
              {getPriceCentsToDollars(currentProduct?.amount || 0)}$
            </Title>
            <PaymentForm
              stripePublicKey={paymentIntent.paymentIntent.data.public_key}
              clientSecret={paymentIntent.paymentIntent.data.client_secret}
              returnUrl={returnUrl}
            />
          </>
        )}
      {(!tokenFromStore || !paymentIntent) && !isLoadingPage && (
        <>
          <NameInput
            value={name}
            placeholder="Your name"
            onValid={handleValidName}
            onInvalid={() => setIsValidName(true)}
          />
          <EmailInput
            name="email"
            value={email}
            placeholder={t("your_email")}
            onValid={handleValidEmail}
            onInvalid={() => setIsValidEmail(false)}
          />

          <MainButton
            className={styles.button}
            onClick={handleClick}
            disabled={isDisabled}
          >
            {isLoading && <Loader color={LoaderColor.White} />}
            {!isLoading &&
              !(!apiError && !error && !isLoading && isAuth) &&
              t("_continue")}
            {!apiError && !error && !isLoading && isAuth && (
              <img
                className={styles["success-icon"]}
                src="/SuccessIcon.png"
                alt="Success Icon"
              />
            )}
          </MainButton>
        </>
      )}
      {(error || apiError) && (
        <Title variant="h3" style={{ color: "red", margin: 0 }}>
          Something went wrong
        </Title>
      )}
      {apiError && (
        <ErrorText
          size="medium"
          isShown={Boolean(apiError)}
          message={apiError ? extractErrorMessage(apiError) : null}
        />
      )}
    </div>
  );
}

export default PaymentWithEmailPage;
