import AgentApi, { type AgentChatModel } from "@/api/agent/Agent";
import AgentWorkApi from "@/api/agent/AgentWorks";
import { nextTick, onBeforeUnmount, onMounted, ref, type Ref } from "vue";
import { ChatUtils } from "../utils/ChatUtils";
import { ChatMessage as ChatMessageModel } from "../model/Message";
import { useMessages, LocalMessageIdPool, mergeSystemMessages } from "./Messages";
import { useToolCalls } from "./ToolCall";
import { useChatStaticMessages } from "./StaticMessages";
import { useChatContext, type ContextMemoryConfig, type ContextMemorySetting } from "./Context";
import { useChatTools, type ChatToolsManager } from "./Tools";
import type { ChatSessionManager } from "../composables/useChatSession";
import type { SSE } from "./speical/ssemp";
import type OpenAI from "openai";
import { requireNotNull } from "@imengyu/imengyu-utils";

export type ChatModelOptionValue = {
  temperature: number;
  top_p: number;
  top_k: number;
  presence_penalty: number;
};

export type ChatAttachmentStatus = 'uploading' | 'success' | 'error';
export type ChatAttachmentType = 'image' | 'audio' | 'video' | 'text' | 'document' | 'unknown';

export interface ChatAttachmentItem {
  id?: number;
  localId: string;
  name: string;
  size: number;
  status: ChatAttachmentStatus;
  path?: string;
  url?: string;
  type: ChatAttachmentType;
  errorMessage?: string;
  file: File;
}
export type ChatInterfaceManager = {
  messages: Ref<ChatMessageModel[]>;
  focusInput?: () => void;
  setInputValue?: (value: string) => void;
  scrollToBottom?: () => void;
  stopMessageEditing?: () => void;
  uploadAttachment?: () => void;
  getAttachmentList?: () => Promise<ChatAttachmentItem[]>;
};
export interface ChatConfig {
  /**
   * 默认系统提示词
   * @default ''
   */
  defaultSystemPrompt?: string;

  /**
   * 上下文记忆设置
   * @default 'short'
   */
  contextMemorySetting?: ContextMemorySetting;
  /**
   * 上下文记忆参数配置
   */
  contextMemoryConfig?: ContextMemoryConfig;

  /**
   * 构建欢迎消息
   */
  onBuildWelcome?: () => {
    /**
     * 欢迎消息
     * @default ''
     */
    welcomeMessage?: string;
    /**
     * 欢迎动作
     * @default []
     */
    welcomeActions?: string[];
  };
  /**
   * 获取发送选项
   * @returns 
   */
  onGetSendOptions: () => ChatSendOptions;

  /**
   * 新对话
   * @param isNewChat - 是否是新对话
   */
  onNewChat?: (isNewChat: boolean) => void;
  /**
   * 消息合并前
   * @param message - 消息
   */
  onBeforeMessageMerge?: (userMessages: ChatMessageModel[], currentUserMessageIds: number[]) => void;
  /**
   * 发送消息前
   * @param message - 消息
   */
  onBeforeSend?: (userMessages: ChatMessageModel[], streamOptions: any) => void;
  /**
   * 程序追加消息，不保存到数据库
   * @returns 
   */
  onGetAppendMessages?: () => ChatMessageModel[];
  /**
   * 对话消息结束
   * @param message - 消息
   * @param currentUserMessageIds - 当前用户消息ID列表
   */
  onAiMessageFinish?: (message: ChatMessageModel, currentUserMessageIds: number[], finishReason: string) => void;

  /**
   * 是否在ai回答后自动生成可能的问题
   * @default false
   */
  autoGeneratePossibleQuestions?: boolean;

  /**
   * 初始化工具
   * @param toolsManager - 工具管理器
   * @returns 
   */
  onInitTools?: (toolsManager: ChatToolsManager) => void;
}

export type ChatSendOptions = {
  enableSearch: boolean;
  enableThinking: boolean;
  model: string;
  modelInfo: AgentChatModel ;
  customSystemPrompt?: string|null;
  chatOptions: ChatModelOptionValue;
};

export function useChat(options: {
  config: ChatConfig;
  interfaceManager: ChatInterfaceManager;
  sessionManager: ChatSessionManager;
}) {
 
  const isLoading = ref(false);
  const config = options.config;
  let streamingAiMessageId: number | null = null;
  let eventSource: SSE | null = null;
  let startTime = 0;

  const messages = options.interfaceManager.messages;
  const referenceMessage = ref('');
  const messagesManager = useMessages(messages);
  const toolsManager = useChatTools(); options.config?.onInitTools?.(toolsManager);
  const staticMessagesManager = useChatStaticMessages(config);
  const sessionManager = options.sessionManager;
  const interfaceManager = options.interfaceManager;
  const contextManager = useChatContext({
    message: messages,
    contextMemorySetting: config.contextMemorySetting,
    contextMemoryConfig: config.contextMemoryConfig,
    sessionManager: sessionManager,
    onGetAppendMessages: config.onGetAppendMessages,
  });
  const toolCallsManager = useToolCalls(messagesManager, toolsManager, interfaceManager, sessionManager);

  //新建会话消息构建
  sessionManager.events.on('session-newed', () => {
    messages.value = [staticMessagesManager.getWelcomeMessage()];
    config.onNewChat?.(true);
    contextManager.estimateTokenUseage(config.onGetSendOptions());
  });
  //加载会话消息构建
  sessionManager.events.on('session-loaded', (session) => {
    config.onNewChat?.(false);
    contextManager.estimateTokenUseage(config.onGetSendOptions());
  });

  async function buildStreamOptions(
    sendOptions: ChatSendOptions,
    currentUserMessageIds: number[],
    limitHistoryStartAtMessageId: number|undefined,
    openAiTools: OpenAI.Chat.Completions.ChatCompletionTool[],
  ) {
    const finalMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [];

    /**
     * 构建系统消息
     */
    const systemMessages = [] as OpenAI.Chat.ChatCompletionSystemMessageParam[];
    if (sendOptions?.customSystemPrompt)
      systemMessages.push({ role: 'system', content: sendOptions.customSystemPrompt.trim() });
    else if (config.defaultSystemPrompt)
      systemMessages.push({ role: 'system', content: config.defaultSystemPrompt.trim() });

    /**
     * 构建用户消息
     */
    const { 
      userMessages, 
      systemMessages: contextSystemMessages 
    } = await contextManager.convertMessagesToAi(sendOptions, currentUserMessageIds, limitHistoryStartAtMessageId);

    const referenceSystemMessages: OpenAI.Chat.ChatCompletionSystemMessageParam[] = [];
    if (referenceMessage.value)
      referenceSystemMessages.push({ role: 'system', content: `[用户引用消息] ${referenceMessage.value.trim()}` });

    finalMessages.push(
      //合并系统消息
      ...mergeSystemMessages([
        ...systemMessages,
        ...referenceSystemMessages,
        ...(contextSystemMessages) as OpenAI.Chat.ChatCompletionSystemMessageParam[], 
      ]),
      ...userMessages,
    );

    if (finalMessages.length === 0)
      throw new Error('消息不能为空');
  
    /**
     * 构建额外选项
     */
    const extraOptions = {
      enable_thinking: sendOptions.enableThinking ?? undefined,
      enable_search: sendOptions.enableSearch ?? undefined,
    };
    const chartOptions: OpenAI.Chat.Completions.ChatCompletionCreateParams = {
      stream: true,
      model: sendOptions.model,
      ...sendOptions.chatOptions || {},
      messages: finalMessages,
      tools: openAiTools.length ? openAiTools : undefined,
      tool_choice: openAiTools.length ? 'auto' : undefined,
    };
    return {
      ...chartOptions,
      ...extraOptions,
    };
  }

  /**
   * 对话逻辑
   */
  async function startStreamForUserMessages(
    currentUserMessageIds: number[], 
    aiMessageId?: number,
    limitHistoryStartAtMessageId?: number
  ) {
    const sendOptions = config.onGetSendOptions();
    if (!sendOptions.model)
      throw new Error('模型不能为空');

    let aiMessage: ChatMessageModel;
    if (!aiMessageId) {
      aiMessageId = LocalMessageIdPool.getNextId();
      aiMessage = messagesManager.addMessage(ChatMessageModel.createAssistant("", aiMessageId, "loading"));
    } else {
      aiMessage = requireNotNull(messagesManager.findMessage(aiMessageId));
    }
    aiMessage.parentId = currentUserMessageIds[0];
    aiMessage.state = "loading";
    aiMessage.name = sendOptions.modelInfo.name ?? '';

    //持久化消息
    if (!aiMessage.isPersisted)
      await sessionManager.persistMessages([aiMessage]);
    await nextTick();
    await interfaceManager.scrollToBottom?.();

    streamingAiMessageId = aiMessage.id;
    startTime = Date.now();

    const toolCallBuffers = new Map<number, { id?: string; name?: string; arguments: string }>();
    let streamOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming;
    try {
      config.onBeforeMessageMerge?.(messages.value.filter(m => currentUserMessageIds.includes(m.id)), currentUserMessageIds);

      // 用于拼接 tool_calls 的 arguments（流式会分片）
      streamOptions = await buildStreamOptions(
        sendOptions,
        currentUserMessageIds, 
        limitHistoryStartAtMessageId,
        toolsManager.openAiTools.value
      );

      config.onBeforeSend?.(messages.value.filter(m => currentUserMessageIds.includes(m.id)), streamOptions);
    } catch (error) {
      console.error("构建流式选项失败:", error);
      failedAndSetInfo("处理消息失败", error);
      return;
    }

    eventSource = AgentApi.chatStream(streamOptions as OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming);
    eventSource.onmessage = async (event) => {
      try {
        const data = JSON.parse(event.data);

        // 后端通过 SSE 下发错误（含超时等）
        if (data?.error) {
          eventSource?.close();
          isLoading.value = false;
          streamingAiMessageId = null;

          const errorType = String(data.errorType || '');
          const errorText = typeof data.error === 'string' ? data.error : '请求失败';
          const title =
            errorType === 'timeout_connect' || errorType === 'timeout_idle'
              ? '请求超时'
              : '请求错误';
          aiMessage.content = errorType.startsWith('timeout')
            ? '请求超时，请检查模型地址/网络后重试。'
            : '失败，请稍后重试。';
          aiMessage.setError(title, errorText);
          await sessionManager.persistMessages([aiMessage]);
          return;
        }

        if (!data.chunk) return;
        const chunk = data.chunk as OpenAI.Chat.ChatCompletionChunk;
        const choice = chunk.choices[0];
        if (!choice) return;

        // 结束处理
        if (choice.finish_reason) {
          //结束状态
          isLoading.value = false;
          streamingAiMessageId = null;

          const isAiMessageEmpty = aiMessage.content === '' && aiMessage.reasoningContent === '';
          const finishReason = choice.finish_reason;
          aiMessage.state = "success";
          aiMessage.replyTime = Date.now() - startTime;

          switch (finishReason) {
            case "tool_calls": {
              // 如果内容与思考内容都为空，则说明ai进行了工具调用
              if (isAiMessageEmpty)  {
                aiMessage.content = '准备执行工具调用...';
              }
              break;
            }
          }

          //持久化消息
          sessionManager.persistAssistantAfterStream(aiMessage, currentUserMessageIds);
          config.onAiMessageFinish?.(aiMessage, currentUserMessageIds, finishReason);
          contextManager.estimateTokenUseage(sendOptions);

          switch (finishReason) {
            case "stop": {
              //如果需要自动生成可能的问题，则生成可能的问题
              if (config.autoGeneratePossibleQuestions && !isAiMessageEmpty) {
                const userMessage = messages.value.find(m => currentUserMessageIds.includes(m.id))?.content;
                const possibleQuestions = await AgentWorkApi.autoGeneratePossibleQuestions(userMessage ?? '', aiMessage.content);
                aiMessage.actions = possibleQuestions;
              }
              break;
            }
            case "tool_calls": {
              //工具调用处理

              const toolCalls: OpenAI.Chat.ChatCompletionMessageToolCall[] = [...toolCallBuffers.entries()]
                .sort((a, b) => a[0] - b[0])
                .map(([, b]) => ({
                  id: b.id || `call_${Math.random().toString(16).slice(2)}`,
                  type: "function",
                  function: {
                    name: b.name || "unknown",
                    arguments: b.arguments || "",
                  },
                }));

              // 把 tool_calls 挂在 assistant 消息上，便于下一轮历史回放（如果后端严格校验）
              aiMessage.toolCalls = toolCalls;

              // 执行工具 -> 追加 tool 消息 -> 再发起一轮 stream 获取最终回答
              await toolCallsManager.executeToolCalls(toolCalls, aiMessage.parentId);

              // 继续一轮对话（同一批 user messages）
              isLoading.value = true;
              await startStreamForUserMessages(currentUserMessageIds);
              return;
            }
          }
        }

        // 结束后关闭
        if (data.finished) {
          closeStream();
          return;
        }

        // tool_calls 拼接
        const delta: any = choice.delta as any;
        if (Array.isArray(delta?.tool_calls)) {
          for (const tc of delta.tool_calls as any[]) {
            const index = tc.index ?? 0;
            const buf = toolCallBuffers.get(index) ?? { arguments: "" };
            if (tc.id) buf.id = tc.id;
            if (tc.function?.name) buf.name = tc.function.name;
            if (typeof tc.function?.arguments === "string") buf.arguments += tc.function.arguments;
            toolCallBuffers.set(index, buf);
          }
        }

        // 内容/思考内容
        if (choice?.delta?.content) {
          aiMessage.content += choice.delta.content;
          //如果思考内容不为空，则计算推理时间
          if (aiMessage.reasoningContent && aiMessage.reasoningTime === 0)
            aiMessage.reasoningTime = Date.now() - startTime;
        } else if (delta?.reasoning_content) {
          aiMessage.reasoningContent += delta.reasoning_content;
        }

      } catch (error) {
        // 解析失败不应打断整个对话
        console.error("解析SSE数据失败:", error);
      }
    };

    eventSource.onerror = (error) => {
      console.error("SSE连接错误:", error);
      eventSource?.close();
      isLoading.value = false;
      streamingAiMessageId = null;

      if (('' +error).includes('402')) {
        aiMessage.content = "您今日的对话次数已用完，请明日再来吧。";
        aiMessage.state = "error";
      } else {
        aiMessage.content = "失败，请稍后重试。";
        aiMessage.setError("请求错误", ChatUtils.formatError(error));
      }
      sessionManager.persistMessages([aiMessage]);
    };

    eventSource.stream();
  }

  /**
   * 发送消息
   * @param inputMessage - 输入消息
   */
  async function send(inputMessage: string) {
    if (isLoading.value) return;

    const userMessage = inputMessage.trim();
    if (!userMessage) {
      messagesManager.addMessage(staticMessagesManager.getEmptyMessage());
      return;
    }

    interfaceManager.stopMessageEditing?.();

    const newMessages = [
      messagesManager.addMessage(ChatMessageModel.createUser(userMessage, LocalMessageIdPool.getNextId()))
    ];
    const attachmentItems = await interfaceManager.getAttachmentList?.() || [];
    for (const item of attachmentItems) {
      const m = await ChatMessageModel.createAttachment(item, LocalMessageIdPool.getNextId());
      m.name = '你';
      newMessages.push(messagesManager.addMessage(m));
    }

    // 保存用户消息与会话
    try {
      await sessionManager.saveUserMessageAndPersistSession(newMessages);

    } catch (error) {
      newMessages.forEach((m) => {
        m.setError("保存会话失败，请稍后重试。", ChatUtils.formatError(error));
      });
      return;
    }

    await nextTick();

    try {
      isLoading.value = true;
      await startStreamForUserMessages(newMessages.map((m) => m.id));
    } catch (error) {
      console.error("失败:", error);
      isLoading.value = false;
      streamingAiMessageId = null;
      const message = messages.value[messages.value.length - 1];
      if (message && !message.isUser) {
        message.content = "失败，请稍后重试。";
        message.setError("请求错误", ChatUtils.formatError(error));
      }
    }
  }
  /**
   * 停止对话
   */
  function stop() {
    failedAndSetInfo("手动停止对话", null);
    closeStream();
    isLoading.value = false;
  }  

  function failedAndSetInfo(message: string, error: any) {
    isLoading.value = false;
    if (streamingAiMessageId) {
      const aiMessage = messagesManager.findMessage(streamingAiMessageId);
      if (aiMessage) {
        aiMessage.content = message;
        aiMessage.setError(message, ChatUtils.formatError(error));
        sessionManager.persistMessages([aiMessage]);
      }
    }
    streamingAiMessageId = null;
  }
  function closeStream() {
    if (eventSource) {
      eventSource.close();
      eventSource = null;
    }
  }
  function prefindUserMessageIds(messageId: number) {
    let limitHistoryStartAtMessageId: number | undefined;
    const currentUserMessageIds = [] as number[];
    for (let i = messages.value.findIndex(m => m.id === messageId); i >= 0; i--) {
      const message = messages.value[i];
      if (message.isUser)
        currentUserMessageIds.push(message.id);
    }
    return {
      currentUserMessageIds,
      limitHistoryStartAtMessageId,
    };
  }

  /**
   * 用户编辑消息，重新发送
   * @param messageId 
   */
  async function editMessage(messageId: number, newContent: string) {
    const message = messagesManager.findMessage(messageId);
    if (!message)
      return;

    message.content = newContent;
    if (message.isPersisted)
      await sessionManager.persistMessages([message]);
 
    //向上查找，找到本轮次所有用户消息ID
    const { currentUserMessageIds, limitHistoryStartAtMessageId } = prefindUserMessageIds(messageId);
    if (message.replyItemId) {
      //如果已有回复，则清空回复内容
      const replyMessage = messagesManager.findMessage(message.replyItemId);
      if (replyMessage) {
        replyMessage.content = '';
        replyMessage.reasoningContent = '';
        replyMessage.resetError();
      }
      await startStreamForUserMessages(currentUserMessageIds, message.replyItemId, limitHistoryStartAtMessageId);
    }
    else
      await startStreamForUserMessages(currentUserMessageIds, undefined, limitHistoryStartAtMessageId);
  }

  /**
   * 重新生成AI消息
   * @param messageId 
   */
  async function regenerateMessage(messageId: number) {
    const message = messagesManager.findMessage(messageId);
    if (!message)
      return;
    if (!message.isAssistant)
      return;
    message.content = '';
    message.reasoningContent = '';
    message.resetError();
    //向上查找，找到本轮次所有用户消息ID
    const { currentUserMessageIds, limitHistoryStartAtMessageId } = prefindUserMessageIds(messageId);
    await startStreamForUserMessages(currentUserMessageIds, message.id, limitHistoryStartAtMessageId);
  }

  /**
   * 设置参考消息并等待用户输入
   * @param message - 参考消息
   */
  async function setReferenceAndWaitUser(message: string) {
    referenceMessage.value = message;
    interfaceManager.focusInput?.();
  }

  /**
   * 清空参考消息
   */
  function clearReferenceMessage() {
    referenceMessage.value = '';
  }

  onMounted(async () => {
    if (sessionManager.enableSession) {
      try {
        await sessionManager.loadSessions();
        sessionManager.onSelectNew();
      } catch (error) {
        console.error("加载会话失败:", error);
        sessionManager.onSelectLocal();
      }
    } else {
      sessionManager.onSelectLocal();
    }
  });
  onBeforeUnmount(() => {
    stop();
  });

  return {
    send,
    stop,
    editMessage,
    regenerateMessage,
    setReferenceAndWaitUser,
    clearReferenceMessage,
    config,
    isLoading,
    messages,
    referenceMessage,
    staticMessagesManager,
    toolsManager,
    messagesManager,
    sessionManager,
    interfaceManager,
    toolCallsManager,
    contextManager,
  }

}

export type ChatManager = ReturnType<typeof useChat>;