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 SellRecieveRenderProps = {
  render: (state: {
    field: ControllerRenderProps<BuySellFormProps, "toAmount"> & {
      assets: Asset[];
      asset?: Asset;
      minQuantity: number;
      hasError?: boolean;
      maxQuantity: number;
      availableRemain: number;
      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 SellRecieveController = ({
  render,
  renderErrorComponent,
}: SellRecieveRenderProps) => {
  // const { control } = BuySellContext.useFormContext();
  // const [ lastChangedField] = useWatch({
  //   name: ["fromAsset", "toAsset", "lastChangedField"],
  //   control,
  //   defaultValue: {
  //     lastChangedField: "from",
  //   },
  // });

  const { lastChangedField } = BuySellContext.useWatch();
  // console.log({4:lastChangedField})
  const { allAssets } = useAssets();
  const { resetRefreshCount, request } = useUpdatePreview({
    mode: "to",
    type: "sell",
  });
  const { filterPrice, getMaxSize, selectedCurrency } = useBuySellMarketConfigs(
    {
      mode: "to",
    },
  );

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

  register("shouldCharge");

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

  const { truncFix } = useDisplayDecimalDigits();

  useEffect(() => {
    const { toAsset } = getValues();
    if (toAsset === undefined) {
      const symbol = assets?.[0]?.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(
    () => ({
      validate: {
        check: (value: string | null | undefined) =>
          checkAmount({
            value,
            mode: "to",
          }),
      },
    }),
    [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: filterPrice?.tickSize,
                ...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}
      />
    </>
  );
};
