import React, { ReactNode, useCallback, useEffect, useMemo } from "react";
import {
  ControllerProps,
  ControllerRenderProps,
  FieldErrors,
} from "react-hook-form";

import { Asset, useAssets, useDefaultCurrency } from "../..";
import { useDisplayDecimalDigits } from "../useDisplayDecimalDigits";
import { BuySellContext, BuySellFormProps } from "./context";
import { useBuySellAmountValidation } from "./useBuySellAmountValidation";
import { useBuySellMarketConfigs } from "./useBuySellConfigs";
import { useUpdatePreview } from "./useUpdatePreview";

type BuyRecieveRenderProps = {
  render: (state: {
    field: ControllerRenderProps<BuySellFormProps, "toAmount"> & {
      assets: Asset[];
      asset?: Asset;
      minQuantity: number;
      maxQuantity: number;
      hasError?: boolean;
      availableRemain: number;
      onSelect?: (value?: Asset | undefined) => void;
      onFocus?: (e: any) => void;
      getMaxSize?: (value: number) => string | number;
      stepSize?: number;
    };
  }) => React.ReactElement;
  renderErrorComponent?: (message?: string) => ReactNode;
};

export const BuyRecieveController = ({
  render,
  renderErrorComponent,
}: BuyRecieveRenderProps) => {
  const { lastChangedField } = BuySellContext.useWatch();
  const { allAssets } = useAssets();
  const { request, resetRefreshCount } = useUpdatePreview({
    mode: "to",
    type: "buy",
  });
  // const { control } = BuySellContext.useFormContext();

  // const [lastChangedField] = useWatch({
  //   name: ["fromAsset", "toAsset", "lastChangedField"],
  //   control,
  //   defaultValue: {
  //     lastChangedField: "from",
  //   },
  // });
  // console.log({2:lastChangedField})

  const { filterLotSize, getMaxSize, selectedCurrency } =
    useBuySellMarketConfigs({
      mode: "to",
    });

  const { setValue, clearErrors, register, getValues } =
    BuySellContext.useFormContext();
  const { defaultCrypto } = useDefaultCurrency();

  register("shouldCharge");

  const assets = useMemo(
    () =>
      allAssets?.filter(
        (item) => item.canTrade && item.currencyType === "Crypto",
      ) || [],
    [allAssets],
  );

  const { truncFix } = useDisplayDecimalDigits();

  useEffect(() => {
    const { toAsset } = getValues();
    if (toAsset === undefined) {
      const symbol = assets?.find(
        ({ symbol }) => symbol === defaultCrypto,
      )?.symbol;
      setValue("toAsset", symbol);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [assets]);

  const { checkAmount, minimumTo, maximumTo } = useBuySellAmountValidation();

  const clearFormErrors = useCallback(
    (errors: FieldErrors<BuySellFormProps>) => {
      if (Object.values(errors).length > 0) {
        clearErrors();
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [],
  );
  const rules = useMemo(() => {
    return {
      validate: {
        check: (value: string | null | undefined) =>
          checkAmount({
            value,
            mode: "to",
          }),
      },
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [checkAmount]);

  const renderForm: ControllerProps<BuySellFormProps, "toAmount">["render"] =
    useCallback(
      ({ field: { onChange, value, ...rest }, formState, fieldState }) => {
        return (
          <>
            {render({
              field: {
                value: value,
                assets,
                availableRemain: truncFix(
                  selectedCurrency?.availableRemain || 0,
                  selectedCurrency?.symbol,
                ),
                minQuantity: minimumTo || 0,
                maxQuantity: maximumTo || 0,
                asset: selectedCurrency,
                hasError: value ? !!fieldState.error : false,
                getMaxSize,
                async onSelect(asset?: Asset) {
                  if (selectedCurrency?.symbol !== asset?.symbol) {
                    onChange("");
                    setValue("fromAmount", "");
                    const symbol = await new Promise<string | undefined>(
                      (res) => {
                        res(asset?.symbol);
                      },
                    );
                    setValue("toAsset", symbol);
                    clearFormErrors(formState.errors);
                  }
                },
                onFocus() {
                  lastChangedField !== "to" &&
                    setValue("lastChangedField", "to");
                },
                onChange(value) {
                  if (value === "") {
                    setValue("fromAmount", "");
                  }
                  clearFormErrors(formState.errors);
                  request();

                  resetRefreshCount();
                  onChange(value);
                  lastChangedField !== "to" &&
                    setValue("lastChangedField", "to");
                },
                stepSize: filterLotSize?.stepSize,
                ...rest,
              },
            })}
            {renderErrorComponent &&
              renderErrorComponent(
                fieldState.error ? fieldState.error.message : "",
              )}
          </>
        );
      },
      // eslint-disable-next-line react-hooks/exhaustive-deps
      [
        assets,
        clearFormErrors,
        getMaxSize,
        lastChangedField,
        render,
        selectedCurrency,
        truncFix,
        minimumTo,
        maximumTo,
        resetRefreshCount,
      ],
    );

  return (
    <>
      <BuySellContext.Controller
        name="toAmount"
        rules={rules}
        render={renderForm}
      />
    </>
  );
};
