/* eslint-disable no-alert */
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-unused-expressions */
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable promise/always-return */
/* eslint-disable promise/catch-or-return */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable camelcase */
import "../css/pay_domain.css";

import { Button, Form, Modal, Select, Switch, Tooltip } from "antd";
import BigNumberNoEther from "bignumber.js";
import classNames from "classnames";
import { BigNumber } from "ethers/lib/ethers";
import { ReactNode, useEffect, useMemo, useState } from "react";
import Countdown, { zeroPad } from "react-countdown";
import { useTranslation } from "react-i18next";
import { ReactSVG } from "react-svg";
import { useAccount, useNetwork } from "wagmi";

import icon_arrow_down from "../assets/icons/icon_arrow_down.svg";
import icon_idc_ploygon_token from "../assets/icons/icon_idc_ploygon_token.svg";
import matic_token from "../assets/icons/matic-token.svg";
import { EnsProvider } from "./components/BNSProvider";
import FontIcon from "./components/PayDomain/components/FontIcon";
import ImageSkeleton from "./components/PayDomain/components/ImageSkeleton";
import addresses from "./components/PayDomain/contracts/contracts";
import { ApprovalState, useApproveCallback } from "./components/PayDomain/hooks/useApprove";
import useBiu from "./components/PayDomain/hooks/useBiu";
import useNotification from "./components/PayDomain/hooks/useNotification";
import { getAddress } from "./components/PayDomain/utils/util";

enum Status {
  Mint = 1,
  Minting = 2,
  MintFail = 3,
  MintSuccess = 4,
}
type DataType = {
  biuName: string;
  inviteName?: string;
  id?: string;
  createTime?: number;
};
interface Props {
  biuName?: string;
  open: boolean;
  setOpen: (val: boolean) => void;
  data: DataType;
  success?: () => void;
  fail?: (err: any) => void;
}
type ListType = { label: ReactNode; value: string; icon: string; coin: string; decimal: number };
export function PayModal(props: Props) {
  const [showCoundown, setShowCoundown] = useState(false);
  const { open, setOpen, data, success, fail } = props;
  const { biuName, inviteName, createTime, id } = data;
  const [priceLoading, setPriceLoading] = useState(false);
  const [loading, setLoading] = useState(false);
  const { successTip, failedTip } = useNotification();
  const { chain } = useNetwork();
  const [check, setCheck] = useState(true);
  const [item, setItem] = useState<ListType>({ label: "MATIC", value: "0x0", icon: "", coin: "MATIC", decimal: 18 });
  const [inviter] = useState(inviteName || id || "");
  const { t, i18n } = useTranslation();

  const [status, setStatus] = useState(Status.Mint);
  const { balance, prices, registerName, waitTransaction, getPrices, balanceMatic, getControlContact, switchChain, chainID } = useBiu();
  const { address } = useAccount();
  const [price, setPrice] = useState<BigNumber>(BigNumber.from(0));
  const [formatPrices, setFormatPrices] = useState<string[]>(["0", "0"]);
  const [controlContact, setControlContact] = useState<string>("");
  const icons: any = { MATIC: matic_token, USDT: icon_idc_ploygon_token };
  const [form] = Form.useForm();

  const [approveState, approve, approveLoading] = useApproveCallback(new BigNumberNoEther(price.toString()), item.value, controlContact);
  const items = [
    { coin: "MATIC", value: "0x0", icon: matic_token, decimal: 18 },
    { coin: "USDT", value: getAddress(addresses.usdt, 137), icon: icon_idc_ploygon_token, decimal: 6 },
  ];

  useEffect(() => {
    getControlContact().then((res: any) => {
      setControlContact(res);
    });
  }, [chain?.id]);

  useEffect(() => {
    const ret = prices.map((el, i) => {
      const item = items[i];
      if (item.value === "0x0") {
        return new BigNumberNoEther(el.toString())
          .div(10 ** item.decimal)
          .times(1.001)
          .toFixed(2);
      }
      return new BigNumberNoEther(el.toString()).div(10 ** item.decimal).toFixed(2);
    });

    setFormatPrices(ret);
  }, [prices]);

  const chainOptions = useMemo(() => {
    const list: ListType[] = [];
    items.forEach((i) => {
      const obj = {
        label: (
          <div style={{ display: "flex", alignItems: "center" }}>
            <ImageSkeleton style={{ width: "30px", height: "30px", borderRadius: "50%", marginRight: "5px" }} url={i.icon} />
            <span>{i.coin}</span>
          </div>
        ),
        value: i.value,
        icon: i.icon,
        coin: i.coin,
        decimal: i.decimal,
      };
      list.push(obj);
    });
    return list;
  }, []);

  const renderBtnText = useMemo(() => {
    let text = t("modal.ens.Register");
    if (item.value !== "0x0" && approveState !== ApprovalState.APPROVED) {
      text = t("modal.ens.SetSpendingCap");
    }
    return text;
  }, [approveState, item.value, t]);
  const onFinish = async (values: any) => {
    if (`${chain?.id}` !== chainID) {
      switchChain();
      return;
    }
    if (item.coin === "MATIC" && new BigNumberNoEther(formatPrices[0]).isGreaterThan(balanceMatic)) {
      failedTip(`MATIC${t("modal.ens.InsufficientBalance")}`);
      return;
    }
    if (item.coin !== "MATIC" && new BigNumberNoEther(formatPrices[1]).isGreaterThan(balance)) {
      failedTip(`USDT${t("modal.ens.InsufficientBalance")}`);
      return;
    }

    setLoading(true);

    try {
      if (item.value !== "0x0" && approveState !== ApprovalState.APPROVED) {
        await approve();
        setLoading(false);
        return;
      }
      let latestPrice: BigNumber;
      const latestPriceRes: BigNumber[] | [BigNumber, BigNumber] = await getPrices(biuName, false);
      if (item.value === "0x0") {
        latestPrice = latestPriceRes[0];
      } else {
        latestPrice = latestPriceRes[1];
      }
      const resRegister: any = await registerName(biuName, (inviter || ``).trim(), address || "", item.coin, latestPrice, check);

      const registerStatus = await waitTransaction(resRegister);
      setLoading(false);

      if (registerStatus) {
        setStatus(Status.MintSuccess);
        successTip(t("Success!"));
      } else {
        setStatus(Status.MintFail);
        failedTip(t("modal.ens.SorryMintFailed"));
      }
      setOpen(false);
      success && success();
    } catch (error) {
      console.error(error, "resRegister");
      failedTip("Fail!");
      fail && fail(error);

      setLoading(false);
    }
  };
  useEffect(() => {
    if (inviteName) {
      form.setFieldValue("inviter", inviteName);
    }
  }, [inviteName]);
  useEffect(() => {
    if (form) {
      form.setFieldsValue({ coin: "0x0" });
      setPriceLoading(true);
      getPrices(biuName, true)
        .then((res: any) => {
          setPrice(res[0]);
          setPriceLoading(false);
        })
        .catch((error) => {
          console.error(error, "getPrice");
          setPriceLoading(false);
        });
    }
  }, [biuName, open]);

  return (
    <EnsProvider>
      <Modal
        rootClassName="payModal_BiuToll"
        visible={open}
        onCancel={() => {
          setOpen(false);
        }}
        title={t("modal.ens.Register")}
        footer={null}
      >
        <div className="BiuToll">
          <div className="title">
            <ImageSkeleton className="name_img" url={`https://metadata.biubiu.id/preview/${biuName}`} />
            <div className="title_info">
              {biuName}
              <div className="coin_ballance_show">
                <ImageSkeleton className="coin_img" alt="" url={icons[item.coin]} />
                {priceLoading ? (
                  <Button loading={priceLoading} style={{ width: 40, height: 26 }} />
                ) : (
                  `${item.value === "0x0" ? formatPrices[0] : formatPrices[1]}  `
                )}
                {item.value === "0x0" && <span>（ {`≈${formatPrices[1]}`} USD ）</span>}
              </div>
            </div>
          </div>

          <Form className="form" form={form} onFinish={onFinish}>
            <div className="form_body">
              <div className="itemWraps">
                <div className="label">{t("modal.ens.Token")}</div>
                <Select
                  value={item.value}
                  onChange={async (value, item) => {
                    try {
                      // @ts-ignore
                      setItem(item);
                      if (value === "0x0") {
                        setPrice(prices[0]);
                      } else {
                        setPrice(prices[1]);
                      }
                    } catch (error) {
                      console.log(error, "error");
                    }
                  }}
                  placement="bottomRight"
                  className="select_coin"
                  popupClassName="coin_select_pop"
                  suffixIcon={<ReactSVG src={icon_arrow_down} />}
                  options={chainOptions}
                />
              </div>
              {inviter && (
                <div className="itemWraps">
                  <p>{t("modal.ens.Inviter")}</p>
                  <div className="invertRightWraps">
                    <p>{inviter}</p>
                    <p className="pBottom">{t("modal.ens.SaveOnRegistrationFee")}</p>
                  </div>
                </div>
              )}
              <div className="itemWraps">
                <div className="label">
                  {t("modal.ens.UseAsPrimaryName")}
                  <Tooltip rootClassName="tips_pop" title={t("modal.ens.ThisLinksYourAddress")}>
                    <FontIcon size={16} color="#7D7E81" type="icon-shuoming1" />
                  </Tooltip>
                </div>
                <Switch
                  className="switch"
                  onChange={(e) => {
                    setCheck(e);
                  }}
                  checked={check}
                />
              </div>

              <div className="itemWraps">
                <div className="label">{t("modal.ens.totalCost")}</div>
                {new BigNumberNoEther(item.value === "0x0" ? formatPrices[0] : formatPrices[1]).multipliedBy(inviter ? 0.95 : 1).toFixed(2)}{" "}
                {item.coin}
              </div>
              <div className={classNames("itemWraps", "balance")}>
                <div className="label" />
                {`${t("modal.ens.balance")}:${item.coin === "MATIC" ? balanceMatic : balance} ${item.coin}`}
              </div>
            </div>
            <div className={classNames("countdown", { show: showCoundown })}>
              {createTime && createTime > 0 && (
                <>
                  {t("modal.ens.RemainingPaymentTime")}{" "}
                  <ICutDown
                    change={(val) => {
                      setShowCoundown(val);
                    }}
                    time={createTime}
                  />
                </>
              )}
            </div>
            <Button
              disabled={priceLoading}
              loading={approveLoading || loading}
              className={classNames("save_btn", { disabled: priceLoading })}
              htmlType="submit"
              shape="round"
              type="primary"
            >
              {renderBtnText}
            </Button>
          </Form>
        </div>
      </Modal>
    </EnsProvider>
  );
}

interface ICutDownProps {
  time: number;
  change: (val: boolean) => void;
}

function ICutDown(props: ICutDownProps) {
  const { time, change } = props;
  const timeRenderer = ({ hours, minutes, seconds, days }: any) => {
    return (
      <div className={`${"count_item"} count_item_box`}>
        <span>{zeroPad(days)}</span>
        <span>:</span>
        <span>{zeroPad(hours)}</span>
        <span>:</span>
        <span>{zeroPad(minutes)}</span>
        <span>:</span>
        <span>{zeroPad(seconds)}</span>
      </div>
    );
  };
  return (
    <Countdown
      onTick={(e) => {
        if (e.total > 0) {
          change(true);
        } else {
          change(false);
        }
      }}
      onMount={(e) => {
        if (e.total > 0) {
          change(true);
        } else {
          change(false);
        }
      }}
      onComplete={() => {
        change && change(false);
      }}
      date={time * 1000 + 10 * 60 * 1000}
      renderer={timeRenderer}
    />
  );
}
