import { useMemo, useState } from "react";
import styles from "./styles.module.css";

import {
  useStripe,
  useElements,
  ExpressCheckoutElement,
} from "@stripe/react-stripe-js";
import {
  AvailablePaymentMethods,
  StripeExpressCheckoutElementReadyEvent,
} from "@stripe/stripe-js";

interface IExpressCheckoutStripeProps {
  clientSecret: string;
  returnUrl?: string;
  isHide?: boolean;
  onAvailable?: (
    isAvailable: boolean,
    availableMethods: AvailablePaymentMethods | undefined
  ) => void;
  onChangeLoading?: (isLoading: boolean) => void;
}

const checkFormAvailable = (
  availablePaymentMethods: undefined | AvailablePaymentMethods
) => {
  if (!availablePaymentMethods) return false;
  let result = false;
  for (const key in availablePaymentMethods) {
    if (availablePaymentMethods[key as keyof AvailablePaymentMethods]) {
      result = true;
      break;
    }
  }
  return result;
};

function ExpressCheckoutStripe({
  clientSecret,
  returnUrl = "https://${window.location.host}/payment/result/",
  isHide = false,
  onAvailable,
  onChangeLoading,
}: IExpressCheckoutStripeProps) {
  const stripe = useStripe();
  const elements = useElements();
  const [errorMessage, setErrorMessage] = useState<string>();
  const [isAvailable, setIsAvailable] = useState(false);
  const isHideForm = useMemo(
    () => isHide || !isAvailable,
    [isAvailable, isHide]
  );

  const onConfirm = async () =>
    // event: StripeExpressCheckoutElementConfirmEvent
    {
      if (!stripe || !elements) {
        // Stripe.js hasn't loaded yet.
        // Make sure to disable form submission until Stripe.js has loaded.
        return;
      }

      const { error: submitError } = await elements.submit();
      if (submitError) {
        setErrorMessage(submitError.message);
        return;
      }

      // // Create the PaymentIntent and obtain clientSecret
      // const res = await fetch("/create-intent", {
      //   method: "POST",
      // });
      // const { client_secret: clientSecret } = await res.json();

      // Confirm the PaymentIntent using the details collected by the Express Checkout Element
      const { error } = await stripe.confirmPayment({
        // `elements` instance used to create the Express Checkout Element
        elements,
        // `clientSecret` from the created PaymentIntent
        clientSecret,
        confirmParams: {
          return_url: returnUrl,
        },
      });

      if (error) {
        // This point is only reached if there's an immediate error when
        // confirming the payment. Show the error to your customer (for example, payment details incomplete)
        setErrorMessage(error.message);
      } else {
        // The payment UI automatically closes with a success animation.
        // Your customer is redirected to your `return_url`.
      }
    };

  const onReady = (event: StripeExpressCheckoutElementReadyEvent) => {
    const _isAvailable = checkFormAvailable(event.availablePaymentMethods);
    setIsAvailable(_isAvailable);
    onAvailable && onAvailable(_isAvailable, event.availablePaymentMethods);
    onChangeLoading && onChangeLoading(false);
  };

  return (
    <div className={`${styles.container} ${isHideForm ? styles.hide : ""}`}>
      <ExpressCheckoutElement
        onReady={onReady}
        onLoadError={() => onChangeLoading && onChangeLoading(false)}
        onConfirm={onConfirm}
      />
      {errorMessage && <p className={styles.error}>{errorMessage}</p>}
    </div>
  );
}

export default ExpressCheckoutStripe;
