<script setup lang="ts">
import { nextTick, onMounted, ref } from "vue";
import ChatComposer from "./components/ChatComposer.vue";
import ChatMessage from "./components/ChatMessage.vue";
import LoginPanel from "./components/LoginPanel.vue";
import SessionDrawer from "./components/SessionDrawer.vue";
import { api, clearToken, getToken, streamChat } from "./services/api";
import type { ChatMessage as ApiMessage, ChatSession, UserProfile } from "./types/api";

interface UiMessage {
  id: string;
  role: "user" | "assistant";
  content: string;
  streaming?: boolean;
}

const user = ref<UserProfile | null>(null);
const sessions = ref<ChatSession[]>([]);
const activeSessionId = ref<number | null>(null);
const messages = ref<UiMessage[]>([]);
const drawerOpen = ref(false);
const loading = ref(false);
const booting = ref(true);
const statusText = ref("连接后端中");
const bottomRef = ref<HTMLElement | null>(null);
const activeAbortController = ref<AbortController | null>(null);

onMounted(async () => {
  if (!getToken()) {
    booting.value = false;
    statusText.value = "请先登录";
    return;
  }
  try {
    user.value = await api.profile();
    await loadSessions();
    statusText.value = "已连接大本营答疑服务";
  } catch {
    clearToken();
    statusText.value = "登录已失效";
  } finally {
    booting.value = false;
  }
});

async function onLoggedIn(profile: UserProfile) {
  user.value = profile;
  statusText.value = "已连接大本营答疑服务";
  await loadSessions();
}

async function loadSessions() {
  sessions.value = await api.listSessions();
  if (sessions.value.length === 0) {
    await createSession();
    return;
  }
  await selectSession(sessions.value[0].id);
}

async function createSession() {
  const result = await api.createSession();
  await refreshSessions(result.sessionId);
  drawerOpen.value = false;
}

async function refreshSessions(selectId = activeSessionId.value) {
  sessions.value = await api.listSessions();
  if (selectId) await selectSession(selectId);
}

async function selectSession(sessionId: number) {
  activeSessionId.value = sessionId;
  const history = await api.history(sessionId);
  messages.value = history.map(toUiMessage);
  drawerOpen.value = false;
  await scrollToBottom();
}

async function send(message: string) {
  if (!activeSessionId.value || loading.value) return;
  const userMessage: UiMessage = { id: `user-${Date.now()}`, role: "user", content: message };
  const assistantMessage: UiMessage = { id: `assistant-${Date.now()}`, role: "assistant", content: "", streaming: true };
  messages.value.push(userMessage, assistantMessage);
  loading.value = true;
  activeAbortController.value = new AbortController();
  let hasContent = false;
  await scrollToBottom();
  try {
    await streamChat(
      activeSessionId.value,
      message,
      async (chunk) => {
        if (!hasContent) {
          assistantMessage.content = "";
          hasContent = true;
        }
        assistantMessage.content += chunk;
        await scrollToBottom();
      },
      async (statusMessage, statusType) => {
        if (statusType === "queued") {
          assistantMessage.content = statusMessage || "当前请求较多，正在排队中。";
        } else if (statusType === "generating" && !hasContent) {
          assistantMessage.content = "";
        }
        await scrollToBottom();
      },
      activeAbortController.value.signal,
    );
    assistantMessage.streaming = false;
    await refreshSessions(activeSessionId.value);
    user.value = await api.profile();
  } catch (error) {
    assistantMessage.streaming = false;
    if (error instanceof DOMException && error.name === "AbortError") {
      assistantMessage.content = assistantMessage.content || "已停止生成";
    } else {
      assistantMessage.content = error instanceof Error ? error.message : "AI 回复失败";
    }
  } finally {
    loading.value = false;
    activeAbortController.value = null;
  }
}

async function stop() {
  if (!activeSessionId.value) return;
  activeAbortController.value?.abort();
  await api.stop(activeSessionId.value);
  loading.value = false;
}

async function renameSession(sessionId: number, title: string) {
  await api.renameSession(sessionId, title);
  await refreshSessions(sessionId);
}

async function deleteSession(sessionId: number) {
  await api.deleteSession(sessionId);
  sessions.value = await api.listSessions();
  if (activeSessionId.value === sessionId) {
    messages.value = [];
    activeSessionId.value = null;
    if (sessions.value.length > 0) {
      await selectSession(sessions.value[0].id);
    }
  }
}

async function logout() {
  try {
    await api.logout();
  } finally {
    clearToken();
    user.value = null;
    sessions.value = [];
    messages.value = [];
    activeSessionId.value = null;
    statusText.value = "请先登录";
  }
}

function toUiMessage(message: ApiMessage): UiMessage {
  return {
    id: String(message.id),
    role: message.role,
    content: message.content,
    streaming: message.message_status === "GENERATING",
  };
}

async function scrollToBottom() {
  await nextTick();
  bottomRef.value?.scrollIntoView({ behavior: "smooth", block: "end" });
}
</script>

<template>
  <main class="app-shell">
    <section class="phone-frame">
      <div v-if="booting" class="booting">正在启动...</div>
      <LoginPanel v-else-if="!user" @logged-in="onLoggedIn" />
      <template v-else>
        <header class="topbar">
          <button type="button" class="icon-btn" @click="drawerOpen = true">☰</button>
          <div>
            <h1>大本营答疑助手</h1>
            <p>{{ statusText }}</p>
          </div>
          <button type="button" class="plain-btn" @click="logout">退出</button>
        </header>

        <section class="quota-strip">
          <span>{{ user.name }}</span>
          <strong>{{ user.todayUsed }}/{{ user.dailyLimit }}</strong>
        </section>

        <section class="chat-area">
          <div v-if="messages.length === 0" class="empty-state">
            <strong>可以开始提问了</strong>
            <p>输入问题，我会尽力为你解答。</p>
          </div>
          <ChatMessage
            v-for="message in messages"
            :key="message.id"
            :role="message.role"
            :content="message.content"
            :streaming="message.streaming"
          />
          <div ref="bottomRef"></div>
        </section>

        <ChatComposer :loading="loading" :disabled="!activeSessionId" @send="send" @stop="stop" />
        <SessionDrawer
          :open="drawerOpen"
          :sessions="sessions"
          :active-session-id="activeSessionId"
          @close="drawerOpen = false"
          @select="selectSession"
          @create="createSession"
          @rename="renameSession"
          @delete="deleteSession"
        />
      </template>
    </section>
  </main>
</template>
