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

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

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

export const BuySpendController = ({
  render,
  renderErrorComponent,
}: BuySpendRenderProps) => {
  const { request, resetRefreshCount } = useUpdatePreview({
    mode: "from",
    type: "buy",
  });
  // const { control } = BuySellContext.useFormContext();
  // const [ lastChangedField] = useWatch({
  //   name: ["fromAsset", "toAsset", "lastChangedField"],
  //   control,
  //   defaultValue: {
  //     lastChangedField: "from",
  //   },
  // });
  const { setValue, clearErrors, register } = BuySellContext.useFormContext();
  const { lastChangedField } = BuySellContext.useWatch();
  // console.log({1:lastChangedField})
  const { getValues } = BuySellContext.useFormContext();
  const { allAssets } = useAssets();
  const { filterPrice, getMaxSize, selectedCurrency } = useBuySellMarketConfigs(
    {
      mode: "from",
    },
  );
  const { truncFix } = useDisplayDecimalDigits();
  const { minimumFrom, maximumFrom, checkAmount } =
    useBuySellAmountValidation();

  const assets = useMemo(() => {
    return allAssets?.filter((i) => i.canCharge);
  }, [allAssets]);

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

  register("shouldCharge");

  const clearFormErrors = useCallback(
    (errors: FieldErrors<BuySellFormProps>) => {
      if (Object.values(errors).length > 0) {
        clearErrors();
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [],
  );

  const rules = useMemo(
    () => ({
      validate: {
        check: (value: string | null | undefined) =>
          checkAmount({
            value,
            mode: "from",
          }),
      },
    }),
    [checkAmount],
  );
  const renderForm: ControllerProps<BuySellFormProps, "fromAmount">["render"] =
    useCallback(
      ({ field: { onChange, value, ...rest }, formState, fieldState }) => {
        return (
          <>
            {render({
              field: {
                value: value,
                assets: assets || [],
                availableRemain: truncFix(
                  selectedCurrency?.availableRemain || 0,
                  selectedCurrency?.symbol,
                ),
                minQuantity: minimumFrom || 0,
                maxQuantity: maximumFrom || 0,
                asset: selectedCurrency,
                hasError: value ? !!fieldState.error : false,
                getMaxSize: getMaxSize,
                async onSelect(asset?: Asset) {
                  if (selectedCurrency?.symbol !== asset?.symbol) {
                    onChange("");
                    setValue("toAmount", "");
                    const symbol = await new Promise<string | undefined>(
                      (res) => {
                        res(asset?.symbol);
                      },
                    );
                    setValue("fromAsset", symbol);
                    clearFormErrors(formState.errors);
                  }
                },
                onFocus() {
                  lastChangedField !== "from" &&
                    setValue("lastChangedField", "from");
                },
                onChange(value) {
                  onChange(value);
                  if (value === "") {
                    setValue("toAmount", "");
                  }
                  clearFormErrors(formState.errors);
                  request();
                  resetRefreshCount();
                  lastChangedField !== "from" &&
                    setValue("lastChangedField", "from");
                },
                stepSize: filterPrice?.tickSize,
                ...rest,
              },
            })}
            {renderErrorComponent &&
              renderErrorComponent(
                fieldState.error ? fieldState.error.message : "",
              )}
          </>
        );
      },
      // eslint-disable-next-line react-hooks/exhaustive-deps
      [
        assets,
        clearFormErrors,
        filterPrice?.tickSize,
        getMaxSize,
        lastChangedField,
        maximumFrom,
        minimumFrom,
        render,
        selectedCurrency,
        truncFix,
        resetRefreshCount,
      ],
    );

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