/**
 * 下单面板
 */
import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
  useImperativeHandle,
  forwardRef,
  ForwardRefRenderFunction,
  Fragment
} from "react";
import {
  PlaceOrderTypeTab,
  OrderTypeTab,
  AvbBalance,
  OrderValue,
  OrderValueProps,
  Buttons,
  CenterQuantity,
  CloseValue
} from "../Form";
import { OrderTypeEnum, OrderSideEnum, TimeInForceEnum, PriceSourceEnum } from "@shared/types";
import { FuturesFormProps, IPlaceOrderParams } from "./interface";
import Slider from "@components/Slider";
import type { IFormatCurrentPair } from "@shared/types/interface";
import {
  getQuantityByCost,
  getCostByQuantity,
  getValueByContr,
  getRateValue,
  getContrByValue
} from "@utils/contractRules";
import { getPositionSide, getPositionSideWithSideText, formatAvbBalance, _DEFAULT } from "./helper";
import { formatFloor, toDefaultNumber } from "@utils/FormatNumber";
import { notification } from "@atomintl/aui-next";
import { useBaseOn, useOrderPrice, useMaxInputQuantity } from "./hooks";
import { PlaceOrderInput, InputType } from "../Form";
import { PriceInput } from "@components/PlaceOrder/Form/PlaceOrderInput/PriceInput";
import { QuantityInput } from "@components/PlaceOrder/Form/PlaceOrderInput/QuantityInput";
import { PriceSourceSelect } from "@components/PlaceOrder/Form/PlaceOrderInput/SuffixPrice/PriceSourceSelect";
import PostOnlyAndTimeInForce from "./Form/PostOnlyAndTimeInForce";

const Form: ForwardRefRenderFunction<{ reset: () => void }, FuturesFormProps> = (props, ref) => {
  const { closeValues, openBaseQty, lastPrice, buyOnePrice, sellOnePrice, isLogin = false } = props;

  const currentPair = props.currentPair ?? ({} as IFormatCurrentPair);
  const {
    settleCurrency,
    base,
    quote,
    tickSizeScale,
    tickSizeStep,
    costSizeScale = 4,
    ctValScale = 4,
    ctVal
  } = currentPair;

  const init = useMemo(() => currentPair?.symbol?.length, [currentPair?.symbol]);
  const avbBalance = useMemo(() => {
    return formatAvbBalance(props.avbBalance, costSizeScale);
  }, [props.avbBalance, costSizeScale]);

  const leverage = useMemo(() => {
    // 不需要格式化计算，只要格式化展示
    return props.leverage ?? 1;
  }, [props.leverage]);

  const takerRate = useMemo(() => {
    return toDefaultNumber(currentPair.takerRate);
  }, [currentPair.takerRate]);

  // 输入框
  const [inputValues, setInputValues] = useState({
    price: "",
    triggerPrice: "",
    quantity: "",
    sliderValue: 0
  });

  const [triggerPxType, setPriceSource] = useState(PriceSourceEnum.MarkPrice);
  const [timeInForce, setTimeInForce] = useState(TimeInForceEnum.GTC);
  const [postOnly, setPostOnly] = useState(false);

  const [orderType, setOrderType] = useState(OrderTypeEnum.Limit);
  const [isClose, setIsClose] = useState(false);

  const qtyInputRef = useRef<HTMLInputElement>(null);
  const priceInputRef = useRef<HTMLInputElement>(null);
  const orderValueRef = useRef<OrderValueProps>(null);

  // 多空方向的数量和成本
  const [sideQuantity, setSideQuantity] = useState(_DEFAULT);
  const [sideCost, setSideCost] = useState(_DEFAULT);
  const isCondition = useMemo(
    () => orderType === OrderTypeEnum.TriggerLimit || orderType === OrderTypeEnum.TriggerMarket,
    [orderType]
  );
  const baseOn = useBaseOn(isClose, isCondition, openBaseQty);
  const orderPrice = useOrderPrice(inputValues.price, inputValues.triggerPrice, buyOnePrice, sellOnePrice, orderType);

  const handleClearQuantityInput = (focus?: boolean) => {
    setInputValues({
      ...inputValues,
      sliderValue: 0,
      quantity: ""
    });
    if (focus) qtyInputRef.current?.focus?.();
    setSideQuantity(_DEFAULT);
    setSideCost(_DEFAULT);
  };

  const onChangePlaceOrderType = (bool: boolean) => {
    setIsClose(bool);
    handleClearQuantityInput();
    setOrderType(OrderTypeEnum.Limit);
  };

  const onChangeOrderType = (type: OrderTypeEnum) => {
    console.log(type, "订单类型");
    setOrderType(type);
    handleClearQuantityInput();
  };

  const onChangeQuantityInput = (val: string) => {
    setInputValues({
      ...inputValues,
      quantity: val,
      sliderValue: 0
    });
    if (baseOn) {
      setSideQuantity({
        buy: val,
        sell: val,
        show: false
      });
    } else {
      setSideCost({
        buy: val,
        sell: val,
        show: false
      });
    }
  };

  // 最大数量value
  const maxInputQuantity = useMaxInputQuantity(
    isClose,
    closeValues,
    orderPrice,
    avbBalance,
    ctVal,
    ctValScale,
    takerRate,
    leverage
  );

  const onChangeBaseQuantity = (bool: boolean) => {
    // 按面值/成本下单

    handleClearQuantityInput();
    props.handleBaseOnChange?.(bool);
  };

  const onChangePriceSource = useCallback((val: PriceSourceEnum) => {
    setPriceSource(val);
  }, []);

  const handleSliderChange = (rate: number) => {
    qtyInputRef.current?.blur?.();
    let cost = "";
    if (rate && !baseOn && avbBalance) {
      // 计算成本
      cost = formatFloor(getRateValue({ rate, max: avbBalance }), costSizeScale);
      setSideCost({
        buy: cost,
        sell: cost,
        show: toDefaultNumber(cost) > 0
      });
    }

    // 清空数量输入框
    setInputValues({
      ...inputValues,
      quantity: cost,
      sliderValue: rate
    });
  };

  const onChangePriceInput = (val: string, key: InputType, focus?: boolean) => {
    console.log(val, key, "更新价格");
    setInputValues({
      ...inputValues,
      [key]: val
    });
    if (focus) {
      priceInputRef?.current?.focus?.();
    }
  };

  const sideText = useMemo(() => {
    return getPositionSideWithSideText(isClose);
  }, [isClose]);

  const isMarket = useMemo(
    () => orderType === OrderTypeEnum.Market || orderType === OrderTypeEnum.TriggerMarket,
    [orderType]
  );

  useImperativeHandle(ref, () => ({
    reset: () => {
      // 清除下单面板(场景下单成功)
      setInputValues({
        price: "",
        triggerPrice: "",
        quantity: "",
        sliderValue: 0
      });
      setSideCost(_DEFAULT);
      setSideQuantity(_DEFAULT);
    }
  }));

  const handlePlaceOrder = (side: OrderSideEnum) => {
    if (!init) return;
    // 限制价格
    const { price, triggerPrice, quantity, sliderValue } = inputValues;

    const isBuy = side === OrderSideEnum.Buy;
    const quantityValue = isBuy ? sideQuantity.buy : sideQuantity.sell;

    let message: null | string = null;
    if (!price && !isMarket) {
      message = "请输入价格";
    } else if (!triggerPrice && isCondition) {
      message = "请输入触发价格";
    } else if (!quantity && !sliderValue) {
      message = "请输入数量";
    }

    if (message) {
      return notification.error({ duration: 2000, message });
    }
    // 可开为0处理
    const orderQty = getContrByValue({
      value: quantityValue,
      multiplier: ctVal
    });

    const params: IPlaceOrderParams = {
      quantityValue,
      isClose,
      isBuy,
      isCondition,
      isMarket,
      sideText: isBuy ? sideText.buy : sideText.sell,
      side,
      positionSide: getPositionSide(isBuy, isClose),
      orderType,
      orderQty,
      cost: isBuy ? sideCost.buy : sideCost.sell,
      orderValue: orderValueRef?.current?.getOrderValue(side),
      postOnly,
      timeInForce,
      price,
      triggerPxType,
      ordPx: inputValues.triggerPrice
    };

    props.handlePlaceOrder?.(params);
  };
  useEffect(() => {
    // 滑块计算数量
    if (inputValues.sliderValue && baseOn) {
      const buy = getRateValue({ rate: inputValues.sliderValue, max: maxInputQuantity.maxBuyValue ?? 0 });
      const sell = getRateValue({ rate: inputValues.sliderValue, max: maxInputQuantity.maxSellValue ?? 0 });

      setSideQuantity({
        buy: formatFloor(buy, ctValScale),
        sell: formatFloor(sell, ctValScale),
        show: buy > 0 || sell > 0
      });
      console.log("计算数量:", buy, sell);
    }
  }, [inputValues.sliderValue, baseOn, maxInputQuantity.maxBuyValue, maxInputQuantity.maxSellValue, ctValScale]);

  useEffect(() => {
    if (!baseOn) {
      // 按成本下单。根据成本计算数量
      let buy = "",
        sell = "";
      const qtyBalance = toDefaultNumber(inputValues.quantity);

      if (qtyBalance) {
        buy = formatFloor(
          getQuantityByCost({
            balance: qtyBalance,
            price: orderPrice.buy,
            takerFee: takerRate,
            leverage
          }),
          ctValScale
        );
        sell = formatFloor(
          getQuantityByCost({
            balance: qtyBalance,
            price: orderPrice.sell,
            takerFee: takerRate,
            leverage
          }),
          ctValScale
        );
      }
      console.log("计算数量:", buy, sell);
      setSideQuantity({ buy, sell, show: false });
    }
  }, [baseOn, inputValues.quantity, orderPrice.buy, orderPrice.sell, ctValScale, takerRate]);

  useEffect(() => {
    if (baseOn && !isClose) {
      // 计算成本
      const buy = getCostByQuantity({
        price: orderPrice.buy,
        quantity: sideQuantity.buy,
        leverage,
        takerFee: takerRate
      });
      const sell = getCostByQuantity({
        price: orderPrice.sell,
        quantity: sideQuantity.sell,
        leverage,
        takerFee: takerRate
      });
      console.log("计算成本:", buy, sell);
      setSideCost({
        buy: formatFloor(buy, costSizeScale),
        sell: formatFloor(sell, costSizeScale),
        show: buy > 0 || sell > 0
      });
    }
  }, [
    baseOn,
    isClose,
    orderPrice.buy,
    orderPrice.sell,
    leverage,
    takerRate,
    costSizeScale,
    sideQuantity.buy,
    sideQuantity.sell
  ]);

  return (
    <div className="pt-[18px] px-[16px] pb-[30px] ">
      <PlaceOrderTypeTab onChangePlaceOrderType={onChangePlaceOrderType} value={isClose} />
      <OrderTypeTab onChangeOrderType={onChangeOrderType} orderType={orderType} hideCondition={isClose} />
      <div className="mb-[16px]">
        <AvbBalance coin={settleCurrency} value={avbBalance} scale={costSizeScale} isLogin={isLogin} />
      </div>

      <form action="" autoComplete="off">
        <div className="mb-[6px]">
          {isCondition ? (
            <PlaceOrderInput
              placeholder="触发价格"
              className="mb-[12px]"
              endAdornment={<PriceSourceSelect value={triggerPxType} onChangePriceSource={onChangePriceSource} />}
              onChange={val => onChangePriceInput(val, InputType.TriggerPrice)}
              value={inputValues.triggerPrice}
              limitInputStep={true}
              scale={tickSizeScale}
              step={tickSizeStep}
              name={InputType.TriggerPrice}
            />
          ) : (
            ""
          )}
          <PriceInput
            ref={priceInputRef}
            value={inputValues.price}
            quote={quote}
            scale={tickSizeScale}
            step={tickSizeStep}
            orderType={orderType}
            name={InputType.Price}
            onChangePriceInput={(val, focus) => onChangePriceInput(val, InputType.Price, focus)}
            triggerTypeChange={onChangeOrderType}
            lastPrice={lastPrice}
            optimumLevel={currentPair.optimumLevel}
          />
          <QuantityInput
            ref={qtyInputRef}
            value={inputValues.quantity}
            baseOn={baseOn}
            base={base}
            settleCurrency={settleCurrency}
            scale={baseOn ? ctValScale : costSizeScale}
            showCenter={sideQuantity.show && baseOn}
            disableCost={isCondition || isClose}
            isLogin={isLogin}
            sideQuantity={sideQuantity}
            name={InputType.Quantity}
            onChangeQuantityInput={onChangeQuantityInput}
            onChangeBaseQuantity={onChangeBaseQuantity}
            handleClearQuantityInput={handleClearQuantityInput}
          />

          {sideCost.show && baseOn ? (
            <div className="flex justify-between items-center">
              成本
              <div className="flex font-[500] text-[12px] ">
                <CenterQuantity buyText={sideCost.buy} sellText={sideCost.sell} className="mr-[4px]" />
                {baseOn ? settleCurrency : base}
              </div>
            </div>
          ) : (
            ""
          )}
        </div>
        <div className={`mb-[20px] px-[3px]`}>
          <Slider onSliderChange={handleSliderChange as any} sliderValue={inputValues.sliderValue}></Slider>
        </div>
        {isLogin ? (
          <Fragment>
            {isClose ? (
              <CloseValue buyValue={closeValues?.buy} sellValue={closeValues?.sell} scale={ctValScale} unit={base} />
            ) : baseOn ? (
              <OrderValue
                unit={settleCurrency}
                buyQuantity={sideQuantity.buy}
                sellQuantity={sideQuantity.sell}
                inputPrice={inputValues.price}
                triggerPrice={inputValues.triggerPrice}
                buyOne={buyOnePrice}
                sellOne={sellOnePrice}
                orderType={orderType}
                scale={costSizeScale}
                ref={orderValueRef}
              />
            ) : (
              ""
            )}
            <Buttons onClick={handlePlaceOrder} buyText={sideText.buy} sellText={sideText.sell} />
            <PostOnlyAndTimeInForce
              show={!isMarket}
              postOnlyValue={postOnly}
              timeInForceValue={timeInForce}
              setPostOnly={setPostOnly}
              setTimeInForce={setTimeInForce}
            />
          </Fragment>
        ) : null}
      </form>
    </div>
  );
};

export { FuturesFormProps, IPlaceOrderParams, IPlaceNormalOrderParams, IPlaceStopOrderParams } from "./interface";

export const FuturesForm = forwardRef(Form);
FuturesForm.defaultProps = {
  buyOnePrice: "17350",
  sellOnePrice: "17400",
  lastPrice: "17320"
};
