import { nextTick, type Ref } from "vue";
import { LocalMessageIdPool, type ChatMessagesManager } from "./Messages";
import { ChatMessage as ChatMessageModel } from "../model/Message";
import { ChatUtils } from "../utils/ChatUtils";
import type OpenAI from "openai"
import type { ChatToolContext, ChatToolsManager } from "./Tools";
import type { ChatInterfaceManager } from "./Chat";
import type { ChatSessionManager } from "../composables/useChatSession";

export function useToolCalls(
  messagesManager: ChatMessagesManager,
  toolsManager: ChatToolsManager,
  interfaceManager: ChatInterfaceManager,
  sessionManager: ChatSessionManager
) {
  /**
   * 执行工具调用
   */
  async function executeToolCalls(toolCalls: OpenAI.Chat.ChatCompletionMessageToolCall[], parentMessageId: number) {
    const ctx: ChatToolContext = {
      messages: messagesManager.messages as Ref<ChatMessageModel[]>,
      scrollToBottom: interfaceManager.scrollToBottom,
    };

    for (const call of toolCalls) {
      if (call.type !== "function") continue;

      const name = call.function.name;
      const tool = toolsManager.toolRegistry.value.get(name);
      const newToolMessageId = LocalMessageIdPool.getNextId();
      const toolMsg = messagesManager.addMessage(ChatMessageModel.createTool(name, `调用工具 ${name}`, newToolMessageId) as ChatMessageModel);;
      toolMsg.parentId = parentMessageId;

      try {

        if (!tool)
          throw new Error(`未找到工具：${name}`);

        let args: any = call.function.arguments;
        if (typeof args === "string" && args.trim()) {
          try {
            args = JSON.parse(args);
          } catch (error) { 
            throw new Error('工具参数解析失败: ' +  (error as Error).message);
          }
        }
        const rs = await tool.handler(args, ctx);
        if (toolMsg) {
          toolMsg.content += ' 成功'
          toolMsg.extra = (typeof rs === "string" ? rs : JSON.stringify(rs, null, 2));
          toolMsg.state = "success";
        }
      } catch (error) {
        toolMsg.state = "error";
        toolMsg.content += ' 失败';
        toolMsg.setError("工具执行失败", ChatUtils.formatError(error));
      }

      if (toolMsg) {
        try {
          await sessionManager.persistMessages([toolMsg]);
        } catch (error) {
          console.error(error);
        }
      }

      await nextTick();
      await interfaceManager.scrollToBottom?.();
    }
  }

  return {
    executeToolCalls,
  }
}