<template>
  <main class="chat-area">
    <div class="chat-header" :class="{ disconnected: store.connectionStatus === 'disconnected' }">
      <span class="chat-header-title">空海医院医疗助手 · Web Demo · 门诊大厅 · 联调演示</span>
      <span class="chat-header-status">
        <span :class="store.connectionStatus === 'disconnected' ? 'status-dot-err' : 'status-dot'" />
        {{ store.connectionStatus === 'disconnected' ? '连接异常' : '在线' }}
      </span>
    </div>

    <div class="chat-messages" ref="messagesEl">
      <!-- Disconnected overlay -->
      <div v-if="store.connectionStatus === 'disconnected'" class="disconnected-overlay">
        <div class="disc-icon">
          <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
            <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
            <line x1="12" y1="9" x2="12" y2="13" />
            <line x1="12" y1="17" x2="12.01" y2="17" />
          </svg>
        </div>
        <p class="disc-title">连接异常</p>
        <p class="disc-desc">请检查网络连接或联系现场工作人员。</p>
        <div class="disc-btns">
          <button class="btn-accent">重新连接</button>
          <button class="btn-outline">联系工作人员</button>
        </div>
      </div>

      <!-- Empty state -->
      <div v-else-if="store.messages.length === 0 && !store.sending" class="chat-empty">
        <div class="chat-empty-icon">
          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
            <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
          </svg>
        </div>
        <p class="chat-empty-text">您好，我是门诊助手</p>
        <p class="chat-empty-hint">请说出您的就诊需求，例如：我头疼三天，想挂号</p>
      </div>

      <!-- Unified timeline: messages + cards interleaved by time -->
      <template v-for="item in timeline" :key="item.key">
        <div v-if="item.type === 'message'" :class="['msg', item.data._type === 'success' ? 'msg-success' : item.data.role === 'user' ? 'msg-user' : 'msg-ai']">
          {{ item.data.content }}
          <span v-if="item.data.timestamp" class="msg-time">{{ item.data.timestamp }}</span>
        </div>
        <div
          v-else
          :class="['chat-card', { active: isPreviewActive(item.data.id) }]"
          @click="store.viewCard(isPreviewActive(item.data.id) ? null : item.data.id)"
        >
          <div class="cc-title">{{ item.data.title }}</div>
          <div class="cc-choice">{{ item.data.subtitle }}</div>
          <span class="msg-time">{{ item.data.timestamp }}</span>
        </div>
      </template>

      <!-- Thinking bubble: shown while waiting for AI to start responding -->
      <div v-if="isThinking" class="msg msg-ai thinking-bubble">
        <span class="wave-char" v-for="(c, i) in '思考中...'" :key="i" :style="{ animationDelay: i * 0.2 + 's' }">{{ c }}</span>
      </div>

    </div>

    <ChatInput :disabled="store.sending" @submit="handleSubmit" />
  </main>
</template>

<script setup lang="ts">
import { watch, ref, nextTick, computed } from 'vue';
import ChatInput from './ChatInput.vue';
import { useTerminalStore } from '../state/terminalStore';

const store = useTerminalStore();
const messagesEl = ref<HTMLElement | null>(null);

interface TimelineItem {
  type: 'message' | 'card';
  key: string;
  data: any;
  _order: number;
}

const timeline = computed<TimelineItem[]>(() => {
  const items: TimelineItem[] = [];
  for (const msg of store.messages) {
    if (msg.role !== 'system') {
      items.push({ type: 'message', key: msg.id, data: msg, _order: 0 });
    }
  }
  for (const preview of store.cardPreviews) {
    items.push({ type: 'card', key: preview.id, data: preview, _order: 0 });
  }
  items.sort((a, b) => (a.data._seq || 0) - (b.data._seq || 0));
  return items;
});

const isThinking = computed(() => {
  if (!store.sending || !store.streaming) return false;
  const last = store.messages[store.messages.length - 1];
  return !last || last.role === 'user' || (last.role === 'assistant' && last.streaming && !last.content);
});

function isPreviewActive(previewId: string): boolean {
  // Active when viewing a historical card, or when this is the latest card and not viewing history
  if (store.viewingCardId) {
    return store.viewingCardId === previewId;
  }
  return store.activeCard?.cardInstanceId === previewId;
}

async function handleSubmit(text: string) {
  try {
    await store.sendMessage(text);
    scrollToBottom();
  } catch {
    // error already set in store
  }
}

function scrollToBottom() {
  nextTick(() => {
    if (!messagesEl.value) return;
    messagesEl.value.scrollTop = messagesEl.value.scrollHeight;
  });
}

watch(
  () => [store.messages.length, store.cardPreviews.length],
  () => scrollToBottom(),
);
</script>

<style scoped>
.chat-area {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: var(--bg);
}

.chat-header {
  padding: 14px 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.chat-header-title {
  font-size: var(--fs-sm);
  color: var(--muted);
  font-weight: 500;
}

.chat-header-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
  color: var(--accent-light);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-light);
}

.status-dot-err {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  animation: blink 1s ease-in-out infinite;
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ─── Empty state ─── */
.chat-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: var(--muted);
}

.chat-empty-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--accent-soft);
  display: grid;
  place-items: center;
  font-size: 28px;
  color: var(--accent);
}

.chat-empty-text {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 500;
  color: var(--fg);
}

.chat-empty-hint {
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* ─── Messages ─── */
.msg {
  max-width: 78%;
  padding: 12px 16px;
  border-radius: var(--radius-lg);
  font-size: var(--fs-body);
  line-height: 1.6;
  animation: msgIn 0.3s ease-out both;
}

@keyframes msgIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.msg-user {
  align-self: flex-end;
  background: var(--accent);
  color: var(--surface);
  border-bottom-right-radius: 4px;
}

.msg-ai {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}

.msg-success {
  align-self: flex-start;
  background: #f0faf5;
  border: 1.5px solid #2ecc71;
  border-bottom-left-radius: 4px;
  color: #1a7a3a;
}

.msg-time {
  display: block;
  text-align: right;
  font-size: 10px;
  color: var(--muted);
  margin-top: 4px;
  opacity: 0.7;
}

/* ─── Mini chat cards ─── */
.chat-card {
  align-self: flex-start;
  margin-top: -4px;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 300px;
  font-size: var(--fs-sm);
}

.chat-card:hover {
  border-color: var(--accent);
  box-shadow: 0 2px 10px rgba(43, 31, 153, 0.1);
}

.chat-card.active {
  border-color: var(--accent);
  background: var(--accent-faint);
  box-shadow: 0 2px 12px rgba(43, 31, 153, 0.08);
}

.cc-title {
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--fg);
  line-height: 1.3;
}

.cc-choice {
  font-size: var(--fs-xs);
  color: var(--muted);
  line-height: 1.4;
}

/* ─── Thinking bubble ─── */
.thinking-bubble {
  color: var(--muted);
  display: flex;
  gap: 1px;
}

.wave-char {
  display: inline-block;
  animation: waveJump 2s ease-in-out infinite;
}

@keyframes waveJump {
  0%, 100% { transform: translateY(0); }
  25% { transform: translateY(-6px); }
  50% { transform: translateY(0); }
}

/* ─── Disconnected overlay ─── */
.disconnected-overlay {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  text-align: center;
}

.disc-icon {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: color-mix(in oklch, var(--danger) 10%, transparent);
  display: grid;
  place-items: center;
  color: var(--danger);
  margin-bottom: 4px;
}

.disc-title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 600;
}

.disc-desc {
  font-size: var(--fs-sm);
  color: var(--muted);
  max-width: 280px;
}

.disc-btns {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.btn-accent {
  padding: 10px 24px;
  background: var(--accent);
  color: var(--surface);
  border-radius: var(--radius-sm);
  font-size: var(--fs-body);
  font-weight: 500;
  transition: background 0.15s ease;
}

.btn-accent:hover {
  background: color-mix(in oklch, var(--accent) 85%, black);
}

.btn-outline {
  padding: 10px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-body);
  color: var(--muted);
  background: transparent;
  transition: background 0.15s ease;
}

.btn-outline:hover {
  background: var(--bg);
}

</style>
