"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";

export class DeepSeekApi implements LLMApi {
  public apiPath: string;

  constructor() {
    this.apiPath = 'http://sse.deepseek.ryuiso.com:56780/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 = {
      model: 'deepseek-r1:8b',
      messages: userMessages,
      stream: true,
      // 进阶配置
      max_tokens: undefined,
      temperature: undefined,
    };

    const controller = new AbortController();

    options.onController?.(controller);

    try {
      const chatPath = this.apiPath;
      const chatPayload = {
        method: "POST",
        body: JSON.stringify(params),
        signal: controller.signal,
        headers: {
          'Content-Type': 'application/json',
        },
      };

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

      let responseText = "";
      let remainText = "";
      let finished = false;

      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;
          let text = responseText + remainText;
          options.onFinish(text);
        }
      };

      controller.signal.onabort = finish;

      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: (msg) => {
          const info = JSON.parse(msg.data);
          if (info.event === 'finish') {
            return finish();
          }
          // 获取当前的数据
          const currentData = info.data;
          const format = '```think' + '' + '```';
          if (responseText.startsWith(format)) {
            responseText = responseText.replace(format, '');
          }
          remainText += currentData;
        },
        async onclose() {
          finish();
          const session = useChatStore.getState().sessions[0];
          const data = {
            id: session.id,
            appId: session.appId,
            userId: undefined,
            dialogName: session.topic,
            messages: session.messages.map(item => ({
              id: item.id,
              date: item.date,
              role: item.role,
              content: item.content,
            })),
          };
          if (session.appId) {
            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 [];
  }
}