import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { toast } from "react-toastify";
import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";

/**
 * Renders a React component that displays the description and last four digits of a payment card.
 */
function ThePaymentText({ value, type }) {
  const { cardNum } = value;
  let description = value.description;
  let digits = value.digits;

  if (type === "new") {
    const firstDigit = cardNum[0];
    if (firstDigit === "4") {
      description = "Visa";
    } else if (firstDigit === "5") {
      description = "Master";
    } else {
      description = "ATM";
    }
    digits = cardNum.slice(-4);
  }

  return (
    <div className="my-2 flex items-center gap-5">
      <div className="card-details flex items-center gap-3">
        <h1 className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1 space-x-1">
          {description} Card
        </h1>
        <p className="text-xl font-normal text-dark-gray dark:text-white tracking-wide">
          Bank **************{digits}
        </p>
      </div>
    </div>
  );
}

/**
 * Renders the amount of a transaction in a specific currency.
 * @returns {JSX.Element} - The rendered component.
 */
function AmountSection({ currency, amount, country }) {
  const formattedAmount = amount?.toFixed(2);
  const gapClassName = country === "US" ? "gap-14" : "gap-4";

  return (
    <div className={`flex items-center ${gapClassName}`}>
      <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
        Amount({currency})
      </h1>
      <span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
        {formattedAmount}
      </span>
    </div>
  );
}

/**
 * Renders the transaction fee for a payment.
 * @returns {JSX.Element} - Rendered JSX displaying the transaction fee with the label "Transaction Fee".
 */
function TransactionFeeSection({ currency, fee, country }) {
  const formattedFee = (+fee).toFixed(2);
  const gapClass = country === "US" ? "gap-[2.7rem]" : "gap-4";

  return (
    <div className={`flex items-center border-b border-gray-600 ${gapClass}`}>
      <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
        Transaction Fee
      </h1>
      <span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
        {formattedFee}
      </span>
    </div>
  );
}

/**
 * Calculates the total amount by adding the `amount` and `fee` values together.
 * Formats the total amount to two decimal places and displays it.
 * @returns {JSX.Element} - The TotalSection component.
 */
function TotalSection({ currency, amount, fee, country }) {
  const total = Number(amount) + Number(fee);
  const formattedTotal = total?.toFixed(2);

  const gap = country === "US" ? "gap-[8rem]" : "gap-[6.3rem]";

  return (
    <div className={`flex items-center ${gap}`}>
      <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
        Total
      </h1>
      <span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
        {formattedTotal}
      </span>
    </div>
  );
}

function ConfirmAddFund({
  confirmCredit,
  onClose,
  walletItem,
  setConfirmCredit,
}) {
  const __confirmData = confirmCredit?.data;
  const __confirmCountry = walletItem?.country;
  const __confirmCardDetails =
    __confirmData.cardType === "prev"
      ? JSON.parse(__confirmData.card)
      : __confirmData.card;

  const apiURL = new usersService();

  const { userDetails } = useSelector((state) => state?.userDetails);

  const [requestStatus, setRequestStatus] = useState({
    message: "",
    loading: false,
    status: false,
  });

  const config = {
    public_key: __confirmData?.flutterwave_key,
    tx_ref: __confirmData?.credit_reference,
    currency: "NGN",
    amount: Number(__confirmData.amount),
    payment_options: "card,mobilemoney,ussd",
    customer: {
      email: userDetails.email,
      phone_number: userDetails.phone,
      name: `${userDetails.lastname} ${userDetails.firstname}`,
    },
    customizations: {
      title: "WrenchBoard",
      description: "Add Credit Payment",
      logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
    },
  };

  const fwConfig = {
    ...config,
    text: "Proceed",
    callback: (response) => {
      debouncedSuccessPayment(); //delays the call for 5 secs

      setTimeout(() => {
        closePaymentModal();
        setConfirmCredit((prev) => ({
          ...prev,
          show: {
            awaitConfirm: { loader: false, state: false },
            acceptConfirm: { loader: false, state: true },
          },
          data: response,
        }));
      }, 1500);
    },
  };

  const onSuccessPayment = () => {
    setRequestStatus({ message: "", loading: true, status: false });
    const reqData = { tx_ref: __confirmData?.credit_reference };
    console.log("**** onSuccessPayment **** THIS WAS REACHED");
    apiURL
      .resultTopUp(reqData)
      .then((res) => {
        if (res.data.internal_return < 0) {
          setRequestStatus({
            message: "Could not finish transaction",
            loading: false,
            status: false,
          });
        }
      })
      .catch((err) => {
        setRequestStatus({
          message: "Opps! An Error Occured",
          loading: false,
          status: false,
        });

        setTimeout(() => {
          setConfirmCredit((prev) => ({
            ...prev,
            show: {
              awaitConfirm: { loader: false, state: false },
              acceptConfirm: { loader: false, state: true },
            },
            data: err,
          }));
        }, 1500);
        toast.success("Opps! something went wrong");
      });
  };

  const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);

  /**
   * Handles the process of making a payment using a previously saved card.
   * Updates the state to show a loader while the payment is being processed,
   * sends a request to the server to make the payment, and updates the state with the response.
   * If the payment is successful, it also dispatches an action to reload the wallet table.
   */
  const handlePrevCard = async () => {
    try {
      // Show loader while the payment is being processed
      setConfirmCredit((prev) => ({
        ...prev,
        show: {
          acceptConfirm: { loader: true },
        },
      }));

      // Extract necessary data from confirmCredit and confirmCardDetails objects
      const { amount, credit_reference, currency } = __confirmData;
      const { card_uid } = __confirmCardDetails;

      // Create request data object with required parameters for making the payment
      const reqData = {
        amount: amount * 100,
        card_uid,
        credit_reference,
        currency,
      };

      // Send request to server to make the payment using getPaidPrevCard method of usersService
      const res = await apiURL.getPaidPrevCard(reqData);
      const _response = res.data;

      // If internal_return value in the response is less than 0, hide the loader and return
      if (_response.internal_return < 0) {
        setConfirmCredit((prev) => ({
          ...prev,
          show: {
            acceptConfirm: { loader: false },
          },
        }));
        return;
      }

      // Update state to show the acceptConfirm state and the response data
      setTimeout(() => {
        setConfirmCredit((prev) => ({
          ...prev,
          show: {
            awaitConfirm: { loader: false, state: false },
            acceptConfirm: { loader: false, state: true },
          },
          data: _response,
        }));
      }, 1500);
    } catch (error) {
      // Handle error and hide the loader
      setConfirmCredit((prev) => ({
        ...prev,
        show: {
          acceptConfirm: { loader: false },
        },
      }));
      console.log(error);
    }
  };

  /**
   * Handles the payment process when a new card is used.
   * @async
   */
  const handleNewCard = async () => {
    try {
      // Extract necessary data from __confirmData and __confirmCardDetails
      const { amount, credit_reference, uid } = __confirmData;
      const { address, cardNum, cvv, expirationMonth, expirationYear } =
        __confirmCardDetails;

      // Set loading state to indicate payment is being processed
      setConfirmCredit((prev) => ({
        ...prev,
        show: {
          acceptConfirm: { loader: true },
        },
      }));

      // Prepare request data
      const reqData = {
        amount: amount * 100,
        cardnumber: cardNum.replace(/\s/g, ""),
        credit_reference,
        cvc: cvv,
        description: address,
        exp_month: expirationMonth,
        exp_year: expirationYear,
        paymenttype: 100,
        uid,
      };

      // Send request to server to process payment
      const res = await apiURL.getPaidNewCard(reqData);
      const _response = res.data;

      // Handle response from server
      if (res.data.internal_return < 0) {
        // Payment could not be completed
        setConfirmCredit((prev) => ({
          ...prev,
          show: {
            awaitConfirm: { loader: false, state: false },
            acceptConfirm: { loader: false, state: true },
          },
          data: _response,
        }));
      } else {
        // Payment was successful
        setTimeout(() => {
          setConfirmCredit((prev) => ({
            ...prev,
            show: {
              awaitConfirm: { loader: false, state: false },
              acceptConfirm: { loader: false, state: true },
            },
            data: _response,
          }));
        }, 1500);
      }
    } catch (error) {
      // Handle error during payment process
      setConfirmCredit((prev) => ({
        ...prev,
        show: {
          acceptConfirm: { loader: false },
        },
      }));
      setTimeout(() => onClose, 10000);
      console.log(error);
    }
  };

  const getBack = () => {
    setConfirmCredit((prev) => ({
      ...prev,
      show: {
        awaitConfirm: { loader: false, state: false },
        acceptConfirm: { loader: false, state: false },
      },
      data: {},
    }));
  };

  return (
    <div className="content-wrapper w-full h-[32rem]">
      <div className="w-full mb-10">
        <div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
          <div className="px-4 md:p-8 py-4 add-fund-info">
            <div className="field w-full mb-3 min-h-[45px]">
              {confirmCredit?.show?.awaitConfirm?.state && (
                <div className="flex flex-col gap-2">
                  <AmountSection
                    currency={__confirmData?.currency}
                    amount={__confirmData?.amount}
                    country={__confirmCountry}
                  />
                  <TransactionFeeSection
                    currency={__confirmData?.currency}
                    fee={__confirmData?.fee}
                    country={__confirmCountry}
                  />
                  <TotalSection
                    currency={__confirmData?.currency}
                    amount={__confirmData?.amount}
                    fee={__confirmData?.fee}
                    country={__confirmCountry}
                  />
                  {__confirmCountry === "US" && (
                    <div className="flex items-center gap-8">
                      <label
                        htmlFor="payment"
                        className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
                      >
                        Payment Method
                      </label>
                      <span className="text-[#181c32] dark:text-white">
                        <ThePaymentText
                          value={__confirmCardDetails}
                          type={__confirmData?.cardType}
                        />
                      </span>
                    </div>
                  )}
                  <div
                    className={`${
                      __confirmCountry === "US"
                        ? "gap-[3.7rem]"
                        : "gap-[1.81rem]"
                    } flex items-center`}
                  >
                    <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
                      Reference No
                    </h1>
                    <span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
                      {__confirmData?.credit_reference}
                    </span>
                  </div>
                </div>
              )}
            </div>
          </div>

          <div
            className={
              __confirmCountry === "US" ? "min-h-[96px]" : "min-h-[157px]"
            }
          ></div>
          <hr />
          <div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
            <button
              className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
              onClick={getBack}
            >
              Back
            </button>
            {__confirmCountry === "US" && (
              <button
                className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full"
                onClick={
                  __confirmData?.cardType === "prev"
                    ? handlePrevCard
                    : handleNewCard
                }
              >
                {confirmCredit?.show?.acceptConfirm?.loader ? (
                  <LoadingSpinner size="6" color="sky-blue" />
                ) : (
                  "Proceed"
                )}
              </button>
            )}
            {__confirmCountry === "NG" && (
              <FlutterWaveButton
                {...fwConfig}
                className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
              />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

export default ConfirmAddFund;
