import { computed, ref, type Ref } from 'vue';
import { ChatMessage } from '../model/Message';
import { ArrayUtils, EventEmitter, waitTimeOut } from '@imengyu/imengyu-utils';
import { ChatGroups } from '../core/Groups';
import AgentApi, { AgentChatHistory } from '@/api/agent/Agent';
import AgentChatFileApi from '@/api/agent/AgentChatFile';
import AgentWorkApi from '@/api/agent/AgentWorks';
import { confirm, toast } from '@/components/utils/DialogAction';

export interface UseChatSessionOptions {
  /**
   * 是否启用会话存储
   * @default true
   */
  enableSession: boolean;
  /**
   * 会话分组ID
   * @default ChatGroups.DEFAULT
   */
  groupId?: number;
  messages: Ref<ChatMessage[]>;
  /**
   * 停止聊天
   */
  onStop: () => void;
  onScrollToBottom: () => void;
}

export const CHAT_SESSION_NEW_ID = -1;
export const CHAT_SESSION_LOCAL_ID = -2;
const CHAT_SESSION_PAGE_SIZE = 20;

/**
 * 聊天会话管理
 * @param options - 选项
 * @returns 
 */
export function useChatSession(options: UseChatSessionOptions) {
  const {
    enableSession,
    groupId = ChatGroups.DEFAULT,
    messages,
    onStop,
    onScrollToBottom,
  } = options;

  const sessions = ref<AgentChatHistory[]>([]);
  const sessionsLoading = ref(false);
  const sessionsHasMore = ref(false);
  const sessionsPage = ref(1);

  const currentSessionId = ref<number>(CHAT_SESSION_NEW_ID);
  const currentGroupId = ref<number>(groupId);
  const currentSessionName = computed(() => {
    return sessions.value.find(s => s.id === currentSessionId.value)?.desc ?? '新会话';
  });
  const currentSession = computed<AgentChatHistory | null>(() =>
    sessions.value.find(s => s.id === currentSessionId.value) as AgentChatHistory | null ?? null,
  );

  const searchSession = ref('');

  const renameVisible = ref(false);
  const renameTitle = ref('');
  const renameTarget = ref<AgentChatHistory | null>(null);

  const events = new EventEmitter<{
    'session-loaded': (session: AgentChatHistory) => void;
    'session-newed': () => void;
    'pager-reset': () => void;
    'pager-init': (id: number) => Promise<void>;
  }>();

  async function loadSessions() {
    sessionsPage.value = 1;
    sessionsLoading.value = true;
    try {
      const rs = await AgentApi.getChatHistory(1, CHAT_SESSION_PAGE_SIZE, searchSession.value, currentGroupId.value);
      sessions.value = (rs.requireData().items ?? []) as AgentChatHistory[];
    } finally {
      sessionsLoading.value = false;
    }
  }
  async function loadMoreSessions() {
    sessionsPage.value++;
    sessionsLoading.value = true;
    try {
      const rs = (await AgentApi.getChatHistory(sessionsPage.value, CHAT_SESSION_PAGE_SIZE, searchSession.value, currentGroupId.value)).requireData();
      sessions.value = [...sessions.value, ...rs.items ?? []];
      sessionsHasMore.value = rs.allPage > sessionsPage.value;
    } finally {
      sessionsLoading.value = false;
    }
  }

  /**
   * 进入临时会话
   */
  function onSelectLocal() {
    onStop();
    currentSessionId.value = CHAT_SESSION_LOCAL_ID;
    events.emit('pager-reset');
    events.emit('session-newed');
    lateScrollToBottom();
  }
  /**
   * 进入新会话
   */
  function onSelectNew() {
    onStop();
    currentSessionId.value = CHAT_SESSION_NEW_ID;
    events.emit('pager-reset');
    events.emit('session-newed');
    lateScrollToBottom();
  }
  /**
   * 进入指定会话
   * @param id 会话ID
   */
  async function onSelectSession(id: number) {
    if (currentSessionId.value === id) {
      return;
    }
    onStop();
    currentSessionId.value = id;
    await events.emitAsync('pager-init', id);
    events.emit('session-loaded', sessions.value.find(s => s.id === id) as AgentChatHistory);
    lateScrollToBottom();
  }

  async function lateScrollToBottom() {
    await waitTimeOut(200);
    onScrollToBottom();
  }

  function onRenameSession(row: AgentChatHistory) {
    const hit = sessions.value.find(s => s.id === row.id);
    if (!hit) {
      return;
    }
    renameTarget.value = hit;
    renameTitle.value = hit.desc ?? '';
    renameVisible.value = true;
  }
  function onDeleteSession(row: AgentChatHistory) {
    const hit = sessions.value.find(s => s.id === row.id);
    if (!hit) {
      return;
    }
    confirm({
      title: '删除会话',
      content: `确定删除「${hit.desc || '未命名'}」吗？聊天记录将一并删除。`,
    }).then(async (result) => {
      if (result) {
        await AgentApi.deleteChatHistory(hit.id);
        await loadSessions();
        if (currentSessionId.value === hit.id) 
          onSelectNew();
      }
    });
  }
  function onDeleteMessage(id: number) {
    confirm({
      title: '删除消息',
      content: `确定删除该消息吗？`,
    }).then(async (result) => {
      if (result) {
        const hit = messages.value.find(m => m.id === id);
        if (!hit) 
          return;
        ArrayUtils.remove(messages.value, hit);
        await AgentApi.deleteChatHistoryItems(currentSessionId.value as number, [id]);
      }
    });
  }
  function onDeleteMessages(ids: number[]) {
    confirm({
      title: '删除消息',
      content: `确定删除选中的消息吗？`,
    }).then(async (result) => {
      if (result) {
        await AgentApi.deleteChatHistoryItems(currentSessionId.value as number, ids);
        messages.value = messages.value.filter(m => !ids.includes(m.id));
      }
    });
  }

  async function submitRename() {
    const row = renameTarget.value;
    if (!row) {
      return;
    }
    const title = renameTitle.value.trim();
    if (!title) {
      toast('请输入会话标题');
      return Promise.reject();
    }
    const payload = new AgentChatHistory().setSelfValues({
      id: row.id,
      userId: row.userId,
      desc: title,
    }) as AgentChatHistory;
    await AgentApi.updateChatHistory(row.id, payload);
    renameVisible.value = false;
    await loadSessions();
  }

  /**
   * 保存用户消息并持久化会话
   * @param userMessages 
   * @returns 
   */
  async function saveUserMessageAndPersistSession(userMessages: ChatMessage[]) {
    /**
     * 如果会话不可用或为临时会话，则不保存消息
     */
    if (!enableSession || currentSessionId.value === CHAT_SESSION_LOCAL_ID || userMessages.length === 0)
      return;

    if (currentSessionId.value <= 0) {
      const historyId = (await AgentApi.createChatHistory('新会话', currentGroupId.value)).requireData();

      await addChatHistoryItems(historyId);
      currentSessionId.value = historyId;
      await loadSessions();
      await events.emitAsync('pager-init', historyId);
      //移除未持久化的消息
      messages.value = messages.value.filter(m => m.isPersisted);

      //异步更新会话摘要
      AgentWorkApi.getQuestionOverview(userMessages.map(m => m.content).join('\n')).then(overview => {
        const session = sessions.value.find(s => s.id === historyId);
        if (session) {
          session.summary = overview;
          AgentApi.updateChatHistory(historyId, session as AgentChatHistory);
        }
      });

    } else {
      await addChatHistoryItems(currentSessionId.value);
    }

    async function persistMessages(historyId: number, messages: ChatMessage[]) {
      if (messages.length === 0)
        return;
      const historyItemIds = (await AgentApi.addOrUpdateChatHistoryItems(historyId, messages.map(m => m.toHistoryItem()))).requireData();
      for (let index = 0; index < messages.length; index++) {
        const m = messages[index];
        m.historyId = historyId;
        m.historyItemId = historyItemIds[index];
        m.id = historyItemIds[index];
        if (m.files && m.files.length > 0)
          await AgentChatFileApi.linkToHistoryItem(m.id, m.files[0].id);
      }
    }
    /**
     * 添加聊天记录项
     */
    async function addChatHistoryItems(historyId: number) {
      await persistMessages(historyId, [userMessages[0]]);
      if (userMessages.length > 1) {
        for (let i = 1; i < userMessages.length; i++) 
          userMessages[i].parentId = userMessages[0].id;
        await persistMessages(historyId, userMessages.slice(1));
      }
    }
  }
  /**
   * 持久化ai消息(必须有会话)
   * @param assistantMessages 
   */
  async function persistMessages(messages: ChatMessage[]) {
    try {
      if (!enableSession || currentSessionId.value < 0) 
        return;
      const historyItemIds = (await AgentApi.addOrUpdateChatHistoryItems(currentSessionId.value, messages.map(m => m.toHistoryItem()))).requireData();
      for (let index = 0; index < messages.length; index++) {
        const m = messages[index];
        m.historyId = currentSessionId.value;
        m.historyItemId = historyItemIds[index];
        m.id = historyItemIds[index];
      }
    } catch (error) {
      console.error(error);
      toast('保存聊天记录失败，请稍后重试');
    }
  }
  /**
   * 在请求流式响应之后持久化ai消息(必须有会话)，并且建立之前未创建会话时消息的回复关系
   * @param aiMessage 
   */
  async function persistAssistantAfterStream(aiMessage: ChatMessage, currentUserMessageIds: number[]) {
    try {
      if (!enableSession || currentSessionId.value < 0) 
        return;
      const messagesToPersist = [ aiMessage ];
      //设置已回复标记
      for (const id of currentUserMessageIds) {
        const message = messages.value.find(m => m.id === id);
        if (message) {
          message.replyItemId = aiMessage.id;
          messagesToPersist.push(message);
        }
      }
      await persistMessages(messagesToPersist);
    } catch (error) {
      console.error(error);
      toast('保存聊天记录失败，请稍后重试');
    }
  }
  /**
   * 更新会话
   * @param session 会话
   */
  async function updateSession(session: AgentChatHistory) {
    await AgentApi.updateChatHistory(session.id, session);
  }

  return {
    enableSession,
    searchSession,
    sessions,
    sessionsLoading,
    sessionsHasMore,
    currentSessionName,
    currentSessionId,
    currentSession,
    renameVisible,
    renameTitle,
    events,
    loadSessions,
    loadMoreSessions,
    onSelectLocal,
    onSelectNew,
    onSelectSession,
    onRenameSession,
    onDeleteMessage,
    onDeleteMessages,
    submitRename,
    onDeleteSession,
    saveUserMessageAndPersistSession,
    persistMessages,
    persistAssistantAfterStream,
    updateSession,
  };
}

export type ChatSessionManager = ReturnType<typeof useChatSession>;
