import { jsx } from "react/jsx-runtime";
import { tcx } from "@choiceform/design-system";
import { observer, use$ as useSelector } from "../../_vendor/@legendapp/state/react.js";
import { useRef, useMemo, useState, useEffect } from "react";
import { useEventCallback } from "../../_vendor/usehooks-ts/dist-index.js";
import { t } from "../../i18n/index.js";
import { coreStore$, coreActions } from "../../stores/core-store.js";
import { usePromptKitDragAndDrop } from "../prompt-kit.js";
import { PromptInputTv } from "./tv.js";
import { useFileUploadHandler } from "./hooks/use-file-upload-handler.js";
import { useInputState } from "./hooks/use-input-state.js";
import { useMessageSending } from "./hooks/use-message-sending.js";
import { useModelSelection } from "./hooks/use-model-selection.js";
import { useVoiceInput } from "./hooks/use-voice-input.js";
import { hasUnuploadedFiles, getSendButtonTooltip, generateStyles } from "./utils/message-utils.js";
import { PromptInputContext } from "./context/prompt-input-context.js";
import { PromptAttachmentPreview } from "./components/prompt-attachment-preview/prompt-attachment-preview.js";
import { PromptTextArea } from "./components/prompt-text-area/prompt-text-area.js";
import { PromptCharacterCount } from "./components/prompt-character-count/prompt-character-count.js";
import { PromptContextMenu } from "./components/prompt-context-menu/prompt-context-menu.js";
import { PromptVoiceInput } from "./components/prompt-voice-input/prompt-voice-input.js";
import { PromptModelMenu } from "./components/prompt-model-menu/prompt-model-menu.js";
import { PromptSendButton } from "./components/prompt-send-button/prompt-send-button.js";
import { PromptStateBar } from "./components/prompt-state-bar/prompt-state-bar.js";
import { PromptMessageQueue } from "./components/prompt-message-queue/prompt-message-queue.js";
import { PromptPlanTodoList } from "./components/prompt-plan-todo-list/prompt-plan-todo-list.js";
import { PromptResearchSwitch } from "./components/prompt-research-switch/prompt-research-switch.js";
import { usePlanUpdates } from "./components/prompt-plan-todo-list/hooks/use-plan-updates.js";
import { isMultimodalModel } from "../../utils/model-utils.js";
const PromptInputBase = observer(function PromptInput2(props) {
  const {
    beforeOnSendMessage,
    className,
    value,
    mentionTriggers,
    mentionPrefix,
    placeholder,
    minHeight = 52,
    maxHeight = 256,
    size = "large",
    variant = "default",
    onChange,
    onAttachmentsChange,
    enableModalSelection,
    onSendMessage,
    onCreateNewChat,
    onFileUploadError,
    attachmentMaxCount,
    onFileUpload,
    onFileUploadByUrl,
    onMentionSelect,
    children
  } = props;
  const inputContainerRef = useRef(null);
  const dragCtx = usePromptKitDragAndDrop();
  const removeAttachment = useMemo(
    () => dragCtx?.removeAttachment || (() => {
    }),
    [dragCtx?.removeAttachment]
  );
  const clearAttachments = useMemo(
    () => dragCtx?.clearAttachments || (() => {
    }),
    [dragCtx?.clearAttachments]
  );
  const addAttachments = useMemo(
    () => dragCtx?.addAttachments || (() => {
    }),
    [dragCtx?.addAttachments]
  );
  const updateAttachmentProgress = useMemo(
    () => dragCtx?.updateAttachmentProgress || (() => {
    }),
    [dragCtx?.updateAttachmentProgress]
  );
  const setAttachmentError = useMemo(
    () => dragCtx?.setAttachmentError || (() => {
    }),
    [dragCtx?.setAttachmentError]
  );
  const updateAttachmentUrl = useMemo(
    () => dragCtx?.updateAttachmentUrl || (() => {
    }),
    [dragCtx?.updateAttachmentUrl]
  );
  const updateAttachmentExtraData = useMemo(
    () => dragCtx?.updateAttachmentExtraData || (() => {
    }),
    [dragCtx?.updateAttachmentExtraData]
  );
  const setAttachmentUploading = useMemo(
    () => dragCtx?.setAttachmentUploading || (() => {
    }),
    [dragCtx?.setAttachmentUploading]
  );
  const getFileById = useMemo(
    () => dragCtx?.getFileById || (() => void 0),
    [dragCtx?.getFileById]
  );
  const createAbortController = useMemo(
    () => dragCtx?.createAbortController || (() => new AbortController()),
    [dragCtx?.createAbortController]
  );
  const cleanupAbortController = useMemo(
    () => dragCtx?.cleanupAbortController || (() => {
    }),
    [dragCtx?.cleanupAbortController]
  );
  const { handleFilesUpload } = useFileUploadHandler({
    onFileUpload,
    onFileUploadError,
    updateAttachmentProgress,
    setAttachmentError,
    updateAttachmentUrl,
    setAttachmentUploading,
    getFileById,
    createAbortController,
    updateAttachmentExtraData,
    cleanupAbortController
  });
  const {
    inputValue,
    contextInputRef,
    setInputValue,
    clearInput,
    focusInput,
    handleKeyDown,
    handleInputChange,
    handleCompositionStart,
    handleCompositionEnd
  } = useInputState({
    value,
    onChange,
    onSendMessage: () => {
      const currentAttachments = dragCtx?.attachments || [];
      handleSendMessage(
        inputValue.text,
        currentAttachments,
        clearInput,
        focusInput,
        getCurrentModelId()
      );
      if (dragCtx?.clearAttachments) {
        dragCtx.clearAttachments();
      }
    }
  });
  const { getCurrentModelId, currentModel } = useModelSelection(enableModalSelection);
  const { currentPlan } = usePlanUpdates();
  const {
    isVoiceSupported,
    isVoiceListening,
    handleVoiceMouseDown,
    handleVoiceMouseUp,
    handleVoiceClick,
    useControlKeyVoiceInput
  } = useVoiceInput({
    inputValue,
    language: "zh-CN",
    onChange,
    onInputChange: handleInputChange,
    onSetInputValue: setInputValue
  });
  const [isInputFocused, setIsInputFocused] = useState(false);
  useControlKeyVoiceInput(isInputFocused);
  const isCurrentModelMultimodal = isMultimodalModel(currentModel);
  let attachmentEnabled = isCurrentModelMultimodal && Boolean(dragCtx);
  if (props.allowUploadByUrl || props.allowUploadLocalFiles) {
    attachmentEnabled = true;
  }
  const allowUploadByUrl = props.allowUploadByUrl;
  const allowUploadLocalFiles = props.allowUploadLocalFiles ?? attachmentEnabled;
  const {
    streamingStatus,
    handleSendMessage,
    handleStopStreaming,
    getSendButtonState,
    hasPendingMessages,
    sendJumpQueueMessage
  } = useMessageSending({
    onSendMessage,
    onCreateNewChat,
    beforeOnSendMessage,
    onFileUploadError
  });
  const hasUnuploadedAttachments = hasUnuploadedFiles(dragCtx?.attachments || []);
  useEffect(() => {
    onAttachmentsChange?.(dragCtx?.attachments || []);
  }, [dragCtx?.attachments, onAttachmentsChange]);
  const processedAttachmentIdsRef = useRef(/* @__PURE__ */ new Set());
  useEffect(() => {
    const attachments = dragCtx?.attachments || [];
    if (!attachments.length) return;
    if (!attachmentEnabled) return;
    const newPending = attachments.filter(
      (a) => a.uploadStatus === "pending" && !processedAttachmentIdsRef.current.has(a.id)
    );
    if (newPending.length > 0) {
      newPending.forEach((a) => processedAttachmentIdsRef.current.add(a.id));
      handleFilesUpload(newPending);
    }
  }, [dragCtx?.attachments, attachmentEnabled, handleFilesUpload, clearAttachments]);
  const handleFileButtonClick = useEventCallback(() => {
    if (!attachmentEnabled) {
      return;
    }
    if (dragCtx?.openFilePicker) {
      dragCtx.openFilePicker();
    }
  });
  useEventCallback(() => {
    if (!attachmentEnabled || !allowUploadByUrl) {
      return;
    }
  });
  const sendButtonState = getSendButtonState(inputValue.text, dragCtx?.attachments?.length || 0);
  const send = t("prompt-input", "send");
  const enterMessageOrAttach = t("prompt-input", "enter-message-or-attach");
  const waitingForUpload = t("prompt-input", "waiting-for-upload");
  const sendButtonTooltip = useMemo(() => {
    return getSendButtonTooltip(
      hasUnuploadedAttachments,
      streamingStatus.isStreaming,
      sendButtonState.hasContent,
      {
        send,
        enterMessageOrAttach,
        waitingForUpload
      }
    );
  }, [
    hasUnuploadedAttachments,
    streamingStatus.isStreaming,
    sendButtonState.hasContent,
    send,
    enterMessageOrAttach,
    waitingForUpload
  ]);
  const styles = useMemo(() => generateStyles(maxHeight), [maxHeight]);
  const [modelMenuOpen, setModelMenuOpen] = useState(false);
  const isDeepThinkingEnabled = useSelector(coreStore$.isDeepThinkingEnabled);
  const isStreaming = Boolean(streamingStatus.isStreaming && streamingStatus.currentMessageId);
  const handleStopAndRollback = useEventCallback(() => {
    const { combinedContent, combinedAttachments } = handleStopStreaming();
    const currentText = inputValue.text.trim();
    const queueText = combinedContent.trim();
    let finalText = "";
    if (currentText && queueText) {
      finalText = currentText + "\n" + queueText;
    } else {
      finalText = currentText || queueText;
    }
    if (finalText) {
      setTimeout(() => {
        const newValue = {
          text: finalText,
          mentions: []
          // TODO: 未来可以考虑保留原有的mentions
        };
        if (onChange) {
          onChange(newValue);
        }
        setInputValue(newValue);
        if (contextInputRef.current) {
          handleInputChange(newValue);
        }
        if (combinedAttachments.length > 0) {
          addAttachments(combinedAttachments);
        }
        focusInput();
      }, 0);
    } else {
      if (combinedAttachments.length > 0) {
        addAttachments(combinedAttachments);
      }
      focusInput();
    }
  });
  const handleModelMenuKeyDown = useEventCallback((event) => {
    if (event.key === "/" && event.metaKey) {
      setModelMenuOpen(true);
      event.preventDefault();
    }
    if (isStreaming && event.key === "Escape") {
      event.preventDefault();
      event.stopPropagation();
      handleStopAndRollback();
    }
  });
  const handleSendMessageClick = useEventCallback(() => {
    if (isStreaming) {
      handleStopAndRollback();
    } else {
      const currentAttachments = dragCtx?.attachments || [];
      handleSendMessage(
        inputValue.text,
        currentAttachments,
        clearInput,
        focusInput,
        getCurrentModelId()
      );
      if (dragCtx?.clearAttachments) {
        dragCtx.clearAttachments();
      }
    }
  });
  const toggleDeepThinking = useEventCallback(() => {
    coreActions.toggleDeepThinking();
  });
  const tv = PromptInputTv({
    hasAttachments: (dragCtx?.attachments?.length || 0) > 0
  });
  const contextValue = useMemo(
    () => ({
      // Props
      className,
      enableModalSelection,
      maxHeight,
      mentionTriggers,
      mentionPrefix,
      minHeight,
      placeholder,
      size,
      variant,
      // State and refs
      inputValue,
      contextInputRef,
      inputContainerRef,
      isInputFocused,
      modelMenuOpen,
      isStreaming,
      currentPlan,
      isDeepThinkingEnabled,
      // Computed values
      attachmentEnabled,
      allowUploadByUrl,
      allowUploadLocalFiles,
      attachmentMaxCount,
      hasUnuploadedAttachments,
      isCurrentModelMultimodal,
      sendButtonState,
      sendButtonTooltip,
      streamingStatus,
      hasPendingMessages,
      // Voice input
      isVoiceSupported,
      isVoiceListening,
      // Drag and drop
      dragCtx,
      removeAttachment,
      // Methods
      setInputValue,
      setIsInputFocused,
      setModelMenuOpen,
      clearInput,
      focusInput,
      handleKeyDown,
      handleInputChange,
      handleCompositionStart,
      handleCompositionEnd,
      handleFileButtonClick,
      handleSendMessageClick,
      handleStopAndRollback,
      handleModelMenuKeyDown,
      handleVoiceMouseDown,
      handleVoiceMouseUp,
      handleVoiceClick,
      getCurrentModelId,
      sendJumpQueueMessage,
      toggleDeepThinking,
      // From props
      onMentionSelect,
      onAttachmentsChange,
      onChange,
      onCreateNewChat,
      onFileUpload,
      onFileUploadByUrl,
      onFileUploadError,
      onSendMessage,
      // Styles
      styles
    }),
    [
      className,
      enableModalSelection,
      maxHeight,
      mentionTriggers,
      mentionPrefix,
      minHeight,
      placeholder,
      size,
      variant,
      inputValue,
      contextInputRef,
      isInputFocused,
      modelMenuOpen,
      isStreaming,
      currentPlan,
      isDeepThinkingEnabled,
      attachmentEnabled,
      allowUploadByUrl,
      allowUploadLocalFiles,
      attachmentMaxCount,
      hasUnuploadedAttachments,
      isCurrentModelMultimodal,
      sendButtonState,
      sendButtonTooltip,
      streamingStatus,
      hasPendingMessages,
      isVoiceSupported,
      isVoiceListening,
      dragCtx,
      removeAttachment,
      setInputValue,
      clearInput,
      focusInput,
      handleKeyDown,
      handleInputChange,
      handleCompositionStart,
      handleCompositionEnd,
      handleFileButtonClick,
      handleSendMessageClick,
      handleStopAndRollback,
      handleModelMenuKeyDown,
      handleVoiceMouseDown,
      handleVoiceMouseUp,
      handleVoiceClick,
      getCurrentModelId,
      sendJumpQueueMessage,
      toggleDeepThinking,
      onMentionSelect,
      onAttachmentsChange,
      onChange,
      onCreateNewChat,
      onFileUpload,
      onFileUploadByUrl,
      onFileUploadError,
      onSendMessage,
      styles
    ]
  );
  return /* @__PURE__ */ jsx(PromptInputContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
    "div",
    {
      className: tcx(tv.root(), className),
      style: styles,
      ref: inputContainerRef,
      onKeyDown: handleModelMenuKeyDown,
      children
    }
  ) });
});
const PromptInput = PromptInputBase;
PromptInput.AttachmentPreview = PromptAttachmentPreview;
PromptInput.TextArea = PromptTextArea;
PromptInput.CharacterCount = PromptCharacterCount;
PromptInput.AttachmentMenu = PromptContextMenu;
PromptInput.VoiceInput = PromptVoiceInput;
PromptInput.ModelMenu = PromptModelMenu;
PromptInput.SendButton = PromptSendButton;
PromptInput.StateBar = PromptStateBar;
PromptInput.MessageQueue = PromptMessageQueue;
PromptInput.PlanTodoList = PromptPlanTodoList;
PromptInput.ResearchSwitch = PromptResearchSwitch;
export {
  PromptInput
};
//# sourceMappingURL=prompt-input.js.map
