import { useXAgent, XStream } from "@ant-design/x";
import { useEffect, useRef, useState } from "react";
import { useSessionStorageState } from "ahooks";
import { GetSessionList, GetSessionMessageList } from "@/api/ai";
import { getDateGroupString } from "@/utils";

import type { ConversationsProps } from "@ant-design/x";
import type { ReactNode } from "react";

// 消息格式
type MessageItem = {
  id: string;
  content: string | ReactNode;
  role: "user" | "assistant" | "system";
  status: "loading" | "done" | "error" | "stop";
  loading?: boolean;
  footer?: ReactNode;
};

// 后端返回格式
type ResponseMessageItem = {
  answer: string;
  conversation_id: string;
  created_at: number;
  event: "message" | "message_end" | "message_error" | "ping";
  message_id: string;
  task_id: string;
};

type ChatParams = {
  // 应用名称
  app_name: string;
  // 会话内容
  chat_query: string;
  // 会话名称 第一次
  chat_name?: string;
  // 会话id 后续会话带入
  conversation_id?: string;
};

type ChatProps = {
  // 应用名称
  app_name: string;
  // 会话id 后续会话带入
  conversation_id?: string;
  // 成功获取会话内容
  onSuccess?: (data: ResponseMessageItem) => void;
  // 更新流式消息内容
  onUpdate: (data: ResponseMessageItem) => void;
  // 异常
  onError?: (error: Error) => void;
};

const defaultConversation = {
  // 会话id
  key: "1",
  label: "新的对话",
  group: '今日'
};

export function useChat({ app_name, onSuccess, onUpdate, onError }: ChatProps) {
  /**
   * 发送消息加载状态
   */
  const [loading, setLoading] = useState(false);

  /**
   * 加载会话记录列表
   */
  const [loadingSession, setLoadingSession] = useState(false);

  /**
   * 加载消息列表
   */
  const [loadingMessages, setLoadingMessages] = useState(false);

  // 用于停止对话
  const abortController = useRef<AbortController | null>(null);

  /**
   * 消息列表
   */
  const [messages, setMessages] = useState<Array<MessageItem>>([]);

  // 会话列表
  const [conversationList, setConversationList] = useState<
    ConversationsProps["items"]
  >([{ ...defaultConversation }]);

  // 活动对话
  const [activeConversation, setActiveConversation] = useState("1");

  // 当前智能体对象
  const [currentAgent, setCurrentAgent] = useSessionStorageState("agent-map");

  // 有更多对话
  const [hasMoreConversation, setHasMoreConversation] = useState(false);

  // 会话分页
  const [pageIndex, setPageIndex] = useState(1);

  const getSession = (page: number) => {
    setLoadingSession(true);
    GetSessionList({
      app_name,
      page_index: page,
    })
      .then((res) => {
        if(page === 1)  {
          setConversationList([
            { ...defaultConversation },
            ...(res?.result?.model || []).map((item: any) => ({
              ...item,
              key: item.sessionId,
              label: item.name,
              group: getDateGroupString(item.updateTime)
            })),
          ]);
        } else {
          setConversationList([
            ...(conversationList || []),
            ...(res?.result?.model || []).map((item: any) => ({
              ...item,
              key: item.sessionId,
              label: item.name,
              group: getDateGroupString(item.updateTime)
            })),
          ]);
        }
        setHasMoreConversation(res?.result.totalPages > page);
      })
      .finally(() => {
        setLoadingSession(false);
      });
  }

  // 切换app时获取会话记录
  useEffect(() => {
    setPageIndex(1);
    getSession(1);
  }, [app_name]);

  /**
   * 加载更多会话
   */
  const loadMoreConversation = () => {
    getSession(pageIndex + 1);
    setPageIndex(pageIndex + 1);
  };

  /**
   * 切换会话
   * @param key 会话id
   * @returns 
   */
  const changeConversation = async (key: string) => {
    setActiveConversation(key);
    if (key === "1") {
      setMessages([]);
      return;
    }
    cancel();
    setLoadingMessages(true);
    // 获取会话内容
    try {
      const res = await GetSessionMessageList({
        app_name,
        session_id: key,
        page_index: 1,
      });

      const list: MessageItem[] = [];
      (res?.result?.model || []).forEach((item: any) => {
        list.push(
          {
            id: item.id + "_query",
            content: item.query,
            role: "user",
            status: "done",
          },
          {
            id: item.id + "_query",
            content: item.answer,
            role: "assistant",
            status: "done",
          }
        );
      });
      setMessages(list);
    } finally {
      setLoadingMessages(false);
    }
  };

  /**
   * 封装智能体
   */
  const [agent] = useXAgent<ResponseMessageItem>({
    request: async (message, { onError, onSuccess, onUpdate }) => {
      abortController.current = new AbortController();
      const signal = abortController.current.signal;
      try {
        setLoading(true);
        const response = await fetch(
          "https://design.shalu.com/api/ai/chat-message",
          {
            method: "POST",
            body: JSON.stringify(message),
            headers: {
              Authorization: localStorage.getItem("token_a") || "",
              "Content-Type": "application/json",
            },
            signal,
          }
        );

        // 判断当前是否流式返回
        if(response.headers.get('content-type')?.includes('text/event-stream')) {
          if (response.body) {
            for await (const chunk of XStream({
              readableStream: response.body,
            })) {
              const data = JSON.parse(chunk.data);
              if (data?.event === "message") {
                onUpdate(data);
              } else if (data?.event === "message_end") {
                onSuccess(data);
              } else if (data?.event === "message_error") {
                onError(data);
              } else if (data?.event === "ping") {
                console.log(">>>> stream start <<<<");
              } else {
                console.log(">>>> stream error <<<<");
                onError(Error(data?.message || '请求失败'));
              }
            }
          }
        } else {
          // 接口异常处理
          response.json().then(res => {
            if(res.code === 0 ) {
              onError?.(Error(res?.error || '请求失败'));
              cancel();
            }
          });
        }
      } catch (error) {
        // 判断是不是 abort 错误
        if (signal.aborted) {
          return;
        }
        onError(error as Error);
      } finally {
        setLoading(false);
      }
    },
  });

  /**
   * 发起请求
   * @param chat_query 对话内容
   */
  const onRequest = (chat_query: string) => {
    activeConversation === '1' && setConversationList((list) => {
      return list?.map((item) => {
        return {
          ...item,
          label: item.key === "1" ? chat_query : item.label,
        };
      });
    });
    agent.request(
      {
        app_name,
        chat_query,
        chat_name: activeConversation === "1" ? chat_query : undefined,
        conversation_id:
          activeConversation === "1" ? undefined : activeConversation,
      },
      {
        onSuccess: (data) => {
          onSuccess?.(data);
        },
        onUpdate: (data) => {
          onUpdate(data);
          // 更新会话相关信息
          if (activeConversation === "1") {
            setConversationList((list) => {
              return list?.map((item) => {
                return {
                  ...item,
                  // 更新当前会话id
                  key: item.key === "1" ? data.conversation_id : item.key,
                };
              });
            });
            setActiveConversation(data.conversation_id);
          }
        },
        onError: (error) => {
          console.log("error", error);
          onError?.(error);
        },
      }
    );
  };

  /**
   * 停止对话
   */
  const cancel = () => {
    abortController.current?.abort();
    setLoading(false);
  };

  /**
   * 新增会话
   */
  const addConversation = () => {
    cancel();
    setMessages([]);
    setActiveConversation("1");
    // 还没产生对话时 直接清除当前对话
    if (!conversationList?.find((item) => item.key === "1")) {
      setConversationList([
        {
          ...defaultConversation,
        },
        ...(conversationList || []),
      ]);
    }
  };

  return {
    agent,
    loading,
    loadingMessages,
    loadingSession,
    cancel,
    messages,
    setMessages,
    conversationList,
    setConversationList,
    activeConversation,
    setActiveConversation,
    onRequest,
    addConversation,
    changeConversation,
    loadMoreConversation,
    hasMoreConversation
  };
}