import OpenAI from "openai";
import { log } from "./log.js";
import { Session } from "./session.js";
import { Prompt } from "./prompt.js";

import { aiConfigManager } from "./config.js";

type MessageItem = {
  role: "system" | "user" | "assistant";
  content: string;
};

export type LLMConfig = {
  apiKey: string;
  baseURL: string;
  model: string;
};

export class AbortError extends Error {
  constructor(message?: string) {
    super(message);
    this.name = "AbortError";
  }
}

export class AIChat {
  private session: Session;
  private messages: MessageItem[] = [];

  addMessage(messageItem: MessageItem) {
    log.info("对话：", messageItem);
    this.messages.push(messageItem);
  }

  getMessages() {
    return this.messages;
  }

  constructor(systemPrompt: string, session: Session) {
    this.session = session;

    this.addMessage({
      role: "system",
      content: systemPrompt,
    });
  }
  /**
   * 流式对话，逐步推送内容
   * @param usermessage 用户输入
   * @returns 最终完整回复
   */
  async chat(usermessage: string) {
    // 创建新的 AbortController
    const abortController = new AbortController();
    const _cancel = () => {
      abortController.abort();
    };

    const _chat = async (usermessage: string) => {
      this.addMessage({
        role: "user",
        content: usermessage,
      });

      const config = aiConfigManager.getConfig();
      const chatClient = new OpenAI({
        apiKey: config.apiKey,
        baseURL: config.baseURL,
        // 在浏览器环境时允许调用
        ...((typeof globalThis !== 'undefined' && 'window' in globalThis)
          ? { dangerouslyAllowBrowser: true }
          : {}),
      });

      let reply = "";
      // 向大模型进行流式问答
      const stream = await chatClient.chat.completions.create(
        {
          model: config.model,
          messages: this.messages,
          stream: true,
        },
        {
          signal: abortController.signal,
        }
      );

      for await (const chunk of stream) {
        // 检查中止信号
        if (abortController.signal.aborted) {
          throw new AbortError();
        }

        const delta = chunk.choices?.[0]?.delta?.content || "";
        if (delta) {
          reply += delta;
          this.session.emit("reply", delta);
        }
      }

      this.addMessage({ role: "assistant", content: reply });
      return reply;
    };

    try {
      this.session.on("cancel", _cancel);
      const reply = await _chat(usermessage);
      return reply;
    } finally {
      this.session.off("cancel", _cancel);
    }
  }
}

export class ChatManager {
  private session: Session;
  private prompt: Prompt;
  constructor({ session }: { session: Session }) {
    this.session = session;
    this.prompt = new Prompt();
  }

  private createChat(system_propmt: string): AIChat {
    const chatClient = new AIChat(system_propmt, this.session);
    return chatClient;
  }

  async createMcpChat() {
    const system_propmt = await this.prompt.buildMcpPrompt();
    return this.createChat(system_propmt);
  }

  async createFixJsonChat() {
    const system_propmt = await this.prompt.buildFixJsonPrompt();
    return this.createChat(system_propmt);
  }
}
