/**
 * @Author: ??
 * @Date: ??
 */
import React, { useCallback, useEffect, useImperativeHandle, useState } from "react";
import {
  AdjustingLeverModalProps,
  AdjustingLeverModalRefFuncProps,
  AdjustingLeverModalConfirmProps
} from "./interface";
import { Modal, ModalProps, NumberInput, Slider } from "../../index";
import { Minus } from "@icons/Minus";
import { Plus } from "@icons/Plus";
import IconCom from "@icons/IconCom";
import { PosiRadio } from "@components/AdjustingLeverModal/PosiRadio";
import {
  createAveragePoints,
  createMarks,
  findNearestTarget,
  originalNodes
} from "@components/AdjustingLeverModal/helpers";
import "./index.css";
import { invertObj } from "ramda";
import { MarginTypeEnum } from "@shared/types";
import { formatMoney, toDefaultNumber } from "@utils/FormatNumber";
/**
 * ### 引用方法
 * ```tsx
 * import { AdjustingLeverModal } from "@atomintl/exchange-ui";
 * ```
 */
export const AdjustingLeverModal: React.FC<AdjustingLeverModalProps & ModalProps> = props => {
  const {
    onConfirm,
    defaultLever,
    defaultOriginalNodes,
    initMarginType,
    disabledCross,
    disabledIsolated,
    open,
    askLimits
  } = props;
  const marks: any = createMarks(defaultOriginalNodes || originalNodes);
  const averagePoints = createAveragePoints(marks);
  const invertAveragePoints = invertObj(averagePoints);
  const marksKeys = Object.keys(marks)
    .map(Number)
    .sort((a, b) => a - b);
  const minLever = marksKeys[0];
  const maxLever = marksKeys[marksKeys.length - 1];
  const [step, setStep] = useState<number>(1);
  const [lever, setLever] = useState<number>(defaultLever ? averagePoints[defaultLever] : 1);
  const [notionalCap, setNotionalCap] = useState<number | string>();
  const [marginType, setMarginType] = useState<MarginTypeEnum>(initMarginType || MarginTypeEnum.Cross);
  const bulkingStep = (key: number) => {
    return (marksKeys[key + 1] - marksKeys[key]) / (marks[marksKeys[key + 1]].value - marks[marksKeys[key]].value);
  };
  const calcStep = (_lever: number, dir: "dec" | "inc") => {
    const isDec = dir === "dec";
    for (let k = 0; k < marksKeys.length - 2; k++) {
      ((_lever > marksKeys[k] && _lever < marksKeys[k + 1]) ||
        (isDec && _lever === marksKeys[k + 1]) ||
        (!isDec && _lever === marksKeys[k])) &&
        setStep(bulkingStep(k));
    }
  };

  const decreaseLever = () => {
    const currentLeverKey = Number(invertAveragePoints[lever]);
    if (currentLeverKey <= minLever) return;
    calcStep(lever, "dec");
    setLever(Number(averagePoints[currentLeverKey - 1]));
  };
  const increaseLever = () => {
    const currentLeverKey = Number(invertAveragePoints[lever]);
    if (currentLeverKey >= maxLever) return;
    calcStep(lever, "inc");
    setLever(Number(averagePoints[currentLeverKey + 1]));
  };
  const onOkCb = useCallback(() => {
    onConfirm?.({ lever: Number(invertAveragePoints[Number(lever)] || 1), marginType, notionalCap });
  }, [lever, marginType, notionalCap]);

  const tipFormatter = () => {
    return `${invertAveragePoints[Number(lever)] || 1}x`;
  };
  const onSliderChange = (v: number | number[]) => {
    calcStep(Number(v), "dec");
    const sortedAveragePointsKeys = Object.keys(invertAveragePoints)
      .map(Number)
      .sort((a, b) => a - b);
    const calibratedSliderValue = findNearestTarget(sortedAveragePointsKeys, Number(v));

    setLever(calibratedSliderValue);
  };

  const onValueUpdate = useCallback(
    (v: string | number) => {
      let _v = Number(v);
      // if (_v < minLever) _v = minLever
      if (_v > maxLever) _v = maxLever;
      setLever(averagePoints[_v]);
    },
    [averagePoints]
  );

  useImperativeHandle(props?.onRef, () => ({ onValueUpdate }));

  useEffect(() => {
    //set up initState
    if (open) {
      setStep(1);
      setLever(defaultLever ? averagePoints[defaultLever] : 1);
      setMarginType(initMarginType || MarginTypeEnum.Cross);
    }
  }, [open]);

  useEffect(() => {
    if (askLimits?.length) {
      const _initialLeverage = invertAveragePoints[lever];
      const _askLimits = askLimits?.sort(
        (a: any, b: any) => toDefaultNumber(a?.initialLeverage) - toDefaultNumber(b?.initialLeverage)
      );
      let _notionalCap = 0;
      for (let k = 0; k < _askLimits.length; k++) {
        _notionalCap = toDefaultNumber(_askLimits[k].notionalCap);
        if (toDefaultNumber(_initialLeverage) <= toDefaultNumber(_askLimits[k].initialLeverage)) {
          break;
        }
      }
      setNotionalCap(toDefaultNumber(_notionalCap));
    }
  }, [lever, askLimits]);

  return (
    <>
      <Modal
        title="调整杠杆"
        cancelText=""
        okText="确认"
        confirmConfig={{ color: "primary", className: "h-[48px]", size: "large" }}
        onOk={onOkCb}
        {...props}
      >
        <div>
          <PosiRadio
            marginType={marginType}
            onChange={setMarginType}
            disabledCross={disabledCross}
            disabledIsolated={disabledIsolated}
          />
          <div className="mt-[30px]">
            <div className="mb-[6px]">杠杆倍数</div>
            <div
              className="w-full h-[48px] flex items-center justify-between text-[14px]"
              style={{ background: "rgba(118, 118, 128, 0.12)" }}
            >
              <div className="ml-[16px]" onClick={decreaseLever}>
                <IconCom>
                  <Minus />
                </IconCom>
              </div>
              <NumberInput
                variant="outlined"
                className={`flex items-baseline -ml-[25px]`}
                style={{ width: 50, border: 0, padding: 0, background: "transparent" }}
                classes={{ inputRoot: `leverRootInput` }}
                value={invertAveragePoints[Number(lever)]}
                onChange={onValueUpdate}
                endAdornment={<span className={`text-[18px] text-black`}>{`x`}</span>}
              />
              <div className="mr-[16px]" onClick={increaseLever}>
                <IconCom>
                  <Plus />
                </IconCom>
              </div>
            </div>
          </div>
          <div className="mt-[20px]">
            <Slider
              min={minLever}
              max={maxLever}
              adsorptionRadius={0}
              marks={marks}
              step={step}
              sliderValue={lever}
              tipFormatter={tipFormatter}
              onSliderChange={onSliderChange}
            />
          </div>
          <div className="mt-[19px]">当前杠杆倍数最高可持有头寸：{formatMoney(toDefaultNumber(notionalCap))} USDT</div>
          {toDefaultNumber(invertAveragePoints[Number(lever)]) > 10 ? (
            <div className="mt-[10px] text-red">当前杠杆倍数较高，容易导致强平，请谨慎调整！</div>
          ) : null}
        </div>
      </Modal>
    </>
  );
};

AdjustingLeverModal.defaultProps = {};

export type { AdjustingLeverModalProps, AdjustingLeverModalRefFuncProps, AdjustingLeverModalConfirmProps };
export default AdjustingLeverModal;
