<template>
  <main class="chat-main" :class="{ 'wide-mode': isWideMode }">
    <!-- 头部 -->
    <ChatHeader
      :title="currentConversation?.title || '新对话'"
      :message-count="messages.length"
      :show-sidebar-toggle="sidebarCollapsed"
      :is-wide-mode="isWideMode"
      :is-pinned="currentConversation?.pinned"
      @toggle-sidebar="$emit('toggle-sidebar')"
      @toggle-wide-mode="toggleWideMode"
      @clear="handleClear"
      @export="handleExport"
      @pin="handlePin"
    />

    <!-- 消息列表 -->
    <MessageList
      ref="messageListRef"
      :messages="messages"
      :show-timestamp="settings.showTimestamp"
      :compact="settings.compactMode"
      :is-typing="isTyping"
      @retry="handleRetry"
      @regenerate="handleRegenerate"
      @select-suggestion="handleSuggestion"
    />

    <!-- 输入区域 -->
    <div class="input-wrapper">
      <div class="input-container" :class="{ wide: isWideMode }">
        <ChatInput
          ref="chatInputRef"
          :placeholder="inputPlaceholder"
          :is-streaming="isStreaming"
          :send-on-enter="settings.sendOnEnter"
          :disabled="false"
          @send="handleSend"
          @stop="handleStop"
        />
      </div>
    </div>
  </main>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from "vue";
import { storeToRefs } from "pinia";
import { useChatStore } from "@/stores/chat";
import { useSettingsStore } from "@/stores/settings";
import ChatHeader from "./ChatHeader.vue";
import MessageList from "./MessageList.vue";
import ChatInput from "@/components/input/ChatInput.vue";
import { MessageType, MessageRole } from "@/types/chat";
import type { Attachment } from "@/types/chat";
import { chatApi } from "@/services/api";

defineEmits<{
  "toggle-sidebar": [];
}>();

const chatStore = useChatStore();
const settingsStore = useSettingsStore();

const { currentConversation, isStreaming } = storeToRefs(chatStore);
const { settings, sidebarCollapsed } = storeToRefs(settingsStore);

const messageListRef = ref<InstanceType<typeof MessageList> | null>(null);
const chatInputRef = ref<InstanceType<typeof ChatInput> | null>(null);
const isWideMode = ref(true);
const isTyping = ref(false);
const currentStreamingMessageId = ref<string | null>(null);
const abortController: any = ref<AbortController | null>(null);

const messages: any = computed(() => currentConversation.value?.messages || []);

const inputPlaceholder = computed(() => {
  if (isStreaming.value) return "正在生成回复...";
  return "输入你的问题，按 Ctrl+Enter 发送";
});

function toggleWideMode() {
  isWideMode.value = !isWideMode.value;
}

function handleClear() {
  if (currentConversation.value) {
    chatStore.clearConversation(currentConversation.value.id);
  }
}

function handleExport() {
  if (!currentConversation.value) return;

  const data = {
    title: currentConversation.value.title,
    messages: currentConversation.value.messages,
    exportedAt: new Date().toISOString(),
  };

  const blob = new Blob([JSON.stringify(data, null, 2)], {
    type: "application/json",
  });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `${currentConversation.value.title}.json`;
  a.click();
  URL.revokeObjectURL(url);
}

function handlePin() {
  if (currentConversation.value) {
    chatStore.togglePinConversation(currentConversation.value.id);
  }
}

// 发送消息 - 使用真实 API
async function handleSend(text: string, attachments: Attachment[]) {
  // 如果没有当前对话，创建新对话
  if (!currentConversation.value) {
    chatStore.createConversation();
  }

  // 添加用户消息
  chatStore.addMessage(MessageRole.USER, {
    type: MessageType.TEXT,
    text,
    images: attachments.filter((a) => a.type === "image"),
    files: attachments.filter((a) => a.type === "file"),
  });

  // 添加 AI 消息占位符
  const aiMessage = chatStore.addMessage(MessageRole.ASSISTANT, {
    type: MessageType.TEXT,
    text: "",
  });

  currentStreamingMessageId.value = aiMessage.id;
  chatStore.updateMessage(aiMessage.id, { isStreaming: true });
  chatStore.startStreaming();
  isTyping.value = true;

  // 创建 AbortController
  abortController.value = new AbortController();
  try {
    const stream = chatApi.streamChat(
      {
        message: text,
        conversationId: currentConversation.value?.id || "",
        model: settings.value.defaultModel,
        stream: true,
      },
      abortController.value.signal,
    );

    let fullText = "";
    isTyping.value = false;

    for await (const chunk of stream) {
      if (abortController.value?.signal.aborted) break;
      fullText += chunk;
      chatStore.updateMessageContent(aiMessage.id, fullText);
    }

    if (!abortController.value?.signal.aborted) {
      chatStore.updateMessage(aiMessage.id, {
        isStreaming: false,
        content: {
          type: MessageType.TEXT,
          text: fullText,
        },
      });
    }
  } catch (error: any) {
    if (error.name !== "AbortError") {
      chatStore.updateMessage(aiMessage.id, {
        isStreaming: false,
        isError: true,
        errorMessage: error.message || "请求失败",
      });
    }
  } finally {
    chatStore.stopStreaming();
    currentStreamingMessageId.value = null;
  }
}

// 停止生成
function handleStop() {
  if (abortController.value) {
    abortController.value.abort();
    abortController.value = null;
  }

  chatStore.stopStreaming();
  chatApi.stopChat(messages.value.at(-1)["messageId"]);
  if (currentStreamingMessageId.value) {
    chatStore.updateMessage(currentStreamingMessageId.value, {
      isStreaming: false,
    });
    currentStreamingMessageId.value = null;
  }
}

// 重试
async function handleRetry(messageId: string) {
  const message = messages.value.find((m: any) => m.id === messageId);
  if (!message || message.role !== MessageRole.ASSISTANT) return;

  const messageIndex = messages.value.findIndex((m: any) => m.id === messageId);
  if (messageIndex <= 0) return;

  const userMessage = messages.value[messageIndex - 1];
  if (userMessage.role !== MessageRole.USER) return;

  // 重置消息状态
  chatStore.updateMessage(messageId, {
    isError: false,
    errorMessage: undefined,
    isStreaming: true,
    isEnd: true,
    content: { type: MessageType.TEXT, text: "" },
  });

  currentStreamingMessageId.value = messageId;
  chatStore.startStreaming();
  abortController.value = new AbortController();

  try {
    const stream = chatApi.streamChat(
      {
        message: userMessage.content.text || "",
        conversationId: currentConversation.value?.id,
        model: settings.value.defaultModel,
        stream: true,
      },
      abortController.value.signal,
    );

    let fullText = "";

    for await (const chunk of stream) {
      if (abortController.value?.signal.aborted) break;
      fullText += chunk;
      chatStore.updateMessageContent(messageId, fullText);
    }

    if (!abortController.value?.signal.aborted) {
      chatStore.updateMessage(messageId, {
        isStreaming: false,
        content: {
          type: MessageType.TEXT,
          text: fullText,
        },
      });
    }
  } catch (error: any) {
    if (error.name !== "AbortError") {
      chatStore.updateMessage(messageId, {
        isStreaming: false,
        isError: true,
        errorMessage: error.message || "请求失败",
      });
    }
  } finally {
    chatStore.stopStreaming();
    currentStreamingMessageId.value = null;
  }
}

function handleRegenerate(messageId: string) {
  handleRetry(messageId);
}

function handleSuggestion(text: string) {
  handleSend(text, []);
}

function focusInput() {
  chatInputRef.value?.focus();
}

defineExpose({
  focusInput,
  messageListRef,
});

watch(
  () => currentConversation.value?.id,
  () => {
    nextTick(() => {
      focusInput();
    });
  },
);
</script>

<style lang="scss" scoped>
.chat-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  height: 100vh;
  background: #ffffff;
  overflow: hidden;

  .dark & {
    background: #11111b;
  }

  &.wide-mode {
    .input-container {
      max-width: 1000px;
    }
  }
}

.input-wrapper {
  flex-shrink: 0;
  padding: 16px 24px 24px;
  background: linear-gradient(to top, white 80%, transparent);

  .dark & {
    background: linear-gradient(to top, #11111b 80%, transparent);
  }
}

.input-container {
  max-width: 800px;
  margin: 0 auto;
  transition: max-width 0.3s ease;

  &.wide {
    max-width: 1000px;
  }
}
</style>
