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

import { heavenApi, type HeavenReading, type HeavenStreamEvent } from "../../shared/api/heaven";
import BaseDialog from "../../shared/components/BaseDialog.vue";

const props = defineProps<{ reading: HeavenReading; history: HeavenReading[] }>();
const emit = defineEmits<{ close: []; completed: [reading: HeavenReading] }>();
const tab = ref<"current" | "history">("current");
const active = ref(props.reading);
const answer = ref(props.reading.interpretation || "");
const loading = ref(!props.reading.interpretation);
const error = ref("");
const canvas = ref<HTMLCanvasElement | null>(null);
let animation: any = null;
let controller: AbortController | null = null;
const title = computed(() => ({ trend: "解势", fortune: "解运", heart: "解卦" })[active.value.mode]);
const modeHistory = computed(() => props.history.filter((item) => item.mode === active.value.mode));

async function run(): Promise<void> {
  if (active.value.interpretation) {
    answer.value = active.value.interpretation;
    loading.value = false;
    return;
  }
  answer.value = "";
  error.value = "";
  loading.value = true;
  await nextTick();
  startAnimation();
  controller = new AbortController();
  try {
    await heavenApi.interpret(
      active.value.id,
      (event: HeavenStreamEvent) => {
        if (event.type === "delta") answer.value += event.content ?? "";
        if (event.type === "error") error.value = event.message ?? "智能解读未完成";
      },
      controller.signal,
    );
    await animation?.complete?.();
    active.value = { ...active.value, interpretation: answer.value, status: error.value ? "error" : "complete" };
    emit("completed", active.value);
  } catch (reason) {
    if (!(reason instanceof DOMException && reason.name === "AbortError")) {
      error.value = reason instanceof Error ? reason.message : "智能解读服务暂不可用";
    }
  } finally {
    loading.value = false;
    animation?.stop?.();
    controller = null;
  }
}

function startAnimation(): void {
  if (!canvas.value || !window.HeavenLoadingCanvas) return;
  animation = new window.HeavenLoadingCanvas(canvas.value);
  const result = active.value.result;
  animation.start(active.value.mode === "fortune" ? "fortune" : "hexagram", {
    yearPillar: result.pillars?.year ?? "",
    movement: result.movement?.element ? `${result.movement.element}运${result.movement.tendency}` : "",
    sixQi: {
      sitian: result.six_qi?.sitian ?? "",
      zaiquan: result.six_qi?.zaiquan ?? "",
      step: result.six_qi?.step ?? 1,
    },
  });
}

function selectHistory(reading: HeavenReading): void {
  controller?.abort();
  animation?.stop?.();
  active.value = reading;
  tab.value = "current";
  void run();
}

function close(): void {
  controller?.abort();
  animation?.stop?.();
  emit("close");
}

onMounted(run);
onBeforeUnmount(() => {
  controller?.abort();
  animation?.stop?.();
});
watch(() => props.reading, (value) => { active.value = value; void run(); });
</script>

<template>
  <BaseDialog :title="title" wide :close-on-backdrop="!loading" @close="close">
    <div class="heaven-dialog-tabs"><button type="button" :class="{ active: tab === 'current' }" @click="tab = 'current'">本次解读</button><button type="button" :class="{ active: tab === 'history' }" @click="tab = 'history'">历史记录</button></div>
    <div v-if="tab === 'history'" class="heaven-history-list">
      <button v-for="item in modeHistory" :key="item.id" type="button" @click="selectHistory(item)"><strong>{{ item.date }} · {{ item.result.stock?.name || item.result.hexagram?.name || item.result.phrase || title }}</strong><span>{{ item.status === 'complete' ? '已完成' : '未完成' }}</span></button>
      <p v-if="!modeHistory.length" class="muted">暂无历史记录</p>
    </div>
    <div v-else class="heaven-dialog-current">
      <div v-if="loading" class="heaven-loading-stage"><canvas ref="canvas" /><p>{{ active.mode === 'fortune' ? '气机渐次归位' : '阴阳渐次成象' }}</p></div>
      <div v-else class="heaven-interpretation"><p v-if="error" class="notice notice-warning">{{ error }}</p><div class="heaven-answer">{{ answer || '本次解读未生成完整内容。' }}</div></div>
    </div>
  </BaseDialog>
</template>
