<script setup lang="ts">
const emit = defineEmits<{ close: [] }>()

const { messages, connected, authorOnline, loading, loadingMore, hasMore, error, send, loadMore } = useChat()
const { user } = useAuthSession()
const currentUserId = computed(() => user.value?.id)

const inputText = ref('')
const listRef = ref<HTMLElement | null>(null)
const inputRef = ref<HTMLInputElement | null>(null)
const sending = ref(false)

watch(() => messages.value.length, () => {
  scrollToBottom()
})

// Also scroll when loading finishes (initial load)
watch(loading, (val) => {
  if (!val && messages.value.length > 0) {
    nextTick(() => scrollToBottom())
  }
})

// Infinite scroll: load older messages when scrolling to top.
// Guard against triggering during initial load or programmatic scroll-to-bottom.
let scrollLock = false

function scrollToBottom() {
  scrollLock = true
  nextTick(() => {
    const el = listRef.value
    if (el && el.lastElementChild) {
      el.lastElementChild.scrollIntoView({ block: 'end' })
    }
    setTimeout(() => { scrollLock = false }, 300)
  })
}

function onScroll() {
  if (scrollLock) return
  const el = listRef.value
  if (!el || loading.value || loadingMore.value || !hasMore.value) return
  if (el.scrollTop < 80) {
    const prevHeight = el.scrollHeight
    loadMore().then(() => {
      nextTick(() => {
        if (listRef.value) {
          listRef.value.scrollTop = listRef.value.scrollHeight - prevHeight
        }
      })
    })
  }
}

async function handleSend() {
  const text = inputText.value.trim()
  if (!text || sending.value) return
  sending.value = true
  try {
    await send(text)
    inputText.value = ''
  } catch { /* composable handles error */ }
  finally {
    sending.value = false
    nextTick(() => inputRef.value?.focus())
  }
}

function handleKeydown(e: KeyboardEvent) {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    handleSend()
  }
}
</script>

<template>
  <div class="chat-room">
    <!-- Header -->
    <div class="chat-header">
      <div class="header-left">
        <h2 class="chat-title">聊天</h2>
        <span v-if="authorOnline" class="author-dot" title="作者在线" />
      </div>
      <div class="header-right">
        <span v-if="!connected" class="connecting-text">连接中…</span>
        <button class="close-btn" @click="emit('close')" aria-label="关闭">
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
            <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
          </svg>
        </button>
      </div>
    </div>

    <!-- Messages -->
    <div ref="listRef" class="chat-messages" @scroll="onScroll">
      <div v-if="loadingMore" class="load-more-indicator">
        <div class="empty-spinner" />
      </div>
      <div v-if="loading" class="chat-empty">
        <div class="empty-spinner" />
        <span>加载消息中</span>
      </div>
      <div v-else-if="messages.length === 0" class="chat-empty">
        <span>还没有消息，说点什么吧</span>
      </div>
      <template v-else>
        <ChatBubble
          v-for="msg in messages"
          :key="msg.id"
          :message="msg"
          :is-mine="msg.userId != null && msg.userId === currentUserId"
        />
      </template>
    </div>

    <!-- Error -->
    <Transition name="error-slide">
      <div v-if="error" class="chat-error">{{ error }}</div>
    </Transition>

    <!-- Input -->
    <div class="chat-input-area">
      <div class="input-composer">
        <input
          ref="inputRef"
          v-model="inputText"
          class="chat-input"
          placeholder="输入消息…"
          maxlength="500"
          @keydown="handleKeydown"
        />
        <button class="at-btn" title="@作者" @click="inputText += (inputText ? ' ' : '') + '@作者 '">@</button>
        <button
          class="send-btn"
          :disabled="!inputText.trim() || sending"
          @click="handleSend"
        >
          <svg v-if="!sending" width="16" height="16" viewBox="0 0 18 18" fill="none">
            <path d="M2 9L16 2L9 16L7.5 10.5L2 9Z" fill="currentColor"/>
            <path d="M7.5 10.5L11 7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
          <span v-else class="sending-spinner" />
        </button>
      </div>
      <p class="input-hint">
        <template v-if="authorOnline">作者在线 &middot; <code>@作者</code> 无需邮件</template>
        <template v-else><code>@作者</code> 可邮件通知</template>
      </p>
    </div>
  </div>
</template>

<style scoped>
/* ═══════════════════════════════════════════
   WARM CREAM CHAT ROOM
   ═══════════════════════════════════════════ */

.chat-room {
  --bg: #faf9f5;
  --bg-card: #ffffff;
  --bg-soft: #f5f0e8;
  --text: #141413;
  --text-body: #3d3d3a;
  --text-soft: #8e8b82;
  --accent: #cc785c;
  --accent-active: #a9583e;
  --hairline: #e6dfd8;
  --hairline-soft: #ebe6df;

  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  background: var(--bg);
}

/* ── Header ── */
.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline-soft);
  background: var(--bg-card);
  flex-shrink: 0;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 10px;
}

.chat-title {
  font-family: 'Abril Fatface', Georgia, serif;
  font-size: 20px;
  font-weight: 400;
  color: var(--text);
  letter-spacing: -0.3px;
  margin: 0;
  line-height: 1;
}

/* Author online dot */
.author-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #5db872;
  box-shadow: 0 0 6px rgba(93, 184, 114, 0.4);
  flex-shrink: 0;
}

/* Header right */
.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.connecting-text {
  font-size: 11px;
  color: var(--text-soft);
}

/* Close button — only visible on narrow screens */
.close-btn {
  display: none;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: transparent;
  color: var(--text-soft);
  border: 1px solid transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
}

.close-btn:hover {
  background: var(--bg-soft);
  color: var(--text);
  border-color: var(--hairline);
}

/* ── Messages ── */
.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  scroll-behavior: smooth;
  background: linear-gradient(180deg, var(--bg-card) 0%, var(--bg) 80px);
}

.chat-messages::-webkit-scrollbar {
  width: 4px;
}

.chat-messages::-webkit-scrollbar-track {
  background: transparent;
}

.chat-messages::-webkit-scrollbar-thumb {
  background: rgba(142, 139, 130, 0.18);
  border-radius: 9999px;
}

.chat-messages::-webkit-scrollbar-thumb:hover {
  background: rgba(142, 139, 130, 0.3);
}

/* Empty */
.chat-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-soft);
  font-size: 13px;
}

.load-more-indicator {
  display: flex;
  justify-content: center;
  padding: 8px 0;
}

.empty-spinner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--hairline);
  border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
  margin-right: 8px;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* ── Error ── */
.chat-error {
  padding: 8px 16px;
  font-size: 12px;
  color: #c64545;
  background: rgba(198, 69, 69, 0.05);
  border-top: 1px solid rgba(198, 69, 69, 0.12);
  flex-shrink: 0;
}

.error-slide-enter-active,
.error-slide-leave-active {
  transition: all 0.2s ease;
}

.error-slide-enter-from,
.error-slide-leave-to {
  opacity: 0;
  transform: translateY(100%);
}

/* ── Input ── */
.chat-input-area {
  flex-shrink: 0;
  padding: 10px 12px 8px;
  border-top: 1px solid var(--hairline-soft);
  background: var(--bg-card);
}

.input-composer {
  display: flex;
  align-items: center;
  gap: 6px;
}

.chat-input {
  flex: 1;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13.5px;
  color: var(--text-body);
  background: var(--bg);
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
  box-sizing: border-box;
}

.chat-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(204, 120, 92, 0.08);
}

.chat-input::placeholder {
  color: var(--text-soft);
}

.chat-input:disabled {
  opacity: 0.5;
}

/* @ button */
.at-btn {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  background: var(--bg);
  color: var(--accent);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.at-btn:hover {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* Send button */
.send-btn {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.15s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.send-btn:hover:not(:disabled) {
  background: var(--accent-active);
}

.send-btn:active:not(:disabled) {
  transform: scale(0.95);
}

.send-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.sending-spinner {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.3);
  border-top-color: #fff;
  animation: spin 0.6s linear infinite;
}

/* Hint */
.input-hint {
  margin: 6px 0 0;
  font-size: 11px;
  color: var(--text-soft);
  opacity: 0.5;
  padding: 0 2px;
}

.input-hint code {
  background: var(--bg-soft);
  padding: 1px 4px;
  border-radius: 3px;
  font-size: 10px;
  color: var(--accent);
  font-weight: 600;
}

/* ── Mobile fullscreen override ── */

@media (max-width: 640px) {
  .close-btn {
    display: flex;
  }

  .chat-header {
    padding: 10px 14px;
  }

  .chat-title {
    font-size: 18px;
  }

  .chat-messages {
    padding: 14px;
  }

  .chat-input-area {
    padding: 8px 10px 8px;
  }
}
</style>
