import type { AxiosRequestConfig } from "axios";

import type { IChatWithLLMRequest, UsageInfo } from "@/interfaces";
import BaseClientService, { BaseUrl } from "./base_service.ts";

export class ChatService {
  public static basePath = BaseUrl;

  /** Chat with LLM */
  public static async ChatWithLLM(
    accessToken: string,
    request: IChatWithLLMRequest,
    onProgress: (content: string) => void,
    getUsageInfo: (object: UsageInfo) => void = () => {},
    getThinking: (thinkingContent: string) => void
  ) {
    let response;
    let buffer = "";
    let accumulatedContent = "";
    let thinking = false;
    let thinkingContent = "";
    try {
      response = await fetch("/v1/chat/completions", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${accessToken}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify(request)
      });

      if (!response.ok) {
        // eslint-disable-next-line unicorn/error-message
        throw new Error();
      }

      const reader = response.body?.getReader();
      const decoder = new TextDecoder();

      while (true) {
        const { done, value } = await reader!.read();

        if (done) break;

        // 将二进制数据转为字符串并存入缓冲区
        buffer += decoder.decode(value);

        // 查找换行符分割数据
        const lines = buffer.split("\n");

        // 保留未处理完的部分
        buffer = lines.pop() || "";

        // 处理每一行
        for (const line of lines) {
          const trimmedLine = line.trim();
          if (!trimmedLine) continue;

          if (trimmedLine.startsWith("data: ")) {
            const jsonStr = trimmedLine.slice(6);

            // 处理结束标记
            if (jsonStr === "[DONE]") {
              onProgress(accumulatedContent); // 最终更新
              return;
            }

            try {
              const data = JSON.parse(jsonStr);

              // 处理内容
              if (data.choices?.[0]?.delta?.content) {
                const content = data.choices[0].delta.content;

                if (content.includes("<think>")) {
                  thinking = true;
                  // 只处理<think>前的内容
                  const [beforeThink, afterThink] = content.split("<think>");
                  if (beforeThink) {
                    accumulatedContent += beforeThink;
                    onProgress(accumulatedContent);
                  }
                  thinkingContent = "";
                  if (afterThink) {
                    thinkingContent += afterThink;
                    getThinking(thinkingContent);
                  }
                  continue;
                }

                if (content.includes("</think>")) {
                  thinking = false;
                  // 只处理</think>后的内容
                  const [beforeEndThink, afterEndThink] =
                    content.split("</think>");
                  thinkingContent += beforeEndThink;
                  getThinking(thinkingContent);
                  if (afterEndThink) {
                    accumulatedContent += afterEndThink;
                    onProgress(accumulatedContent);
                  }
                  thinkingContent = "";
                  continue;
                }

                if (thinking) {
                  thinkingContent += content;
                  getThinking(thinkingContent);
                } else {
                  accumulatedContent += content;
                  onProgress(accumulatedContent);
                }
              }

              // 处理使用信息
              if (data.usage) {
                const { prompt_tokens, completion_tokens, total_tokens } =
                  data.usage;
                getUsageInfo({
                  prompt_tokens,
                  completion_tokens,
                  total_tokens
                });
              }
            } catch (err) {
              console.error("JSON解析失败:", err);
            }
          }
        }
      }
    } catch (err) {
      console.error("Error:", err);
    }
  }

  // 获取模型列表
  public static GetModelList(config?: AxiosRequestConfig<any>) {
    return BaseClientService.get(`${this.basePath}/model/list`, config);
  }

  // 获取音色列表
  public static GetSpeakerList(config?: AxiosRequestConfig<any>) {
    return BaseClientService.get(`${this.basePath}/speaker/list`, config);
  }
}
