<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";

import { mentorApi, type Mentor, type MentorMessage, type MentorStreamEvent } from "../../shared/api/mentor";
import EmptyState from "../../shared/components/EmptyState.vue";
import { useMarketStore } from "../../shared/stores/market";
import { useSessionStore } from "../../shared/stores/session";
import { useUiStore } from "../../shared/stores/ui";
import MentorAnswer from "./MentorAnswer.vue";
import MentorLibrary from "./MentorLibrary.vue";

const session = useSessionStore();
const market = useMarketStore();
const ui = useUiStore();
const mentors = ref<Mentor[]>([]);
const tradeDate = ref("");
const selectedId = ref("");
const messages = ref<MentorMessage[]>([]);
const grade = ref<"all" | "A" | "B" | "C">("all");
const query = ref("");
const question = ref("");
const lastQuestion = ref("");
const loading = ref(false);
const historyLoading = ref(false);
const generating = ref(false);
const streamError = ref("");
const mobileLibrary = ref(false);
let controller: AbortController | null = null;

const locked = computed(() => !session.account?.smart_access);
const selected = computed(() => mentors.value.find((item) => item.id === selectedId.value));
const quickPrompts = computed(() => [
  "今天市场情绪处于什么位置？",
  "当前最值得关注的风险是什么？",
  "请按你的方法复盘今天的核心机会。",
  "如果明天出现分歧，应观察哪些确认信号？",
]);

async function load(): Promise<void> {
  loading.value = true;
  streamError.value = "";
  try {
    const setup = await mentorApi.setup(market.selectedDate);
    mentors.value = setup.mentors;
    tradeDate.value = setup.trade_date;
    if (!mentors.value.some((item) => item.id === selectedId.value)) {
      selectedId.value = mentors.value[0]?.id ?? "";
    }
    await loadMessages();
  } catch (error) {
    streamError.value = error instanceof Error ? error.message : "问师数据读取失败";
  } finally {
    loading.value = false;
  }
}

async function loadMessages(): Promise<void> {
  messages.value = [];
  if (locked.value || !selectedId.value || !tradeDate.value) return;
  historyLoading.value = true;
  try {
    messages.value = await mentorApi.messages(selectedId.value, tradeDate.value);
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "历史记录读取失败");
  } finally {
    historyLoading.value = false;
  }
}

async function selectMentor(mentor: Mentor): Promise<void> {
  if (generating.value) stop();
  selectedId.value = mentor.id;
  mobileLibrary.value = false;
  streamError.value = "";
  await loadMessages();
}

async function savePreferences(): Promise<void> {
  try {
    await mentorApi.preferences(
      mentors.value.map((item) => item.id),
      mentors.value.filter((item) => item.pinned).map((item) => item.id),
    );
  } catch (error) {
    ui.showToast(error instanceof Error ? error.message : "排序保存失败");
    await load();
  }
}

async function pin(mentor: Mentor): Promise<void> {
  mentor.pinned = !mentor.pinned;
  mentors.value.sort((left, right) => Number(right.pinned) - Number(left.pinned));
  await savePreferences();
}

async function move(mentor: Mentor, delta: number): Promise<void> {
  const current = mentors.value.findIndex((item) => item.id === mentor.id);
  const target = current + delta;
  if (current < 0 || target < 0 || target >= mentors.value.length) return;
  const [item] = mentors.value.splice(current, 1);
  if (!item) return;
  mentors.value.splice(target, 0, item);
  mentors.value = [...mentors.value];
  await savePreferences();
}

async function reorder(sourceId: string, targetId: string): Promise<void> {
  if (!sourceId || sourceId === targetId) return;
  const source = mentors.value.findIndex((item) => item.id === sourceId);
  const target = mentors.value.findIndex((item) => item.id === targetId);
  if (source < 0 || target < 0) return;
  const [item] = mentors.value.splice(source, 1);
  if (!item) return;
  mentors.value.splice(target, 0, item);
  mentors.value.sort((left, right) => Number(right.pinned) - Number(left.pinned));
  mentors.value = [...mentors.value];
  await savePreferences();
}

async function send(value = question.value): Promise<void> {
  const normalized = value.trim();
  if (!normalized || !selected.value || generating.value || locked.value) return;
  question.value = "";
  lastQuestion.value = normalized;
  streamError.value = "";
  messages.value.push({ role: "user", content: normalized, status: "complete" });
  const answer: MentorMessage = { role: "assistant", content: "", status: "complete" };
  messages.value.push(answer);
  generating.value = true;
  controller = new AbortController();
  try {
    await mentorApi.chat(
      selected.value.id,
      tradeDate.value,
      normalized,
      (event: MentorStreamEvent) => {
        if (event.type === "delta") answer.content += event.content ?? "";
        if (event.type === "error") {
          answer.status = "error";
          streamError.value = event.message ?? "回答生成失败";
        }
      },
      controller.signal,
    );
  } catch (error) {
    if (error instanceof DOMException && error.name === "AbortError") {
      answer.status = "stopped";
    } else {
      answer.status = "error";
      streamError.value = error instanceof Error ? error.message : "回答生成失败";
    }
  } finally {
    generating.value = false;
    controller = null;
    if (!answer.content && answer.status !== "complete") messages.value.pop();
  }
}

function stop(): void {
  controller?.abort();
}

async function clearHistory(): Promise<void> {
  if (!selected.value || !messages.value.length) return;
  const confirmed = await ui.askConfirmation({
    title: "清空当前对话",
    message: `仅清空 ${selected.value.name} 在 ${tradeDate.value} 的对话记录，其他模型和日期不受影响。`,
    confirmLabel: "清空",
  });
  if (!confirmed) return;
  await mentorApi.clear(selected.value.id, tradeDate.value);
  messages.value = [];
  ui.showToast("当前对话已清空");
}

function keydown(event: KeyboardEvent): void {
  if (event.key === "Enter" && !event.shiftKey) {
    event.preventDefault();
    void send();
  }
}

onMounted(load);
onBeforeUnmount(stop);
watch(() => market.selectedDate, load);
</script>

<template>
  <main class="page-frame mentor-page">
    <header class="page-header mentor-page-header">
      <div><h1>问师</h1><p class="page-subtitle">公开资料蒸馏的思维模型 · 数据日期 {{ tradeDate || market.selectedDate }}</p></div>
      <button class="btn mentor-mobile-directory" type="button" @click="mobileLibrary = !mobileLibrary">模型库</button>
    </header>
    <div v-if="locked" class="notice notice-warning membership-lock">
      <span><strong>问师仅对会员开放</strong>，开通会员后可使用思维模型复盘对话。</span>
      <button class="btn btn-small" type="button" @click="ui.openDialog('membership')">查看会员状态</button>
    </div>
    <div v-if="loading" class="card workspace-state">正在读取思维模型</div>
    <EmptyState v-else-if="streamError && !mentors.length" class="card" title="问师暂不可用" :description="streamError" />
    <section v-else class="mentor-workspace" :class="{ 'locked-content': locked, 'show-library': mobileLibrary }">
      <MentorLibrary v-model:grade="grade" v-model:query="query" :mentors="mentors" :selected-id="selectedId" :disabled="locked" @select="selectMentor" @pin="pin" @move="move" @reorder="reorder" />
      <article class="card mentor-chat">
        <header v-if="selected" class="mentor-chat-header">
          <div class="mentor-identity"><strong>{{ selected.name }}</strong><span class="tag" :class="`mentor-grade-${selected.grade.toLowerCase()}`">{{ selected.grade }}</span><span>{{ selected.description }}</span></div>
          <button class="btn btn-small" type="button" :disabled="!messages.length || generating" @click="clearHistory">清空</button>
        </header>
        <div class="mentor-messages" aria-live="polite">
          <p v-if="historyLoading" class="mentor-chat-empty">正在读取当前对话</p>
          <div v-else-if="!messages.length" class="mentor-welcome">
            <strong>{{ selected?.tagline || '从问题出发，按模型的方法拆解市场。' }}</strong>
            <p>回答基于公开资料蒸馏，不是真人本人，不构成投资建议。</p>
            <div class="mentor-prompts"><button v-for="prompt in quickPrompts" :key="prompt" class="btn" type="button" @click="send(prompt)">{{ prompt }}</button></div>
          </div>
          <div v-for="(message, index) in messages" :key="message.id ?? index" class="mentor-message" :class="`mentor-message-${message.role}`">
            <span class="mentor-role">{{ message.role === 'user' ? '我' : selected?.name }}</span>
            <MentorAnswer v-if="message.role === 'assistant'" :content="message.content || (generating && index === messages.length - 1 ? '正在思考…' : '')" />
            <p v-else>{{ message.content }}</p>
            <small v-if="message.status === 'stopped'">已停止生成</small>
            <small v-else-if="message.status === 'error'">回答未完整生成</small>
          </div>
        </div>
        <footer class="mentor-composer">
          <div v-if="streamError" class="mentor-stream-error"><span>{{ streamError }}</span><button v-if="lastQuestion && !generating" class="btn btn-small" type="button" @click="send(lastQuestion)">重试</button></div>
          <textarea v-model="question" class="textarea" rows="2" maxlength="2000" placeholder="输入你的复盘问题" :disabled="locked || generating || !selected" @keydown="keydown" />
          <div class="mentor-composer-actions"><span class="muted">Enter 发送 · Shift+Enter 换行</span><button v-if="generating" class="btn" type="button" @click="stop">停止</button><button v-else class="btn btn-primary" type="button" :disabled="!question.trim() || locked" @click="send()">发送</button></div>
        </footer>
      </article>
    </section>
  </main>
</template>
