<script setup lang="ts">
import { ref, nextTick, watch } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useAiChat } from '@/composables/useAiChat'

const ai = useAiChat()
const inputText = ref('')
const scrollIntoView = ref('')
const scrollTimer = ref<ReturnType<typeof setTimeout> | null>(null)

/** 滚动到底部(消息列表更新时) */
function scrollToBottom(): void {
  if (scrollTimer.value) clearTimeout(scrollTimer.value)
  scrollTimer.value = setTimeout(() => {
    // 用 id 标记滚动锚点
    scrollIntoView.value = ''
    nextTick(() => {
      scrollIntoView.value = 'msg-bottom-anchor'
    })
  }, 50)
}

/** 发送消息 */
function handleSend(): void {
  const text = inputText.value
  if (!text.trim() || ai.generating.value) return
  ai.send(text)
  inputText.value = ''
}

/** 停止生成 */
function handleStop(): void {
  ai.stop()
}

/** 切换到会话列表页 */
function goConversations(): void {
  uni.switchTab({ url: '/pages/conversations/index' })
}

// 消息列表变化时滚到底
watch(
  () => ai.messages.length,
  () => scrollToBottom()
)
watch(
  () => ai.currentText.value,
  () => scrollToBottom()
)

onShow(() => {
  // 页面显示时若已连接,滚到底部展示最新消息
  scrollToBottom()
})
</script>

<template>
  <view class="chat-page">
    <!-- 顶部状态栏 -->
    <view class="status-bar">
      <view class="status-dot" :class="ai.isWsConnected.value ? 'online' : 'offline'" />
      <text class="status-text">
        {{ ai.isWsConnected.value ? '已连接桌面端' : ai.wsStatus.value }}
      </text>
      <view class="status-spacer" />
      <view class="header-btn" @click="goConversations">
        <text>会话</text>
      </view>
    </view>

    <!-- 消息列表 -->
    <scroll-view
      class="msg-list"
      scroll-y
      :scroll-into-view="scrollIntoView"
      :scroll-with-animation="true"
    >
      <view v-if="ai.messages.length === 0" class="empty-hint">
        <text>暂无消息,发送一条试试</text>
      </view>

      <view
        v-for="msg in ai.messages"
        :key="msg.id"
        class="msg-row"
        :class="msg.role"
      >
        <!-- user 气泡 -->
        <view v-if="msg.role === 'user'" class="bubble user-bubble">
          <text>{{ msg.content }}</text>
        </view>

        <!-- assistant / system 气泡 -->
        <view v-else class="bubble" :class="msg.isError ? 'error-bubble' : msg.role === 'system' ? 'system-bubble' : 'assistant-bubble'">
          <text>{{ msg.content }}</text>
          <!-- 工具调用列表(简化展示 name + status) -->
          <view v-if="msg.toolCalls && msg.toolCalls.length" class="tool-calls">
            <view v-for="tc in msg.toolCalls" :key="tc.id" class="tool-call">
              <text class="tool-name">{{ tc.name }}</text>
              <text class="tool-status" :class="tc.status">{{ tc.status }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 流式生成中的当前文本(末尾渲染,非独立气泡) -->
      <view v-if="ai.generating.value && ai.currentText.value" class="msg-row assistant">
        <view class="bubble assistant-bubble streaming">
          <text>{{ ai.currentText.value }}</text>
          <text class="cursor">▎</text>
        </view>
      </view>

      <!-- 空占位 assistant(刚发,等首个 delta) -->
      <view
        v-if="ai.generating.value && !ai.currentText.value && ai.messages.length > 0 && ai.messages[ai.messages.length - 1].role === 'assistant' && !ai.messages[ai.messages.length - 1].content"
        class="msg-row assistant"
      >
        <view class="bubble assistant-bubble">
          <text class="thinking">思考中...</text>
        </view>
      </view>

      <!-- 滚动锚点 -->
      <view id="msg-bottom-anchor" class="bottom-anchor" />
    </scroll-view>

    <!-- 输入栏 -->
    <view class="input-bar">
      <view class="input-wrap">
        <input
          v-model="inputText"
          class="input"
          type="text"
          placeholder="输入消息..."
          :disabled="ai.generating.value"
          confirm-type="send"
          @confirm="handleSend"
        />
      </view>
      <view v-if="!ai.generating.value" class="send-btn" @click="handleSend">
        <text>发送</text>
      </view>
      <view v-else class="stop-btn" @click="handleStop">
        <text>停止</text>
      </view>
    </view>
  </view>
</template>

<style lang="scss" scoped>
.chat-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: $uni-bg-color;
}

.status-bar {
  display: flex;
  align-items: center;
  padding: 16rpx 24rpx;
  background-color: $uni-bg-color-dark;
  border-bottom: 1rpx solid $uni-border-color;
}

.status-dot {
  width: 16rpx;
  height: 16rpx;
  border-radius: 50%;
  margin-right: 12rpx;
  &.online {
    background-color: $uni-color-success;
  }
  &.offline {
    background-color: $uni-text-color-disable;
  }
}

.status-text {
  font-size: $uni-font-size-sm;
  color: $uni-text-color-grey;
}

.status-spacer {
  flex: 1;
}

.header-btn {
  padding: 8rpx 24rpx;
  background-color: $uni-bg-color-light;
  border-radius: 8rpx;
  text {
    font-size: $uni-font-size-sm;
    color: $uni-color-primary;
  }
}

.msg-list {
  flex: 1;
  padding: 24rpx;
}

.empty-hint {
  text-align: center;
  padding: 200rpx 0;
  text {
    color: $uni-text-color-disable;
    font-size: $uni-font-size-sm;
  }
}

.msg-row {
  display: flex;
  margin-bottom: 24rpx;
  &.user {
    justify-content: flex-end;
  }
  &.assistant,
  &.system {
    justify-content: flex-start;
  }
}

.bubble {
  max-width: 80%;
  padding: 20rpx 24rpx;
  border-radius: 16rpx;
  text {
    font-size: $uni-font-size-base;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
  }
}

.user-bubble {
  background-color: $uni-bubble-user-bg;
  text {
    color: $uni-bubble-user-text;
  }
}

.assistant-bubble {
  background-color: $uni-bubble-assistant-bg;
  text {
    color: $uni-bubble-assistant-text;
  }
  &.streaming {
    border: 1rpx solid $uni-color-primary;
  }
}

.system-bubble {
  background-color: transparent;
  border: 1rpx dashed $uni-border-color;
  text {
    color: $uni-text-color-grey;
    font-size: $uni-font-size-sm;
  }
}

.error-bubble {
  background-color: $uni-bubble-error-bg;
  text {
    color: $uni-bubble-error-text;
  }
}

.cursor {
  color: $uni-color-primary;
  animation: blink 1s infinite;
}

.thinking {
  color: $uni-text-color-grey;
  font-style: italic;
}

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

.tool-calls {
  margin-top: 12rpx;
  padding-top: 12rpx;
  border-top: 1rpx solid $uni-border-color;
}

.tool-call {
  display: flex;
  align-items: center;
  margin-bottom: 4rpx;
}

.tool-name {
  font-size: $uni-font-size-sm;
  color: $uni-color-primary;
  margin-right: 12rpx;
}

.tool-status {
  font-size: $uni-font-size-sm;
  color: $uni-text-color-grey;
  &.completed { color: $uni-color-success; }
  &.failed, &.rejected { color: $uni-color-error; }
  &.pending_approval { color: $uni-color-warning; }
}

.bottom-anchor {
  height: 1rpx;
}

.input-bar {
  display: flex;
  align-items: center;
  padding: 16rpx 24rpx;
  background-color: $uni-bg-color-dark;
  border-top: 1rpx solid $uni-border-color;
}

.input-wrap {
  flex: 1;
  padding: 0 24rpx;
  background-color: $uni-bg-color-light;
  border-radius: 8rpx;
}

.input {
  width: 100%;
  height: 72rpx;
  color: $uni-text-color;
  font-size: $uni-font-size-base;
}

.send-btn {
  padding: 16rpx 32rpx;
  background-color: $uni-color-primary;
  border-radius: 8rpx;
  margin-left: 16rpx;
  text {
    color: #ffffff;
    font-size: $uni-font-size-base;
  }
}

.stop-btn {
  padding: 16rpx 32rpx;
  background-color: $uni-color-error;
  border-radius: 8rpx;
  margin-left: 16rpx;
  text {
    color: #ffffff;
    font-size: $uni-font-size-base;
  }
}
</style>
