import { useCallback, useEffect, useRef } from "react";
import { useDebounce } from "reactjs-view-core";

import { useTranslation } from "react-i18next";
import { useAuth } from "react-oidc-js";
import { usePostOtcV1PublicOtcConvertPreview } from "../../services";
import { useAssets } from "../useAssets";
import { useDisplayDecimalDigits } from "../useDisplayDecimalDigits";
import { ConvertContext } from "./context";

const REFRESH_TIME = 8000;
const REFRESH_COUNT = 5;

export const useUpdatePreview = ({
  mode,
  type,
}: {
  mode: "from" | "to";
  type: "limit" | "market";
}) => {
  const {
    fromAmount,
    toAmount,
    lastChangedField,
    fromAsset,
    toAsset,
    isPreviewOpen,
  } = ConvertContext.useWatch();
  const [deobunceAmount] = useDebounce(
    500,
    mode === "from" ? fromAmount : toAmount,
  );
  const { userData } = useAuth();

  const { t } = useTranslation();
  const { setValue, setError } = ConvertContext.useFormContext();
  const { isValid } = ConvertContext.useFormState();
  const { getAssetBySymbol } = useAssets();
  const { truncFix } = useDisplayDecimalDigits();

  const { mutate: requestPreview } = usePostOtcV1PublicOtcConvertPreview({
    onSuccess: ({
      finalDestinationQuantity,
      finalSourceQuantity,
      sourceCurrencySymbol,
      destinationCurrencySymbol,
    }) => {
      if (mode === "from" && type === "market") {
        setValue(
          "toAmount",
          truncFix(
            finalDestinationQuantity,
            destinationCurrencySymbol,
          ).toString(),
        );
      } else {
        setValue(
          "fromAmount",
          truncFix(finalSourceQuantity, sourceCurrencySymbol).toString(),
        );
      }
      const availableRemain = sourceCurrencySymbol
        ? getAssetBySymbol(sourceCurrencySymbol)?.availableRemain || 0
        : 0;
      if (
        availableRemain < finalSourceQuantity &&
        isValid &&
        userData !== null
      ) {
        lastChangedField === "to" && setError("toAmount", { message: " " });
        return setError("fromAmount", { message: t("insufficientBalance") });
      }
    },
  });

  const request = useCallback(() => {
    if (
      deobunceAmount &&
      fromAsset &&
      toAsset &&
      lastChangedField === mode &&
      !isPreviewOpen
    ) {
      requestPreview({
        requestBody: {
          validityDurationInSecond: 10,
          sourceQuantity:
            lastChangedField === "from" ? Number(deobunceAmount) : undefined,
          destinationQunatity:
            lastChangedField === "to" ? Number(deobunceAmount) : undefined,
          destinationCurrencySymbol: toAsset,
          sourceCurrencySymbol: fromAsset,
        },
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    deobunceAmount,
    fromAsset,
    isPreviewOpen,
    lastChangedField,
    mode,
    requestPreview,
    toAsset,
  ]);
  const refreshCount = useRef(0);

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

  useEffect(() => {
    const interval = setInterval(() => {
      if (refreshCount.current >= REFRESH_COUNT) {
        return;
      }
      request();
      refreshCount.current = refreshCount.current + 1;
    }, REFRESH_TIME);

    return () => {
      if (interval) clearInterval(interval);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [deobunceAmount]);

  return {
    resetRefreshCount: () => (refreshCount.current = 0),
  };
};
