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

import { useDemo } from "./app/useDemo";

type PanelName = "records" | "relationship" | "history";

const {
  appInfo,
  busy,
  error,
  lastSubmittedIntent,
  loading,
  pack,
  playerView,
  submitTurn,
  turnError
} = useDemo();
const draft = ref("");
const activePanel = ref<PanelName | null>(null);
const selectedHistoryNode = ref<string | null>(null);
const closeButton = ref<HTMLButtonElement | null>(null);

const sceneLabel = computed(() => {
  if (!playerView.value) return "载入场景";
  return `${playerView.value.sceneTitle} · ${pack.value?.displayName ?? ""}`;
});

const recentBeats = computed(() => playerView.value?.beats.slice(-5) ?? []);

const relationshipLabels = {
  affinity: "好感",
  trust: "信赖",
  hope: "希望",
  respect: "尊重",
  intimacy: "亲密",
  attachment: "依恋"
} as const;

const relationshipBandLabels = {
  distant: "疏远",
  guarded: "保留",
  warming: "渐暖",
  close: "亲近",
  bonded: "深厚"
} as const;

const certaintyLabels = {
  suspected: "推测",
  reported: "听闻",
  confirmed: "确认"
} as const;

const promiseStatusLabels = {
  proposed: "待回应",
  accepted: "已接受",
  fulfilled: "已履行",
  broken: "已背弃",
  released: "已解除",
  impossible: "无法完成"
} as const;

const placementLabels = {
  bag: "随身",
  worn: "穿戴",
  hand: "手持",
  scene: "场景中",
  hidden: "收起"
} as const;

function useSuggestion(suggestion: { draft: string }) {
  draft.value = suggestion.draft;
}

async function openPanel(panel: PanelName) {
  activePanel.value = activePanel.value === panel ? null : panel;
  if (activePanel.value) {
    await nextTick();
    closeButton.value?.focus();
  }
}

function closePanel() {
  activePanel.value = null;
}

async function sendDraft() {
  const input = draft.value.trim();
  if (!input || busy.value) return;

  draft.value = "";
  await submitTurn("speak_or_act", input);
}

async function continueStory() {
  if (busy.value || !playerView.value?.canContinue) return;
  await submitTurn("continue", "");
}

function handleEscape(event: KeyboardEvent) {
  if (event.key === "Escape" && activePanel.value) {
    closePanel();
  }
}

onMounted(() => window.addEventListener("keydown", handleEscape));
onBeforeUnmount(() => window.removeEventListener("keydown", handleEscape));
</script>

<template>
  <main class="app-shell">
    <header class="topbar">
      <div class="brand">
        <span class="brand-mark" aria-hidden="true">∞</span>
        <span>{{ appInfo?.name ?? "听娜娜讲故事" }}</span>
      </div>
      <div class="scene-label">{{ sceneLabel }}</div>
      <nav class="top-actions" aria-label="故事工具">
        <button
          type="button"
          aria-controls="records-panel"
          :aria-expanded="activePanel === 'records'"
          @click="openPanel('records')"
        >
          持有物
        </button>
        <button
          type="button"
          aria-controls="relationship-panel"
          :aria-expanded="activePanel === 'relationship'"
          @click="openPanel('relationship')"
        >
          关系
        </button>
        <button
          type="button"
          aria-controls="history-panel"
          :aria-expanded="activePanel === 'history'"
          @click="openPanel('history')"
        >
          回溯
        </button>
      </nav>
    </header>

    <section v-if="loading" class="state-screen">正在载入故事……</section>
    <section v-else-if="error" class="state-screen state-screen--error">
      <strong>内容载入失败</strong>
      <span>{{ error }}</span>
    </section>

    <section v-else-if="playerView" class="stage">
      <div class="stage-sky" />
      <div class="station-sign">旧青川站</div>
      <div class="character" aria-label="娜娜">
        <div class="character-hair" />
        <div class="character-face">
          <i class="eye eye--left" />
          <i class="eye eye--right" />
          <i class="mouth" />
        </div>
        <div class="character-coat" />
      </div>

      <div class="chapter-chip">第一幕 · 雨夜车站</div>

      <article class="dialogue-panel" aria-label="最近演出">
        <ol class="beat-list">
          <li v-for="beat in recentBeats" :key="beat.id" :class="`beat beat--${beat.kind}`">
            <strong v-if="beat.speaker">{{ beat.speaker }}</strong>
            <p>{{ beat.text }}</p>
          </li>
        </ol>
      </article>

      <div class="suggestions" aria-label="行动建议">
        <button
          v-for="suggestion in playerView.suggestions"
          :key="suggestion.id"
          type="button"
          :disabled="busy"
          @click="useSuggestion(suggestion)"
        >
          {{ suggestion.label }}
        </button>
      </div>

      <form class="composer" aria-label="玩家输入" @submit.prevent="sendDraft">
        <textarea
          v-model="draft"
          aria-label="自由输入"
          placeholder="说些什么，或者描述你的行动……"
          rows="2"
          :disabled="busy"
        />
        <button
          class="continue-button"
          type="button"
          :disabled="busy || !playerView.canContinue"
          @click="continueStory"
        >
          {{ busy && lastSubmittedIntent === "continue" ? "继续中…" : "继续" }}
        </button>
        <button class="send-button" type="submit" :disabled="busy || draft.trim().length === 0">
          {{ busy && lastSubmittedIntent === "speak_or_act" ? "发送中…" : "发送" }}
        </button>
      </form>

      <p class="turn-status" aria-live="polite">
        <span v-if="busy">故事正在回应，请稍候。</span>
        <span v-else-if="turnError">请求未完成：{{ turnError }}</span>
      </p>

      <footer class="statusline">
        <span>{{ playerView.nodeId }}</span>
        <span>{{ playerView.branchId }}</span>
        <span>关系与判定已隐藏</span>
      </footer>

      <div v-if="activePanel" class="panel-scrim" @click.self="closePanel">
        <aside
          :id="`${activePanel}-panel`"
          class="side-panel"
          role="dialog"
          aria-modal="true"
          :aria-labelledby="`${activePanel}-title`"
        >
          <header class="panel-header">
            <div>
              <span class="panel-eyebrow">当前故事</span>
              <h2 :id="`${activePanel}-title`">
                {{
                  activePanel === "records"
                    ? "随身记录"
                    : activePanel === "relationship"
                      ? `与${playerView.characterName}的关系`
                      : "故事回溯"
                }}
              </h2>
            </div>
            <button ref="closeButton" class="panel-close" type="button" aria-label="关闭面板" @click="closePanel">
              ×
            </button>
          </header>

          <div v-if="activePanel === 'records'" class="panel-content records-panel">
            <section aria-labelledby="inventory-title">
              <h3 id="inventory-title">持有物</h3>
              <ul v-if="playerView.inventory.length" class="card-list">
                <li v-for="item in playerView.inventory" :key="item.instanceId">
                  <div class="card-title">
                    <strong>{{ item.name }}</strong>
                    <span>{{ placementLabels[item.placement] }} · ×{{ item.quantity }}</span>
                  </div>
                  <p>{{ item.description }}</p>
                  <small>状态：{{ item.condition }}</small>
                </li>
              </ul>
              <p v-else class="empty-copy">目前没有随身持有物。</p>
            </section>

            <section aria-labelledby="knowledge-title">
              <h3 id="knowledge-title">已知线索</h3>
              <ul v-if="playerView.knowledge.length" class="card-list">
                <li v-for="record in playerView.knowledge" :key="record.id">
                  <div class="card-title">
                    <strong>{{ record.title }}</strong>
                    <span>{{ certaintyLabels[record.certainty] }}</span>
                  </div>
                  <p>{{ record.summary }}</p>
                </li>
              </ul>
              <p v-else class="empty-copy">还没有确认的线索。</p>
            </section>

            <section aria-labelledby="promises-title">
              <h3 id="promises-title">重要许诺</h3>
              <ul v-if="playerView.promises.length" class="card-list">
                <li v-for="promise in playerView.promises" :key="promise.id">
                  <div class="card-title">
                    <strong>{{ promise.content }}</strong>
                    <span>{{ promiseStatusLabels[promise.status] }}</span>
                  </div>
                  <small>{{ promise.weight === "major" ? "重要许诺" : "普通许诺" }}</small>
                </li>
              </ul>
              <p v-else class="empty-copy">你们之间还没有被接受的许诺。</p>
            </section>
          </div>

          <div v-else-if="activePanel === 'relationship'" class="panel-content relationship-panel">
            <p class="panel-intro">关系只呈现她此刻对你的大致感受，不显示精确数值。</p>
            <dl class="relationship-list">
              <div
                v-for="(label, key) in relationshipLabels"
                :key="key"
                class="relationship-row"
              >
                <dt>{{ label }}</dt>
                <dd :data-band="playerView.relationship[key]">
                  {{ relationshipBandLabels[playerView.relationship[key]] }}
                </dd>
              </div>
            </dl>
            <p class="panel-note">
              {{
                playerView.relationship.updatedAtNode
                  ? "最近在一个场景节点后发生了变化。"
                  : "当前场景尚未结算新的关系变化。"
              }}
            </p>
          </div>

          <div v-else class="panel-content history-panel">
            <p class="panel-intro">选择一个故事节点查看回溯入口。当前原型不会创建或保存新分支。</p>
            <ol class="history-list">
              <li v-for="node in playerView.history" :key="node.id">
                <button
                  type="button"
                  :class="{ selected: selectedHistoryNode === node.id }"
                  :aria-pressed="selectedHistoryNode === node.id"
                  @click="selectedHistoryNode = node.id"
                >
                  <span>{{ node.label }}</span>
                  <small>{{ node.isCurrent ? "当前节点" : "旧节点" }}</small>
                </button>
              </li>
            </ol>
            <div v-if="selectedHistoryNode" class="rewind-placeholder" aria-live="polite">
              <span>已选择：{{ selectedHistoryNode }}</span>
              <button type="button" disabled>从这里继续（尚未接入）</button>
              <small>这里只展示入口，不会更改当前线路。</small>
            </div>
          </div>
        </aside>
      </div>
    </section>
  </main>
</template>
