"use client";
import { REQUEST_TIMEOUT_MS } from "@/app/constant";
import { useChatStore } from "@/app/store";
import {
  ChatOptions,
  LLMApi,
  LLMModel,
} from "../api";
import Locale from "../../locales";
import {
  EventStreamContentType,
  fetchEventSource,
} from "@fortaine/fetch-event-source";
import { prettyObject } from "@/app/utils/format";
import { getMessageTextContent } from "@/app/utils";
import api from "@/app/api/api";
import {processSliceData} from "@/app/utils/index"; 

export class BigModelApi implements LLMApi {
  public baseURL: string;
  public apiPath: string;

  constructor() {
    const chatMode = useChatStore.getState().chatMode;
    // this.baseURL = 'http://xia0miduo.gicp.net:8401';
    this.baseURL = '/bigmodel-api';
    this.apiPath = this.baseURL + '/deepseek/api/chat';
  }

  async chat(options: ChatOptions) {
    const messages = options.messages.map((item) => {
      return {
        role: item.role,
        content: getMessageTextContent(item),
      }
    });

    const userMessages = messages.filter(item => item.content);

    if (userMessages.length % 2 === 0) {
      userMessages.unshift({
        role: "user",
        content: "⠀",
      });
    }

    // 参数
    const params = {
      appId: options.config.appId,// 应用id
      prompt: userMessages,
      // 进阶配置
      request_id: 'jkec2024-knowledge-base',
      returnType: undefined,
      knowledge_ids: undefined,
      document_ids: undefined,
    };

    const controller = new AbortController();

    options.onController?.(controller);

    try {
      const userInfo = localStorage.getItem('userInfo');
      const token = userInfo ? JSON.parse(userInfo).token : "";
      const chatPath = this.apiPath;
      const paramsflag = { ...params }
      paramsflag.prompt.forEach(val => {
        val.content = btoa(unescape(encodeURIComponent(val.content)))
      });
      const chatPayload = {
        method: "POST",
        body: JSON.stringify(paramsflag),
        // body: btoa(unescape(encodeURIComponent(JSON.stringify(params)))),
        signal: controller.signal,
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + token,
          'clientid': 'e5cd7e4891bf95d1d19206ce24a7b32e'
        },
      };

      const requestTimeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);

      let responseText = "";
      let remainText = "";
      let finished = false;
      let finishData: any = {}; //保存后数据

      function animateResponseText() {
        if (finished || controller.signal.aborted) {
          responseText += remainText;
          if (responseText?.length === 0) {
            options.onError?.(new Error("请求已中止，请检查网络环境。"));
          }
          return;
        }

        if (remainText.length > 0) {
          const fetchCount = Math.max(1, Math.round(remainText.length / 60));
          const fetchText = remainText.slice(0, fetchCount);
          responseText += fetchText;
          remainText = remainText.slice(fetchCount);
          options.onUpdate?.(responseText, fetchText);
        }

        requestAnimationFrame(animateResponseText);
      }

      animateResponseText();

      const finish = () => {
        if (!finished) {
          finished = true;
          options.onFinish(responseText + remainText);
        }
      };

      controller.signal.onabort = finish;
      let sliceInfoPromise: Promise<void> | null = null;

      fetchEventSource(chatPath, {
        ...chatPayload,
        async onopen(res: any) {
          clearTimeout(requestTimeoutId);
          const contentType = res.headers.get("content-type");

          if (contentType?.startsWith("text/plain")) {
            responseText = await res.clone().text();
            return finish();
          }

          if (
            !res.ok ||
            !res.headers.get("content-type")?.startsWith(EventStreamContentType) ||
            res.status !== 200
          ) {
            const responseTexts = [responseText];
            let extraInfo = await res.clone().text();
            try {
              const resJson = await res.clone().json();
              extraInfo = prettyObject(resJson);
            } catch { }

            if (res.status === 401) {
              responseTexts.push(Locale.Error.Unauthorized);
            }

            if (extraInfo) {
              responseTexts.push(extraInfo);
            }

            responseText = responseTexts.join("\n\n");

            return finish();
          }
        },
        onmessage: async (msg) => {
          const info = JSON.parse(msg.data);
          if (info.event === 'finish') { // 完成
            const chatMode = useChatStore.getState().chatMode;
            if (info.data) {
              // console.log('info.data---', info.data);
              finishData = info && info?.data ? JSON.parse(info.data) : {};
            }
            // console.log('finishData', finishData);
            if (chatMode === 'LOCAL') {// 切片
              useChatStore.getState().updateCurrentSession((se) => {
                se.chat_id = info.id;
              });
              sliceInfoPromise = (async () => {
                try {
                  const res: any = await api.get(`deepseek/api/slice/search/${info.id}`);
                  let allChunkNum = 0;
                  delete res.data.code;
                  const values1 = Object.keys(res.data).reduce((acc, knowledge_id) => {
                    const docs = res.data[knowledge_id];
                    const transformedDocs = docs.map((doc: any) => {
                      allChunkNum += doc.chunk_nums;
                      return {
                        knowledge_id,
                        ...doc
                      }
                    });
                    return acc.concat(transformedDocs);
                  }, []);
                  const result = processSliceData(values1);
                  // 使用解构赋值，让结果更清晰
                  const { withDeprecated, withoutDeprecated } = result;
                  const sliceInfo = {
                    allChunkNum: allChunkNum,
                    ...res.data,
                    doc: values1,
                    docDeprecated:withDeprecated,
                    docActive:withoutDeprecated,
                  };
                  // console.log('values1---', values1,withDeprecated,withoutDeprecated);
                  // console.log('sliceInfo---', sliceInfo);
                  delete sliceInfo.code;
                  useChatStore.getState().updateCurrentSession((session) => {
                    session.messages = session.messages.map((item, index) => {
                      if (index === session.messages.length - 1 && item.role !== 'user') {
                        return {
                          ...item,
                          sliceInfo: sliceInfo,
                          delSliceInfo: withDeprecated ? sliceInfo : []
                        };
                      } else {
                        return {
                          ...item,
                        }
                      }
                    });
                  });
                } catch (error) {
                  console.error(error);
                }
              })();
            }
            return finish();
          }

          // 获取当前的数据
          const currentData = info.data;
          const formatStart = '```think';
          const formatEnd = 'think```';

          if (currentData?.startsWith(formatStart)) {
            remainText += currentData.replace(formatStart, '```think\n');
          } else if (currentData?.startsWith(formatEnd)) {
            remainText += currentData.replace(formatEnd, '```');
          } else {
            remainText += currentData;
          }
        },
        async onclose() {
          finish();
          if (sliceInfoPromise) {
            await sliceInfoPromise; // 等待 sliceInfo 加载完成
          }
          const session = useChatStore.getState().sessions[0];

          const item = session.messages.find(item => item.role === 'user');
          const dialogName = item ? item.content : '新的聊天';
          const data = {
            id: session.id,
            appId: session.appId,
            userId: undefined,
            dialogName: dialogName,
            messages: session.messages.map((item: any) => ({
              id: item.id,
              date: item.date,
              role: item.role,
              content: btoa(unescape(encodeURIComponent(item.content))),
              sliceInfo: item.sliceInfo,
              ...finishData
            })),
          };
          const messages = session.messages.slice();
          const backList = messages.reverse();
          const record = backList.find(item => item.content && item.role === 'assistant');
          if (record) {
            useChatStore.setState({
              message: {
                content: record.content as string,
                role: record.role,
              }
            });
          }
          const chatMode = useChatStore.getState().chatMode;
          // console.log('保存对话数据----', data);
          // if (chatMode === 'LOCAL') {
          await api.post('deepseek/api/dialog/save', data);
          // } else {
          //   await api.post('bigmodel/api/dialog/save', data);
          // }
        },
        onerror(e) {
          options.onError?.(e);
          throw e;
        },
        openWhenHidden: true,
      });
    } catch (e) {
      options.onError?.(e as Error);
    }
  }

  async usage() {
    return {
      used: 0,
      total: 0,
    };
  }

  async models(): Promise<LLMModel[]> {
    return [];
  }
}