import { use$ as useSelector } from "../../../_vendor/@legendapp/state/react.js";
import { nanoid } from "../../../_vendor/nanoid/index.browser.js";
import { useRef, useState, useEffect } from "react";
import { useEventCallback } from "../../../_vendor/usehooks-ts/dist-index.js";
import { combinedComputed$ } from "../../../stores/combined-store.js";
import { concurrencyComputed$, concurrencyActions } from "../../../stores/concurrency-store.js";
import { streamingComputed$, streamingActions } from "../../../stores/streaming-store.js";
import { queueComputed$, queueActions } from "../../../stores/queue-store.js";
import { commandHistoryActions } from "../../../stores/command-history-store.js";
import { coreStore$ } from "../../../stores/core-store.js";
import { Status, Role } from "../../../types/core.js";
import { messageActions } from "../../../stores/message-store.js";
function useMessageSending(options) {
  const { onSendMessage, onCreateNewChat, onFileUploadError, beforeOnSendMessage } = options;
  const currentChat = useSelector(coreStore$.currentChat);
  const canSendMessage = useSelector(combinedComputed$.canSendMessage);
  const canSendNewMessage = useSelector(concurrencyComputed$.canSendNewMessage);
  const streamingStatus = useSelector(streamingComputed$.streamingStatus);
  const hasPendingMessages = useSelector(queueComputed$.hasPendingMessages);
  const lastSentMessageRef = useRef(null);
  const [isSending, setIsSending] = useState(false);
  const timeoutRef = useRef(null);
  const checkUnuploadedFiles = (attachments) => {
    return attachments.some(
      (att) => att.uploadStatus !== "completed" && att.uploadStatus !== void 0
    );
  };
  const checkDuplicateRequest = (content) => {
    const now = Date.now();
    if (lastSentMessageRef.current) {
      const { content: lastContent, timestamp: lastTime } = lastSentMessageRef.current;
      const timeDiff = now - lastTime;
      if (lastContent === content && timeDiff < 1e3) {
        console.warn(
          "Duplicate message detected. Please wait before sending the same message again."
        );
        return true;
      }
    }
    return false;
  };
  const addMessageToQueue = useEventCallback(
    (content, attachments, clearInput, focusInput, modelId) => {
      if (!content.trim() && attachments.length === 0) return;
      const trimmedContent = content.trim();
      const hasUnuploadedFiles = checkUnuploadedFiles(attachments);
      if (hasUnuploadedFiles) {
        onFileUploadError?.("Please wait for all files to finish uploading");
        return;
      }
      if (checkDuplicateRequest(trimmedContent)) return;
      const pendingMessage = {
        id: nanoid(),
        content: trimmedContent,
        attachments: attachments.length > 0 ? attachments : void 0,
        modelId,
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        priority: 0
        // 默认优先级
      };
      queueActions.addPendingMessage(pendingMessage);
      commandHistoryActions.addCommand(trimmedContent);
      clearInput();
      focusInput();
      console.log(`Message queued: "${trimmedContent}"`);
    }
  );
  const handleSendMessage = useEventCallback(
    async (content, attachments, clearInput, focusInput, modelId) => {
      if (beforeOnSendMessage && !await beforeOnSendMessage()) {
        return;
      }
      if (streamingStatus.isStreaming && streamingStatus.currentMessageId) {
        return addMessageToQueue(content, attachments, clearInput, focusInput, modelId);
      }
      if (!content.trim() && attachments.length === 0 || !canSendMessage || isSending) return;
      const trimmedContent = content.trim();
      const hasUnuploadedFiles = checkUnuploadedFiles(attachments);
      if (hasUnuploadedFiles) {
        onFileUploadError?.("Please wait for all files to finish uploading");
        return;
      }
      if (checkDuplicateRequest(trimmedContent)) return;
      if (!canSendNewMessage) {
        console.warn(
          "Maximum concurrent messages reached. Please wait for current messages to complete."
        );
        return;
      }
      setIsSending(true);
      lastSentMessageRef.current = { content: trimmedContent, timestamp: Date.now() };
      try {
        let chatId = currentChat?.id;
        if (!chatId) {
          if (onCreateNewChat) {
            chatId = onCreateNewChat();
          } else {
            console.warn("No current chat available and no onCreateNewChat provided");
            return;
          }
        }
        clearInput();
        focusInput();
        const userMessage = {
          id: nanoid(),
          content: trimmedContent,
          role: Role.User,
          timestamp: (/* @__PURE__ */ new Date()).toISOString(),
          createdAt: (/* @__PURE__ */ new Date()).toISOString(),
          version: 1,
          isStreaming: false,
          status: Status.Pending,
          retryCount: 0,
          maxRetries: 3,
          abortController: new AbortController(),
          attachments: attachments.length > 0 ? attachments : void 0
        };
        messageActions.addMessage(userMessage);
        commandHistoryActions.addCommand(trimmedContent);
        if (onSendMessage && chatId) {
          concurrencyActions.incrementActiveSessions();
          queueActions.enqueueMessage(userMessage.id, "sendingQueue");
          const timeoutDuration = 3e4;
          timeoutRef.current = setTimeout(() => {
            userMessage.abortController?.abort();
            messageActions.updateMessage(userMessage.id, {
              status: Status.Failed,
              error: {
                message: "Request timeout after 30 seconds",
                code: "TIMEOUT",
                timestamp: (/* @__PURE__ */ new Date()).toISOString()
              }
            });
            queueActions.dequeueMessage(userMessage.id, "sendingQueue");
            queueActions.enqueueMessage(userMessage.id, "failedQueue");
            concurrencyActions.decrementActiveSessions();
          }, timeoutDuration);
          try {
            const validAttachments = attachments.filter((att) => att.uploadStatus === "completed" || att.uploadStatus === void 0).map((att) => ({
              ...att,
              url: att.url
            }));
            await onSendMessage(
              trimmedContent,
              chatId,
              validAttachments.length > 0 ? validAttachments : void 0,
              modelId,
              userMessage.id
            );
            if (timeoutRef.current) {
              clearTimeout(timeoutRef.current);
              timeoutRef.current = null;
            }
            queueActions.dequeueMessage(userMessage.id, "sendingQueue");
          } catch (error) {
            if (timeoutRef.current) {
              clearTimeout(timeoutRef.current);
              timeoutRef.current = null;
            }
            queueActions.dequeueMessage(userMessage.id, "sendingQueue");
            queueActions.enqueueMessage(userMessage.id, "failedQueue");
            messageActions.updateMessage(userMessage.id, {
              status: Status.Failed,
              error: {
                message: error instanceof Error ? error.message : "Failed to send message",
                timestamp: (/* @__PURE__ */ new Date()).toISOString()
              }
            });
            throw error;
          } finally {
            concurrencyActions.decrementActiveSessions();
          }
        }
      } catch (error) {
        console.error("Send message failed:", error);
      } finally {
        setIsSending(false);
      }
    }
  );
  const getSendButtonState = (text, attachmentsCount) => {
    return useSelector(combinedComputed$.sendButtonState(text, attachmentsCount));
  };
  const sendNextQueuedMessage = useEventCallback(async () => {
    const nextMessage = queueActions.dequeuePendingMessage();
    if (!nextMessage) return;
    console.log(`Sending queued message: "${nextMessage.content}"`);
    try {
      let chatId = currentChat?.id;
      if (!chatId) {
        if (onCreateNewChat) {
          chatId = onCreateNewChat();
        } else {
          console.warn("No current chat available and no onCreateNewChat provided");
          return;
        }
      }
      const userMessage = {
        id: nanoid(),
        content: nextMessage.content,
        role: Role.User,
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        createdAt: (/* @__PURE__ */ new Date()).toISOString(),
        version: 1,
        isStreaming: false,
        status: Status.Pending,
        retryCount: 0,
        maxRetries: 3,
        abortController: new AbortController(),
        attachments: nextMessage.attachments
      };
      messageActions.addMessage(userMessage);
      if (onSendMessage && chatId) {
        concurrencyActions.incrementActiveSessions();
        queueActions.enqueueMessage(userMessage.id, "sendingQueue");
        try {
          const validAttachments = nextMessage.attachments?.filter((att) => att.uploadStatus === "completed" || att.uploadStatus === void 0).map((att) => ({ ...att, url: att.url }));
          await onSendMessage(
            nextMessage.content,
            chatId,
            validAttachments && validAttachments.length > 0 ? validAttachments : void 0,
            nextMessage.modelId,
            userMessage.id
          );
          queueActions.dequeueMessage(userMessage.id, "sendingQueue");
        } catch (error) {
          queueActions.dequeueMessage(userMessage.id, "sendingQueue");
          queueActions.enqueueMessage(userMessage.id, "failedQueue");
          messageActions.updateMessage(userMessage.id, {
            status: Status.Failed,
            error: {
              message: error instanceof Error ? error.message : "Failed to send message",
              timestamp: (/* @__PURE__ */ new Date()).toISOString()
            }
          });
          throw error;
        } finally {
          concurrencyActions.decrementActiveSessions();
        }
      }
    } catch (error) {
      console.error("Send queued message failed:", error);
    }
  });
  useEffect(() => {
    if (!streamingStatus.isStreaming && hasPendingMessages) {
      const timer = setTimeout(() => {
        sendNextQueuedMessage();
      }, 500);
      return () => clearTimeout(timer);
    }
  }, [streamingStatus.isStreaming, hasPendingMessages, sendNextQueuedMessage]);
  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);
  const sendJumpQueueMessage = useEventCallback(async (messageId) => {
    const pendingMessages = queueComputed$.sortedPendingMessages.peek();
    const jumpMessage = pendingMessages.find((msg) => msg.id === messageId);
    if (!jumpMessage) {
      console.error(`Jump queue message not found with ID: ${messageId}`);
      return;
    }
    console.log(`🚀 Sending jump queue message: "${jumpMessage.content}"`);
    queueActions.removePendingMessage(messageId);
    try {
      let chatId = currentChat?.id;
      if (!chatId) {
        if (onCreateNewChat) {
          chatId = onCreateNewChat();
        } else {
          console.warn("No current chat available and no onCreateNewChat provided");
          return;
        }
      }
      const userMessage = {
        id: nanoid(),
        content: jumpMessage.content,
        role: Role.User,
        timestamp: (/* @__PURE__ */ new Date()).toISOString(),
        createdAt: (/* @__PURE__ */ new Date()).toISOString(),
        version: 1,
        isStreaming: false,
        status: Status.Pending,
        retryCount: 0,
        maxRetries: 3,
        abortController: new AbortController(),
        attachments: jumpMessage.attachments
      };
      messageActions.addMessage(userMessage);
      if (onSendMessage && chatId) {
        concurrencyActions.incrementActiveSessions();
        queueActions.enqueueMessage(userMessage.id, "sendingQueue");
        try {
          const validAttachments = jumpMessage.attachments?.filter(
            (att) => att.uploadStatus === "completed" || att.uploadStatus === void 0
          ).map((att) => ({ ...att, url: att.url }));
          await onSendMessage(
            jumpMessage.content,
            chatId,
            validAttachments && validAttachments.length > 0 ? validAttachments : void 0,
            jumpMessage.modelId,
            userMessage.id
          );
          queueActions.dequeueMessage(userMessage.id, "sendingQueue");
        } catch (error) {
          queueActions.dequeueMessage(userMessage.id, "sendingQueue");
          queueActions.enqueueMessage(userMessage.id, "failedQueue");
          messageActions.updateMessage(userMessage.id, {
            status: Status.Failed,
            error: {
              message: error instanceof Error ? error.message : "Failed to send jump queue message",
              timestamp: (/* @__PURE__ */ new Date()).toISOString()
            }
          });
          throw error;
        } finally {
          concurrencyActions.decrementActiveSessions();
        }
      }
    } catch (error) {
      console.error("Send jump queue message failed:", error);
    }
  });
  const handleStopStreaming = useEventCallback(
    () => {
      if (streamingStatus.isStreaming && streamingStatus.currentMessageId) {
        messageActions.cancelStreamingMessage(streamingStatus.currentMessageId);
        streamingActions.stopStreaming();
      }
      const pendingMessages = queueComputed$.sortedPendingMessages.peek();
      const combinedContent = pendingMessages.map((msg) => msg.content).join("\n");
      const allAttachments = [];
      pendingMessages.forEach((msg) => {
        if (msg.attachments && msg.attachments.length > 0) {
          allAttachments.push(...msg.attachments);
        }
      });
      const uniqueAttachments = allAttachments.filter((attachment, index, arr) => {
        return arr.findIndex(
          (a) => a.id === attachment.id || a.url && attachment.url && a.url === attachment.url
        ) === index;
      });
      queueActions.clearAllQueues();
      return {
        combinedAttachments: uniqueAttachments,
        combinedContent
      };
    }
  );
  return {
    // 状态
    canSendMessage,
    canSendNewMessage,
    streamingStatus,
    isSending,
    hasPendingMessages,
    // 方法
    handleSendMessage,
    handleStopStreaming,
    getSendButtonState,
    checkUnuploadedFiles,
    sendNextQueuedMessage,
    sendJumpQueueMessage,
    addMessageToQueue
  };
}
export {
  useMessageSending
};
//# sourceMappingURL=use-message-sending.js.map
