import React, { memo, useMemo, useCallback, useState, useRef, useEffect } from "react";
import { InputRef, InputProps } from "antd";
import { Tooltip, TYIcon, Input, Dropdown } from "@tingwu/design";
import {
  Wrapper,
  Button,
  DropdownOverlay,
  RelatedSpeakerList,
  RelatedSpeakerIcon,
  RelatedSpeakerText,
  RelatedSpeaker,
  CompanyPeopleList,
  CompanyPeople,
  CompanyPeopleAvatar,
  CompanyPeopleInfo,
  CompanyPeopleTitle,
  CompanyPeopleSubTitle,
  CommonUseSpeakerList,
  HorizontalDivider,
  AlibabaEmpty,
  StarContainer,
  CommonUseSpeakeLine,
  CurrentCommonUseListTitle,
  CommonUseListTitleWord,
  CurrentCommonUseListDescribe,
  CurrentListTitle,
  CurrentListDescribe,
  DeleteIconBox,
  StarBox,
  RelatedCommonUseSpeaker,
  DefaultAvatarIcon,
  CommonUseListContain,
  RelatedSpeakerListContain,
} from "./styled";
import { useTranscriptionHooks, getTranscriptionController } from "../../controller";
import { Controller, PID, UID, AlibabaEmployee, Speaker, CommonUseSpeaker } from "@tingwu/core";
import { HighlightText } from "../highlightText";
import { isEnterHotkey } from "@tingwu/common";

import {
  getDisplayAlibabaEmployeeName,
  UID_START_WORD,
  getSpeakerName,
  findDeleteCommonSpeakerIndex,
  isInCommonSpeakers,
} from "../../utils";

export interface SpeakerInputProps extends InputProps {
  controller: Controller;
  pid?: PID;
  isUnfix?: boolean;
  emptyUnfix?: boolean;
  defaultName?: string;
  onFinishEditing?: () => void;
  getParagraphContainer?: () => HTMLDivElement;
}

export type SpeakerInputHandler = InputRef;

const DEFAULT_AVATAR_URL =
  "https://img.alicdn.com/imgextra/i2/O1CN01ZNuOEG253lmJp2lwB_!!6000000007471-55-tps-77-77.svg";

const EMPTY_OVERLAY = <div />;

const renderCompanyPeople = (
  inputText: string,
  employee: AlibabaEmployee,
  onSelect: (employee: AlibabaEmployee) => void
) => {
  return (
    <CompanyPeople key={employee.bizUid} onClick={() => onSelect(employee)}>
      <CompanyPeopleAvatar>
        <img src={employee.avatarUrl || DEFAULT_AVATAR_URL} />
      </CompanyPeopleAvatar>
      <CompanyPeopleInfo>
        <CompanyPeopleTitle>
          <HighlightText
            text={getDisplayAlibabaEmployeeName(employee)}
            keyword={inputText}
            highlightClassName={"highlight"}
            inline
          />
          {employee.bizUid ? ` - ${employee.bizUid}` : ""}
        </CompanyPeopleTitle>
        <CompanyPeopleSubTitle>{employee.departName}</CompanyPeopleSubTitle>
      </CompanyPeopleInfo>
    </CompanyPeople>
  );
};

const renderCompanyPeoples = (
  inputText: string,
  alibabaEmployees: AlibabaEmployee[],
  onSelect: (employee: AlibabaEmployee) => void
) => {
  return (
    <CompanyPeopleList>
      {alibabaEmployees.map(employee => renderCompanyPeople(inputText, employee, onSelect))}
    </CompanyPeopleList>
  );
};

interface RenderSpeakerProps {
  speaker: Speaker;
  onSelect: (speaker: Speaker) => void;
  getDefaultSpeakerName: (speaker?: Speaker) => string;
  currentUseSpeakersList: Speaker[];
  renderAvatar?: (uid: UID) => React.ReactNode;
  onCollectSpeaker?: (speaker: Speaker, isCollect: boolean) => void;
  toolTipInnerStyle: React.CSSProperties;
}

const RenderSpeaker: React.FC<RenderSpeakerProps> = memo(props => {
  const {
    speaker,
    onSelect,
    getDefaultSpeakerName,
    currentUseSpeakersList,
    renderAvatar,
    onCollectSpeaker,
    toolTipInnerStyle,
  } = props;
  const avatarIcon = (renderAvatar && renderAvatar(speaker.uid)) || <DefaultAvatarIcon />;

  const handleClick = useCallback(
    (event: React.MouseEvent) => {
      event.stopPropagation();
      if (onCollectSpeaker) {
        onCollectSpeaker(speaker, !isInCommonSpeakers(speaker, currentUseSpeakersList));
      }
    },
    [onCollectSpeaker, speaker, currentUseSpeakersList]
  );

  const starColor = useMemo(() => {
    return isInCommonSpeakers(speaker, currentUseSpeakersList) ? "var(--Caution_Clicked)" : "";
  }, [currentUseSpeakersList, speaker]);

  const handleClickSpeaker = useCallback(() => {
    onSelect(speaker);
  }, [onSelect, speaker]);

  const toolTipinnerText = useMemo(() => {
    return isInCommonSpeakers(speaker, currentUseSpeakersList)
      ? "取消常用发言人"
      : "设为常用发言人";
  }, [currentUseSpeakersList, speaker]);

  return (
    <RelatedSpeaker key={speaker.uid} onClick={handleClickSpeaker}>
      <RelatedSpeakerIcon>{avatarIcon}</RelatedSpeakerIcon>
      <RelatedSpeakerText className="relatedSpeakerText">
        {getSpeakerName(speaker, getDefaultSpeakerName)}
      </RelatedSpeakerText>
      <Tooltip
        overlayInnerStyle={toolTipInnerStyle}
        title={toolTipinnerText}
        placement="top"
        zIndex={1200}
      >
        <StarBox className="star" onClick={handleClick}>
          <StarContainer isColleted={!isInCommonSpeakers(speaker, currentUseSpeakersList)}>
            <TYIcon
              type={"tongyi-star-fill"}
              size={15}
              style={{ color: `${starColor}`, fontSize: 16 }}
            />
          </StarContainer>
        </StarBox>
      </Tooltip>
    </RelatedSpeaker>
  );
});

interface RenderCommonUseSpeakerProps {
  speaker: CommonUseSpeaker;
  onSelect: (speaker: CommonUseSpeaker) => void;
  getDefaultSpeakerName?: (speaker?: CommonUseSpeaker) => string;
  renderCommonUseAvatar?: (speaker: CommonUseSpeaker) => React.ReactNode;
  onCollectSpeaker?: (speaker: CommonUseSpeaker, isCollect: boolean) => void;
  toolTipInnerStyle: React.CSSProperties;
}

const RenderCommonUseSpeaker: React.FC<RenderCommonUseSpeakerProps> = memo(props => {
  const {
    speaker,
    onSelect,
    getDefaultSpeakerName,
    renderCommonUseAvatar,
    onCollectSpeaker,
    toolTipInnerStyle,
  } = props;
  const avatarIcon = (renderCommonUseAvatar && renderCommonUseAvatar(speaker)) || (
    <DefaultAvatarIcon />
  );

  const handleClick = useCallback(
    (event: React.MouseEvent) => {
      event.stopPropagation();
      if (onCollectSpeaker) {
        onCollectSpeaker(speaker, false);
      }
    },
    [onCollectSpeaker, speaker]
  );

  return (
    <RelatedCommonUseSpeaker
      key={`${speaker.name}-${speaker.bizUid}`}
      onClick={() => onSelect(speaker)}
    >
      <RelatedSpeakerIcon>{avatarIcon}</RelatedSpeakerIcon>
      <RelatedSpeakerText className="relatedSpeakerText">
        {getDefaultSpeakerName && getSpeakerName(speaker, getDefaultSpeakerName)}
      </RelatedSpeakerText>
      <Tooltip
        overlayInnerStyle={toolTipInnerStyle}
        title="删除"
        placement="top"
        color={"rgba(39,38,77,1)"}
        zIndex={1200}
      >
        <DeleteIconBox className="deleteIcon" onClick={handleClick}>
          <TYIcon type={"tongyi-false-line"} style={{ fontSize: 14 }} />
        </DeleteIconBox>
      </Tooltip>
    </RelatedCommonUseSpeaker>
  );
});
interface RenderSpeakerListProps {
  speakers: Speaker[];
  onSelect: (speaker: Speaker) => void;
  getDefaultSpeakerName: (speaker?: Speaker) => string;
  currentUseSpeakersList: CommonUseSpeaker[];
  renderAvatar?: (uid: UID) => React.ReactNode;
  onCollectSpeaker?: (speaker: CommonUseSpeaker, isCollect: boolean) => void;
  toolTipInnerStyle: React.CSSProperties;
}

const RenderSpeakerList: React.FC<RenderSpeakerListProps> = memo(props => {
  const {
    speakers,
    onSelect,
    getDefaultSpeakerName,
    currentUseSpeakersList,
    renderAvatar,
    onCollectSpeaker,
    toolTipInnerStyle,
  } = props;

  return (
    <RelatedSpeakerList>
      <CurrentListTitle>当前记录发言人</CurrentListTitle>
      <CurrentListDescribe>选中发言人点击星标，即可设为常用发言人</CurrentListDescribe>
      <RelatedSpeakerListContain>
        {speakers.map((speaker, index) => (
          <RenderSpeaker
            key={`${speaker.name}/${index}`}
            speaker={speaker}
            onSelect={onSelect}
            getDefaultSpeakerName={getDefaultSpeakerName}
            currentUseSpeakersList={currentUseSpeakersList}
            renderAvatar={renderAvatar}
            onCollectSpeaker={onCollectSpeaker}
            toolTipInnerStyle={toolTipInnerStyle}
          />
        ))}
      </RelatedSpeakerListContain>
    </RelatedSpeakerList>
  );
});

interface RenderCommonUseSpeakerListProps {
  speakers: CommonUseSpeaker[];
  isMaxHeight: boolean;
  isEmpyt: boolean;
  onSelect: (speaker: CommonUseSpeaker) => void;
  getDefaultSpeakerName?: (speaker?: CommonUseSpeaker) => string;
  renderCommonUseAvatar?: (speaker: CommonUseSpeaker) => React.ReactNode;
  onCollectSpeaker?: (speaker: CommonUseSpeaker, isCollect: boolean) => void;
  toolTipInnerStyle: React.CSSProperties;
}

const RenderCommonUseSpeakerList: React.FC<RenderCommonUseSpeakerListProps> = memo(props => {
  const {
    speakers,
    isMaxHeight,
    isEmpyt,
    onSelect,
    getDefaultSpeakerName,
    renderCommonUseAvatar,
    onCollectSpeaker,
    toolTipInnerStyle,
  } = props;

  const heightNum = useMemo(() => {
    return isMaxHeight ? 137 : 194;
  }, [isMaxHeight]);

  const listHeightNum = useMemo(() => {
    return isMaxHeight ? 82 : 158;
  }, [isMaxHeight]);

  const isBlock = useMemo(() => {
    return speakers.length > 0 ? "inline-flex" : "none";
  }, [speakers.length]);

  return (
    <CommonUseSpeakerList style={{ height: "100%", maxHeight: heightNum }}>
      <CommonUseSpeakeLine style={{ display: isMaxHeight ? "block" : "none" }} />
      <CurrentCommonUseListTitle>
        <CommonUseListTitleWord>常用发言人</CommonUseListTitleWord>
        <StarContainer>
          <TYIcon type={"tongyi-star-fill"} size={20} style={{ color: "var(--Text_Primary)" }} />
        </StarContainer>
      </CurrentCommonUseListTitle>
      <CurrentCommonUseListDescribe>
        {!isEmpyt
          ? "常用发言人会展示在所有记录中"
          : "选中当前记录发言人并点击星标，即可设为常用发言人，常用发言人会展示在所有记录中"}
      </CurrentCommonUseListDescribe>
      <CommonUseListContain
        style={{
          display: isBlock,
          height: "100%",
          maxHeight: !isEmpyt ? listHeightNum : 0,
        }}
      >
        {speakers.map((speaker, index) => (
          <RenderCommonUseSpeaker
            key={`${speaker.name}/${index}`}
            speaker={speaker}
            onSelect={onSelect}
            getDefaultSpeakerName={getDefaultSpeakerName}
            renderCommonUseAvatar={renderCommonUseAvatar}
            onCollectSpeaker={onCollectSpeaker}
            toolTipInnerStyle={toolTipInnerStyle}
          />
        ))}
      </CommonUseListContain>
    </CommonUseSpeakerList>
  );
});

export const SpeakerInput = React.forwardRef<InputRef, SpeakerInputProps>((props, ref) => {
  const {
    onFocus,
    onBlur,
    style,
    controller,
    pid,
    isUnfix = false,
    emptyUnfix = false,
    defaultName = "",
    onFinishEditing,
    getParagraphContainer,
    ...resetProps
  } = props;

  const {
    onFetchAlibabaEmployees,
    getTranscriptionContainer,
    getAvailableSpeakers,
    renderAvatar,
    enableSelectAlibabaEmployee,
    enableCommonUseSpeaker,
    getDefaultSpeakerName,
    onEvent,
    getCommonUseSpeakers,
    renderCommonUseAvatar,
    addCommonUseSpeaker,
  } = useTranscriptionHooks(controller, [
    "onFetchAlibabaEmployees",
    "getTranscriptionContainer",
    "getAvailableSpeakers",
    "renderAvatar",
    "enableSelectAlibabaEmployee",
    "enableCommonUseSpeaker",
    "getDefaultSpeakerName",
    "onEvent",
    "getCommonUseSpeakers",
    "addCommonUseSpeaker",
    "renderCommonUseAvatar",
  ]);
  const isLivingMode = controller.getLivingMode();

  // don't use `useMemo`, will be have mistake
  const availableSpeakers: Speaker[] = getAvailableSpeakers ? getAvailableSpeakers() : [];
  const commonUseSpeakers: CommonUseSpeaker[] = getCommonUseSpeakers ? getCommonUseSpeakers() : [];
  const displayAvailableSpeakers = availableSpeakers.filter(speaker => {
    return speaker.uid.startsWith(UID_START_WORD);
  });

  const [dropdownVisible, setDropdownVisible] = useState(false);
  const [alibabaEmployees, setAlibabaEmployees] = useState<AlibabaEmployee[]>([]);
  const [inputValue, setInputValue] = useState<string>(defaultName);
  const [selectedSpeaker, setSelectedSpeaker] = useState<Speaker>();
  const [selectedAlibabaEmployee, setSelectedAlibabaEmployee] = useState<AlibabaEmployee>();
  const [fetchingAlibabaEmployees, setFetchingAlibabaEmployees] = useState(false);
  const [fetchedAlibabaEmployees, setFetchedAlibabaEmployees] = useState(false);
  const [currentUseSpeakersList, setCurrentUseSpeakersList] =
    useState<CommonUseSpeaker[]>(commonUseSpeakers);
  const transController = getTranscriptionController(controller);
  const [miniMode, setMiniMode] = useState(transController.getIsMiniMode());

  useEffect(() => {
    return transController.on("miniModeChange", ({ isMiniMode }) => {
      setMiniMode(isMiniMode);
    });
  }, [transController]);

  const stateRef = useRef<{
    fetchId: number;
    timeout: ReturnType<typeof setTimeout> | undefined;
  }>({
    fetchId: 0,
    timeout: undefined,
  });

  const handleCommitOneOnEmptyUnfix = useCallback(() => {
    onEvent &&
      onEvent("didEditSpeaker", {
        emptyUnfix: true,
        oldSpeaker: defaultName,
        newSpeaker: selectedSpeaker?.name || selectedAlibabaEmployee?.name || inputValue,
        isMutiple: false,
      });
    if (selectedSpeaker) {
      controller.updateOneByHistorySpeakerOnEmptyUnfix(selectedSpeaker);
    } else if (selectedAlibabaEmployee) {
      controller.updateOneByAlibabaEmployeeOnEmptyUnfix(selectedAlibabaEmployee);
    } else {
      controller.updateOneByInputTextOnEmptyUnfix(defaultName, inputValue.trim());
    }
    onFinishEditing && onFinishEditing();
  }, [
    selectedSpeaker,
    controller,
    inputValue,
    onFinishEditing,
    selectedAlibabaEmployee,
    defaultName,
    onEvent,
  ]);

  const handleCommitOne = useCallback(() => {
    if (!pid) {
      return;
    }
    onEvent &&
      onEvent("didEditSpeaker", {
        pid,
        emptyUnfix: false,
        oldSpeaker: defaultName,
        newSpeaker: selectedSpeaker?.name || selectedAlibabaEmployee?.name || inputValue.trim(),
        isMutiple: false,
      });
    if (selectedSpeaker) {
      controller.updateOneByHistorySpeaker(pid, selectedSpeaker);
    } else if (selectedAlibabaEmployee) {
      controller.updateOneByAlibabaEmployee(pid, selectedAlibabaEmployee);
    } else {
      controller.updateOneByInputText(pid, defaultName, inputValue.trim());
    }

    onFinishEditing && onFinishEditing();
  }, [
    inputValue,
    controller,
    pid,
    selectedSpeaker,
    selectedAlibabaEmployee,
    onFinishEditing,
    defaultName,
    onEvent,
  ]);

  const handleCommitAll = useCallback(() => {
    if (!pid) {
      return;
    }

    onEvent &&
      onEvent("didEditSpeaker", {
        pid,
        emptyUnfix: false,
        oldSpeaker: defaultName,
        newSpeaker: selectedSpeaker?.name || selectedAlibabaEmployee?.name || inputValue.trim(),
        isMutiple: true,
      });

    if (selectedSpeaker) {
      controller.updateManyByHistorySpeaker(pid, selectedSpeaker);
    } else if (selectedAlibabaEmployee) {
      controller.updateManyByAlibabaEmployee(pid, selectedAlibabaEmployee);
    } else {
      controller.updateManyByInputText(pid, defaultName, inputValue.trim());
    }

    onFinishEditing && onFinishEditing();
  }, [
    pid,
    onEvent,
    defaultName,
    selectedSpeaker,
    selectedAlibabaEmployee,
    inputValue,
    onFinishEditing,
    controller,
  ]);

  const toolTipInnerStyle = useMemo(
    () => ({
      backgroundColor: "rgba(39,38,77,1)",
      boxShadow: "0 2px 8px 0 rgba(90, 68, 151, 0.1)",
      borderRadius: 8,
      fontWeight: 400,
      fontSize: 12,
      color: "#ffffff",
      padding: "4px 12px",
      paddingTop: "6px",
      lineHeight: "20px",
    }),
    []
  );

  const handleCancel = useCallback(() => {
    if (ref) {
      (ref as React.MutableRefObject<InputRef>).current.blur();
    }
  }, [ref]);

  const [nextCommit, setNextCommit] = useState(false);

  useEffect(() => {
    if (!nextCommit) {
      return;
    }
    setNextCommit(false);
    if (emptyUnfix) {
      handleCommitOneOnEmptyUnfix();
    } else {
      handleCommitOne();
    }
  }, [nextCommit, emptyUnfix, handleCommitOneOnEmptyUnfix, handleCommitOne]);

  const commitFunc = useCallback(() => {
    setNextCommit(true);
  }, []);

  const onSelectSpeaker = useCallback(
    (speaker: Speaker) => {
      setSelectedSpeaker(speaker);
      setSelectedAlibabaEmployee(undefined);
      setInputValue(speaker.name);
      if (ref) {
        (ref as React.MutableRefObject<InputRef>).current.focus();
      }
      if (isLivingMode) {
        commitFunc();
      }
    },
    [ref, commitFunc, isLivingMode]
  );

  const canAddCommonUseSpeaker = useCallback(
    async (speaker: CommonUseSpeaker) => {
      if (!addCommonUseSpeaker) {
        console.error("`addCommonUseSpeaker` not found");
      } else {
        const result = await addCommonUseSpeaker(speaker);
        if (result.code === "0") {
          const newSpeakerList = [speaker, ...currentUseSpeakersList];
          setCurrentUseSpeakersList(newSpeakerList);
          controller.updateCommonUseSpeakersList(newSpeakerList);
        }
      }
    },
    [addCommonUseSpeaker, controller, currentUseSpeakersList]
  );

  const onCollectSpeaker = useCallback(
    (speaker: CommonUseSpeaker, isCollect: boolean) => {
      const index = findDeleteCommonSpeakerIndex(speaker, currentUseSpeakersList);
      if (isCollect) {
        if (index < 0) {
          canAddCommonUseSpeaker(speaker);
        }
      } else if (index > -1) {
        onEvent && onEvent("cancelCollectSpeaker", speaker);
        const newSpeakerList = currentUseSpeakersList.filter((_item, i) => {
          return i !== index;
        });
        setCurrentUseSpeakersList(newSpeakerList);
        controller.updateCommonUseSpeakersList(newSpeakerList);
      }
      if (ref) {
        (ref as React.MutableRefObject<InputRef>).current.focus();
      }
    },
    [canAddCommonUseSpeaker, controller, currentUseSpeakersList, onEvent, ref]
  );

  const onSelectAlibabaEmployees = useCallback(
    (employee: AlibabaEmployee) => {
      setSelectedSpeaker(undefined);
      setSelectedAlibabaEmployee(employee);
      setInputValue(getDisplayAlibabaEmployeeName(employee));
      setAlibabaEmployees([]);
      setFetchedAlibabaEmployees(false);
      if (ref) {
        (ref as React.MutableRefObject<InputRef>).current.focus();
      }
      if (isLivingMode) {
        commitFunc();
      }
    },
    [commitFunc, isLivingMode, ref]
  );

  const fetchAlibabaEmployeeById = useCallback(
    async (keyword: string) => {
      if (!onFetchAlibabaEmployees) {
        console.error("`onFetchAlibabaEmployees` not found");
      } else {
        const result = await onFetchAlibabaEmployees(keyword);
        const targetEmployee = result.filter(v => {
          return v.bizUid === keyword;
        });
        targetEmployee && targetEmployee.length && onSelectAlibabaEmployees(targetEmployee[0]);
      }
    },
    [onFetchAlibabaEmployees, onSelectAlibabaEmployees]
  );

  const onSelectCommonUseSpeaker = useCallback(
    (speaker: Speaker) => {
      if (speaker.bizUid) {
        fetchAlibabaEmployeeById(speaker.bizUid);
      } else {
        setSelectedAlibabaEmployee(undefined);
        setInputValue(speaker.name);
        if (isLivingMode) {
          commitFunc();
        }
      }
      onEvent && onEvent("selectCommonUseSpeaker", speaker);
      if (ref) {
        (ref as React.MutableRefObject<InputRef>).current.focus();
      }
    },
    [commitFunc, fetchAlibabaEmployeeById, isLivingMode, ref, onEvent]
  );

  const overlay: React.ReactNode = useMemo(() => {
    const fetchedAlibabaEmployeesAndEmpty =
      !fetchingAlibabaEmployees && fetchedAlibabaEmployees && alibabaEmployees.length === 0;

    if (alibabaEmployees.length === 0 && !enableCommonUseSpeaker) {
      return null;
    }

    return (
      <DropdownOverlay style={{ width: 300 }}>
        {fetchedAlibabaEmployeesAndEmpty && inputValue && (
          <>
            <AlibabaEmpty>无对应集团用户，你可以直接添加</AlibabaEmpty>
            {displayAvailableSpeakers.length > 0 && <HorizontalDivider />}
          </>
        )}
        {alibabaEmployees.length > 0 && (
          <>{renderCompanyPeoples(inputValue, alibabaEmployees, onSelectAlibabaEmployees)}</>
        )}
        {alibabaEmployees.length === 0 && displayAvailableSpeakers.length > 0 && (
          <RenderSpeakerList
            speakers={displayAvailableSpeakers}
            onSelect={onSelectSpeaker}
            getDefaultSpeakerName={getDefaultSpeakerName}
            currentUseSpeakersList={currentUseSpeakersList}
            renderAvatar={renderAvatar}
            onCollectSpeaker={onCollectSpeaker}
            toolTipInnerStyle={toolTipInnerStyle}
          />
        )}
        {alibabaEmployees.length === 0 && enableCommonUseSpeaker && (
          <RenderCommonUseSpeakerList
            speakers={currentUseSpeakersList}
            isMaxHeight={displayAvailableSpeakers.length > 0}
            isEmpyt={displayAvailableSpeakers.length === 0 && currentUseSpeakersList.length === 0}
            onSelect={onSelectCommonUseSpeaker}
            getDefaultSpeakerName={getDefaultSpeakerName}
            renderCommonUseAvatar={renderCommonUseAvatar}
            onCollectSpeaker={onCollectSpeaker}
            toolTipInnerStyle={toolTipInnerStyle}
          />
        )}
      </DropdownOverlay>
    );
  }, [
    fetchingAlibabaEmployees,
    fetchedAlibabaEmployees,
    alibabaEmployees,
    displayAvailableSpeakers,
    getDefaultSpeakerName,
    onSelectAlibabaEmployees,
    onSelectSpeaker,
    enableCommonUseSpeaker,
    onSelectCommonUseSpeaker,
    renderAvatar,
    renderCommonUseAvatar,
    inputValue,
    currentUseSpeakersList,
    onCollectSpeaker,
    toolTipInnerStyle,
  ]);

  const handleFocus = useCallback(
    (event: React.FocusEvent<HTMLInputElement, Element>) => {
      setDropdownVisible(true);
      onFocus && onFocus(event);
      if (stateRef.current.timeout) {
        clearTimeout(stateRef.current.timeout);
        stateRef.current.timeout = undefined;
      }
    },
    [onFocus]
  );

  const handleBlur = useCallback(
    (event: React.FocusEvent<HTMLInputElement, Element>) => {
      stateRef.current.timeout = setTimeout(() => {
        setDropdownVisible(false);
        setFetchedAlibabaEmployees(false);
        stateRef.current.timeout = undefined;
        onFinishEditing && onFinishEditing();
      }, 300);
      onBlur && onBlur(event);
    },
    [onBlur, onFinishEditing]
  );

  const fetchAlibabaEmployees = useCallback(
    async (keyword: string) => {
      if (!onFetchAlibabaEmployees) {
        console.error("`onFetchAlibabaEmployees` not found");
      } else {
        const fetchId = ++stateRef.current.fetchId;
        setFetchingAlibabaEmployees(true);
        try {
          const result = await onFetchAlibabaEmployees(keyword);
          if (fetchId !== stateRef.current.fetchId) {
            return;
          }
          if (result && result.length > 0) {
            setAlibabaEmployees(result);
          } else {
            setAlibabaEmployees([]);
          }
        } catch (error) {
          setAlibabaEmployees([]);
          throw error;
        } finally {
          setFetchedAlibabaEmployees(true);
          setFetchingAlibabaEmployees(false);
        }
      }
    },
    [onFetchAlibabaEmployees]
  );

  const handleKeydown = useCallback(
    (event: React.KeyboardEvent) => {
      event.stopPropagation();
      if (isEnterHotkey(event.keyCode)) {
        commitFunc();
      }
    },
    [commitFunc]
  );

  const handleChange = useCallback(
    async (event: React.ChangeEvent<HTMLInputElement>) => {
      const text = event.target.value;

      const formatedText = text.trim();
      if (enableSelectAlibabaEmployee) {
        fetchAlibabaEmployees(formatedText);
      }

      setInputValue(text);
      setSelectedSpeaker(undefined);
      setSelectedAlibabaEmployee(undefined);
    },
    [fetchAlibabaEmployees, enableSelectAlibabaEmployee]
  );

  return (
    <Wrapper miniMode={miniMode}>
      <Dropdown
        open={dropdownVisible && overlay != null}
        dropdownRender={() => overlay || EMPTY_OVERLAY}
        getPopupContainer={isUnfix ? getParagraphContainer : getTranscriptionContainer}
        // align={{
        //   overflow: {
        //     adjustY: false,
        //   },
        // }}
      >
        <Input
          {...resetProps}
          ref={ref}
          value={inputValue}
          onKeyDown={handleKeydown}
          onChange={handleChange}
          onFocus={handleFocus}
          onBlur={handleBlur}
          placeholder={"请输入发言人"}
          style={style}
          maxLength={20}
        />
      </Dropdown>
      <Button
        primary
        onMouseDown={emptyUnfix ? handleCommitOneOnEmptyUnfix : handleCommitOne}
        style={{ marginLeft: 12 }}
      >
        {isLivingMode ? "确定" : "单个"}
      </Button>
      {!isLivingMode && (
        <Button onMouseDown={handleCommitAll} style={{ marginLeft: 8 }}>
          全局
        </Button>
      )}
      {isLivingMode && (
        <Button onMouseDown={handleCancel} style={{ marginLeft: 8 }}>
          取消
        </Button>
      )}
    </Wrapper>
  );
});
