"use client";
'use strict';

const jsxRuntime = require('react/jsx-runtime');
const react = require('@ai-sdk/react');
const React = require('react');
const reactQuery = require('@tanstack/react-query');
const chatMessage = require('./chat-message.cjs');
const chatInput = require('./chat-input.cjs');
const stackAttribution = require('../../../../../../ui/src/components/stack-attribution.cjs');
const scrollArea = require('../../../../../../ui/src/components/scroll-area.cjs');
const ai = require('ai');
const utils = require('../../../../../../ui/src/lib/utils.cjs');
const context = require('@btst/stack/context');
const index = require('../localization/index.cjs');
const client = require('@btst/stack/plugins/client');
const plugins_aiChat_queryKeys = require('../../../../../../../plugins/ai-chat/query-keys.cjs');
const chatHooks = require('../hooks/chat-hooks.cjs');

function ChatInterface({
  apiPath = "/api/chat",
  initialMessages,
  id,
  variant = "full",
  className,
  onMessagesChange
}) {
  const {
    navigate,
    localization: customLocalization,
    apiBaseURL,
    apiBasePath,
    headers,
    mode,
    showAttribution,
    chatSuggestions
  } = context.usePluginOverrides(
    "ai-chat",
    { showAttribution: true }
  );
  const basePath = context.useBasePath();
  const isPublicMode = mode === "public";
  const localization = { ...index.AI_CHAT_LOCALIZATION, ...customLocalization };
  const queryClient = reactQuery.useQueryClient();
  const conversationsListQueryKey = React.useMemo(() => {
    if (isPublicMode) return ["ai-chat", "disabled"];
    const client$1 = client.createApiClient({
      baseURL: apiBaseURL,
      basePath: apiBasePath
    });
    const queries = plugins_aiChat_queryKeys.createAiChatQueryKeys(client$1, headers);
    return queries.conversations.list().queryKey;
  }, [apiBaseURL, apiBasePath, headers, isPublicMode]);
  const [currentConversationId, setCurrentConversationId] = React.useState(isPublicMode ? void 0 : id);
  const isFirstMessageSentRef = React.useRef(false);
  const hasNavigatedRef = React.useRef(false);
  React.useEffect(() => {
    if (!isPublicMode) {
      setCurrentConversationId(id);
      isFirstMessageSentRef.current = false;
      hasNavigatedRef.current = false;
      isEditInProgressRef.current = false;
    }
  }, [id, isPublicMode]);
  const { conversation, isLoading: isLoadingConversation } = chatHooks.useConversation(
    id,
    { enabled: !!id && !isPublicMode }
  );
  const { conversations } = chatHooks.useConversations({ enabled: !isPublicMode });
  const conversationIdRef = React.useRef(
    isPublicMode ? void 0 : id
  );
  React.useEffect(() => {
    if (!isPublicMode) {
      conversationIdRef.current = currentConversationId;
    }
  }, [currentConversationId, isPublicMode]);
  const editMessagesRef = React.useRef(null);
  const isEditInProgressRef = React.useRef(false);
  const [isMessagesInitialized, setIsMessagesInitialized] = React.useState(
    () => (
      // Start as initialized if there are no initialMessages to load
      !initialMessages || initialMessages.length === 0
    )
  );
  const transport = React.useMemo(
    () => new ai.DefaultChatTransport({
      api: apiPath,
      // In public mode, don't send conversationId
      body: isPublicMode ? void 0 : () => ({ conversationId: conversationIdRef.current }),
      // Handle edit operations by using truncated messages from the ref
      prepareSendMessagesRequest: ({ messages: hookMessages }) => {
        if (editMessagesRef.current !== null) {
          const newUserMessage = hookMessages[hookMessages.length - 1];
          const messagesToSend = [...editMessagesRef.current];
          if (newUserMessage) {
            messagesToSend.push(newUserMessage);
          }
          editMessagesRef.current = null;
          return {
            body: {
              messages: messagesToSend,
              conversationId: conversationIdRef.current
            }
          };
        }
        return {
          body: {
            messages: hookMessages,
            conversationId: conversationIdRef.current
          }
        };
      }
    }),
    [apiPath, isPublicMode]
  );
  const { messages, sendMessage, status, error, setMessages, regenerate } = react.useChat({
    transport,
    onError: (err) => {
      console.error("useChat onError:", err);
      if (!id && !hasNavigatedRef.current) {
        isFirstMessageSentRef.current = false;
      }
    },
    onFinish: async () => {
      if (isPublicMode) return;
      await queryClient.invalidateQueries({
        queryKey: conversationsListQueryKey
      });
      if (isFirstMessageSentRef.current && !id && !hasNavigatedRef.current) {
        hasNavigatedRef.current = true;
        await queryClient.refetchQueries({
          queryKey: conversationsListQueryKey
        });
        const cachedConversations = queryClient.getQueryData(conversationsListQueryKey);
        if (cachedConversations && cachedConversations.length > 0) {
          const newConversation = cachedConversations[0];
          if (newConversation) {
            setCurrentConversationId(newConversation.id);
            conversationIdRef.current = newConversation.id;
            const newUrl = `${basePath}/chat/${newConversation.id}`;
            if (typeof window !== "undefined") {
              window.history.replaceState(
                { ...window.history.state },
                "",
                newUrl
              );
            }
          }
        }
      }
    }
  });
  React.useEffect(() => {
    if (isEditInProgressRef.current) {
      return;
    }
    if (conversation?.messages && conversation.messages.length > 0 && messages.length === 0) {
      const uiMessages = conversation.messages.filter((m) => m.role !== "data").map((m) => {
        let parts;
        try {
          const parsed = JSON.parse(m.content);
          if (Array.isArray(parsed)) {
            parts = parsed;
          } else {
            parts = [{ type: "text", text: m.content }];
          }
        } catch {
          parts = [{ type: "text", text: m.content }];
        }
        return {
          id: m.id,
          role: m.role,
          parts
        };
      });
      setMessages(uiMessages);
    }
  }, [conversation, messages.length, setMessages]);
  React.useEffect(() => {
    if (initialMessages && initialMessages.length > 0 && messages.length === 0) {
      setMessages(initialMessages);
      setIsMessagesInitialized(true);
    }
  }, [initialMessages, setMessages, messages.length]);
  const [input, setInput] = React.useState("");
  const [attachedFiles, setAttachedFiles] = React.useState([]);
  const scrollRef = React.useRef(null);
  const userHasScrolledRef = React.useRef(false);
  const prevStatusRef = React.useRef(status);
  React.useEffect(() => {
    if (status !== prevStatusRef.current && (status === "streaming" || status === "submitted")) {
      userHasScrolledRef.current = false;
    }
    prevStatusRef.current = status;
  }, [status]);
  React.useEffect(() => {
    const viewport = scrollRef.current?.querySelector(
      "[data-radix-scroll-area-viewport]"
    );
    if (!viewport) return;
    const handleScroll = () => {
      const { scrollTop, scrollHeight, clientHeight } = viewport;
      const isNearBottom = scrollHeight - scrollTop - clientHeight < 50;
      userHasScrolledRef.current = !isNearBottom;
    };
    viewport.addEventListener("scroll", handleScroll);
    return () => viewport.removeEventListener("scroll", handleScroll);
  }, []);
  React.useEffect(() => {
    if (userHasScrolledRef.current) return;
    if (scrollRef.current) {
      const scrollElement = scrollRef.current.querySelector(
        "[data-radix-scroll-area-viewport]"
      );
      if (scrollElement) {
        scrollElement.scrollTop = scrollElement.scrollHeight;
      }
    }
  }, [messages]);
  React.useEffect(() => {
    if (isPublicMode && onMessagesChange && isMessagesInitialized) {
      onMessagesChange(messages);
    }
  }, [messages, isPublicMode, onMessagesChange, isMessagesInitialized]);
  const handleInputChange = (e) => {
    setInput(e.target.value);
  };
  const handleSubmit = async (e, files) => {
    e.preventDefault();
    const text = input.trim();
    if (!text && (!files || files.length === 0)) return;
    if (!isPublicMode && !id && messages.length === 0) {
      isFirstMessageSentRef.current = true;
    }
    userHasScrolledRef.current = false;
    const savedInput = input;
    const savedFiles = files ? [...files] : [];
    const messageCountBeforeSend = messages.length;
    setInput("");
    setAttachedFiles([]);
    try {
      if (files && files.length > 0) {
        const fileUIParts = files.map((file) => ({
          type: "file",
          mediaType: file.mediaType,
          url: file.url,
          filename: file.filename
        }));
        await sendMessage({
          text: text || "",
          // AI SDK requires text, even if empty
          files: fileUIParts
        });
      } else {
        await sendMessage({ text });
      }
    } catch (error2) {
      setInput(savedInput);
      setAttachedFiles(savedFiles);
      if (isFirstMessageSentRef.current && !hasNavigatedRef.current) {
        isFirstMessageSentRef.current = false;
      }
      setMessages((prev) => prev.slice(0, messageCountBeforeSend));
      console.error("Error sending message:", error2);
    }
  };
  const isLoading = status === "streaming" || status === "submitted";
  const handleRetry = React.useCallback(() => {
    regenerate();
  }, [regenerate]);
  const [pendingEdit, setPendingEdit] = React.useState(null);
  React.useEffect(() => {
    if (pendingEdit && messages.length === pendingEdit.expectedLength) {
      const textToSend = pendingEdit.text;
      setPendingEdit(null);
      isEditInProgressRef.current = false;
      sendMessage({ text: textToSend });
    }
  }, [messages.length, pendingEdit, sendMessage]);
  const handleEditMessage = React.useCallback(
    (messageId, newText) => {
      const messageIndex = messages.findIndex((m) => m.id === messageId);
      if (messageIndex === -1) return;
      const messageToEdit = messages[messageIndex];
      if (!messageToEdit || messageToEdit.role !== "user") return;
      const truncatedMessages = messages.slice(0, messageIndex);
      isEditInProgressRef.current = true;
      editMessagesRef.current = truncatedMessages;
      setPendingEdit({ text: newText, expectedLength: messageIndex });
      setMessages(truncatedMessages);
    },
    [messages, setMessages]
  );
  const isWidget = variant === "widget";
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
      "div",
      {
        className: utils.cn(
          "flex flex-col h-full w-full bg-background",
          isWidget && "rounded-xl",
          className
        ),
        "data-testid": "chat-interface",
        "data-chat-status": status,
        children: /* @__PURE__ */ jsxRuntime.jsx(scrollArea.ScrollArea, { ref: scrollRef, className: "flex-1 h-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
          "div",
          {
            className: utils.cn(
              "flex flex-col p-4",
              isWidget ? "max-w-full" : "max-w-3xl mx-auto w-full"
            ),
            children: [
              messages.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full min-h-[300px]", children: [
                /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: localization.CHAT_EMPTY_STATE }) }),
                chatSuggestions && chatSuggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-2 pb-4 max-w-md mx-auto", children: chatSuggestions.map((suggestion, index) => /* @__PURE__ */ jsxRuntime.jsx(
                  "button",
                  {
                    type: "button",
                    onClick: () => setInput(suggestion),
                    className: "px-3 py-2 text-sm rounded-lg border border-border bg-background hover:bg-accent hover:text-accent-foreground transition-colors text-foreground",
                    children: suggestion
                  },
                  index
                )) })
              ] }) : messages.map((m, index) => /* @__PURE__ */ jsxRuntime.jsx(
                chatMessage.ChatMessage,
                {
                  message: m,
                  isStreaming: status === "streaming" && m.id === messages[messages.length - 1]?.id && m.role === "assistant",
                  variant: isWidget ? "compact" : "default",
                  onRetry: (
                    // Only show retry on the last assistant message
                    m.role === "assistant" && index === messages.length - 1 ? handleRetry : void 0
                  ),
                  onEdit: (
                    // Allow editing user messages
                    m.role === "user" ? (newText) => handleEditMessage(m.id, newText) : void 0
                  ),
                  isRetrying: isLoading && m.role === "assistant"
                },
                m.id || `msg-${index}`
              )),
              isLoading && messages[messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 text-muted-foreground text-sm py-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-pulse", children: localization.CHAT_LOADING }) }),
              error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 text-destructive text-sm py-4 px-3 bg-destructive/10 rounded-md", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: localization.CHAT_ERROR }) })
            ]
          }
        ) })
      }
    ) }),
    /* @__PURE__ */ jsxRuntime.jsx(
      "div",
      {
        className: utils.cn(
          "border-t bg-background p-4",
          isWidget ? "px-3 py-3" : "px-4"
        ),
        children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn(!isWidget && "max-w-3xl mx-auto"), children: [
          /* @__PURE__ */ jsxRuntime.jsx(
            chatInput.ChatInput,
            {
              input,
              handleInputChange,
              handleSubmit,
              isLoading,
              placeholder: localization.CHAT_PLACEHOLDER,
              variant: isWidget ? "compact" : "default",
              onFilesAttached: setAttachedFiles,
              attachedFiles
            }
          ),
          showAttribution && /* @__PURE__ */ jsxRuntime.jsx(stackAttribution.StackAttribution, {})
        ] })
      }
    )
  ] });
}

exports.ChatInterface = ChatInterface;
