<template>
  <view :class="themeClass" class="page-container chat-page">
    <!-- 自定义导航栏 -->
    <view class="chat-nav" :style="{ paddingTop: headerPaddingTop }">
      <view class="chat-nav-inner">
        <view class="nav-back" @click="goBack">
          <text class="nav-back-icon">‹</text>
        </view>
        <view class="nav-center">
          <text class="nav-title">{{ nickname }}</text>
          <text class="nav-status">{{ peerTyping ? '正在输入...' : (isOnline ? '在线' : '离线') }}</text>
        </view>
        <view class="nav-placeholder"></view>
      </view>
    </view>

    <!-- 消息区域 -->
    <scroll-view
      class="chat-scroll"
      scroll-y
      :scroll-into-view="scrollToId"
      :scroll-with-animation="true"
    >
      <view class="chat-messages">
        <template v-for="(msg, idx) in messages" :key="msg.id">
          <!-- 时间分隔线 -->
          <view v-if="showTimeDivider(idx)" class="time-divider">
            <text class="time-divider-text">{{ formatTime(msg.timestamp) }}</text>
          </view>

          <!-- 消息气泡 -->
          <view
            :id="'msg-' + msg.id"
            class="msg-row"
            :class="{ 'msg-row-self': isSelf(msg) }"
          >
            <!-- 对方头像 -->
            <view v-if="!isSelf(msg)" class="msg-avatar-wrap">
              <view class="msg-avatar msg-avatar-ph">
                <text class="msg-avatar-text">{{ nickname ? nickname[0] : '酒' }}</text>
              </view>
            </view>

            <!-- 气泡 -->
            <view class="msg-bubble" :class="isSelf(msg) ? 'msg-bubble-self' : 'msg-bubble-peer'">
              <image
                v-if="msg.type === 'image'"
                class="msg-image"
                :src="msg.content"
                mode="widthFix"
                @click="previewImage(msg.content)"
              ></image>
              <text v-else class="msg-text">{{ msg.content }}</text>
            </view>

            <!-- 自己头像 -->
            <view v-if="isSelf(msg)" class="msg-avatar-wrap">
              <view class="msg-avatar msg-avatar-ph msg-avatar-self">
                <text class="msg-avatar-text">我</text>
              </view>
            </view>
          </view>

          <!-- 消息状态（仅自己发送的） -->
          <view v-if="isSelf(msg) && msg.status === 'sending'" class="msg-status">
            <text class="msg-status-text">发送中...</text>
          </view>
          <view v-if="isSelf(msg) && msg.status === 'failed'" class="msg-status msg-status-fail" @click="resend(msg)">
            <text class="msg-status-text">发送失败，点击重试</text>
          </view>
        </template>

        <!-- 对方正在输入 -->
        <view v-if="peerTyping" class="msg-row">
          <view class="msg-avatar-wrap">
            <view class="msg-avatar msg-avatar-ph">
              <text class="msg-avatar-text">{{ nickname ? nickname[0] : '酒' }}</text>
            </view>
          </view>
          <view class="msg-bubble msg-bubble-peer msg-typing">
            <text class="msg-typing-dot">·</text>
            <text class="msg-typing-dot">·</text>
            <text class="msg-typing-dot">·</text>
          </view>
        </view>

        <!-- 底部锚点 -->
        <view id="msg-bottom" style="height: 20rpx;"></view>
      </view>
    </scroll-view>

    <!-- 底部输入栏 -->
    <view class="chat-input-bar" :style="inputBarStyle">
      <view class="chat-input-wrap">
        <input
          class="chat-input"
          v-model="inputText"
          placeholder="说点什么..."
          placeholder-class="chat-input-ph"
          confirm-type="send"
          :adjust-position="false"
          :focus="inputFocus"
          :hold-keyboard="true"
          @confirm="sendMessage"
          @input="onInput"
          @blur="onInputBlur"
        />
      </view>
      <view
        class="chat-send-btn"
        :class="{ 'chat-send-active': inputText.trim() }"
        @touchstart="onSendTouch"
        @click="sendMessage"
      >
        <text class="chat-send-icon">➤</text>
      </view>
    </view>
  </view>
</template>

<script>
import { GetMessages, MarkRead } from '../../common/api'
import wsManager from '../../common/websocket'
import themeMixin from '../../common/theme-mixin'

export default {
  mixins: [themeMixin],
  data() {
    const menuBtn = uni.getMenuButtonBoundingClientRect()
    return {
      headerPaddingTop: (menuBtn.top + 8) + 'px',
      friendId: '',
      nickname: '',
      conversationId: '',
      messages: [],
      inputText: '',
      inputFocus: false,
      keyboardHeight: 0,
      scrollToId: '',
      isOnline: false,
      peerTyping: false,
      typingTimer: null,
      page: 1,
      hasMore: true
    }
  },
  onLoad(options) {
    this.friendId = options.friendId || ''
    this.nickname = decodeURIComponent(options.nickname || '')
    this.conversationId = options.conversationId || ''
    this.loadMessages()
    this.markRead()
    this.bindWsEvents()
    // 监听键盘高度变化，动态调整输入栏位置（避免键盘顶起整个页面）
    uni.onKeyboardHeightChange(res => {
      this.keyboardHeight = res.height
      if (res.height > 0) {
        this.$nextTick(() => this.scrollToBottom())
      }
    })
  },
  onUnload() {
    this.unbindWsEvents()
    if (this.typingTimer) {
      clearTimeout(this.typingTimer)
    }
    uni.offKeyboardHeightChange()
  },
  computed: {
    inputBarStyle() {
      if (this.keyboardHeight > 0) {
        // +10px 缓冲，避免输入栏与键盘顶部贴合/遮挡
        return { paddingBottom: (this.keyboardHeight + 10) + 'px' }
      }
      return {}
    }
  },
  methods: {
    // === 数据加载 ===
    async loadMessages() {
      try {
        const res = await GetMessages({ conversationId: this.conversationId, page: this.page })
        this.messages = res.data.list
        this.hasMore = res.data.hasMore
        this.$nextTick(() => {
          this.scrollToBottom()
        })
      } catch (e) {
        console.warn('加载消息失败', e)
      }
    },

    async markRead() {
      try {
        await MarkRead({ conversationId: this.conversationId })
        // 通过 WebSocket 发送已读回执
        if (this.messages.length) {
          const lastMsg = this.messages[this.messages.length - 1]
          wsManager.send('read', {
            conversationId: this.conversationId,
            lastMsgId: lastMsg.id
          })
        }
      } catch (e) { /* ignore */ }
    },

    // === WebSocket 事件 ===
    bindWsEvents() {
      wsManager.on('message', this.onWsMessage)
      wsManager.on('typing', this.onWsTyping)
      wsManager.on('ack', this.onWsAck)
    },
    unbindWsEvents() {
      wsManager.off('message', this.onWsMessage)
      wsManager.off('typing', this.onWsTyping)
      wsManager.off('ack', this.onWsAck)
    },

    /** 收到新消息 */
    onWsMessage(data) {
      // 只处理当前会话的消息
      if (data.senderId !== this.friendId) return
      const msg = {
        id: data.msgId || 'msg_' + Date.now(),
        conversationId: this.conversationId,
        senderId: data.senderId,
        receiverId: 'user_001',
        type: data.msgType || 'text',
        content: data.content,
        timestamp: data.timestamp || Date.now(),
        status: 'sent'
      }
      this.messages.push(msg)
      this.peerTyping = false
      this.$nextTick(() => this.scrollToBottom())
      // 发送已读回执
      wsManager.send('read', {
        conversationId: this.conversationId,
        lastMsgId: msg.id
      })
    },

    /** 对方正在输入 */
    onWsTyping(data) {
      if (data.senderId !== this.friendId) return
      this.peerTyping = true
      if (this.typingTimer) clearTimeout(this.typingTimer)
      this.typingTimer = setTimeout(() => {
        this.peerTyping = false
      }, 3000)
    },

    /** 消息送达确认 */
    onWsAck(data) {
      const msg = this.messages.find(m => m.id === data.clientMsgId)
      if (msg) {
        msg.id = data.msgId || msg.id
        msg.status = data.status || 'sent'
      }
    },

    // === 发送消息 ===
    sendMessage() {
      const text = this.inputText.trim()
      if (!text) return

      const clientMsgId = 'msg_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6)
      const msg = {
        id: clientMsgId,
        conversationId: this.conversationId,
        senderId: 'user_001',
        receiverId: this.friendId,
        type: 'text',
        content: text,
        timestamp: Date.now(),
        status: 'sending'
      }

      // 乐观更新：立即显示
      this.messages.push(msg)
      this.inputText = ''
      this.$nextTick(() => this.scrollToBottom())

      // 键盘保持由 onInputBlur 处理，无需额外操作

      // 通过 WebSocket 发送
      wsManager.send('chat', {
        receiverId: this.friendId,
        content: text,
        msgType: 'text',
        clientMsgId
      })

      // 模拟确认（Mock模式下直接标记为已发送）
      setTimeout(() => {
        msg.status = 'sent'
      }, 500)
    },

    /** 重发失败消息 */
    resend(msg) {
      msg.status = 'sending'
      wsManager.send('chat', {
        receiverId: this.friendId,
        content: msg.content,
        msgType: msg.type,
        clientMsgId: msg.id
      })
      setTimeout(() => {
        msg.status = 'sent'
      }, 500)
    },

    /** 点击发送按钮时记录时间戳 */
    onSendTouch() {
      this._sendTouchedAt = Date.now()
    },

    /** 输入框失焦：若因点击发送按钮导致，立即重聚焦保持键盘不收起 */
    onInputBlur() {
      if (this._sendTouchedAt && Date.now() - this._sendTouchedAt < 500) {
        this._sendTouchedAt = 0
        this.inputFocus = false
        this.$nextTick(() => {
          this.inputFocus = true
        })
      }
    },

    /** 输入时通知对方 */
    onInput() {
      wsManager.send('typing', { receiverId: this.friendId })
    },

    // === 辅助方法 ===
    isSelf(msg) {
      return msg.senderId === 'user_001'
    },

    showTimeDivider(idx) {
      if (idx === 0) return true
      const prev = this.messages[idx - 1]
      const curr = this.messages[idx]
      return (curr.timestamp - prev.timestamp) > 5 * 60 * 1000
    },

    formatTime(ts) {
      const d = new Date(ts)
      const now = new Date()
      const isToday = d.toDateString() === now.toDateString()
      const h = String(d.getHours()).padStart(2, '0')
      const m = String(d.getMinutes()).padStart(2, '0')
      if (isToday) return `${h}:${m}`
      const month = d.getMonth() + 1
      const day = d.getDate()
      return `${month}月${day}日 ${h}:${m}`
    },

    scrollToBottom() {
      this.scrollToId = ''
      this.$nextTick(() => {
        this.scrollToId = 'msg-bottom'
      })
    },

    previewImage(url) {
      uni.previewImage({ urls: [url] })
    },

    goBack() {
      uni.navigateBack()
    }
  }
}
</script>

<style lang="scss" scoped>
.chat-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

/* 导航栏 */
.chat-nav {
  background: $bg-base;
  padding-left: $sp-lg;
  padding-right: $sp-lg;
  padding-bottom: $sp-sm;
  position: relative;
  z-index: 10;
  border-bottom: 1rpx solid var(--border-faint, rgba(255,255,255,0.08));
}

.chat-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 88rpx;
}

.nav-back {
  width: 64rpx;
  height: 64rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: $bg-card;

  &:active {
    background: $bg-card-alt;
  }
}

.nav-back-icon {
  font-size: 44rpx;
  color: $text-primary;
  font-weight: $fw-bold;
  margin-top: -4rpx;
}

.nav-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2rpx;
}

.nav-title {
  font-size: $fs-base;
  font-weight: $fw-bold;
  color: $text-primary;
}

.nav-status {
  font-size: $fs-xs;
  color: $text-tertiary;
}

.nav-placeholder {
  width: 64rpx;
}

/* 消息区域 */
.chat-scroll {
  flex: 1;
  height: 0;
}

.chat-messages {
  padding: $sp-lg;
  padding-bottom: $sp-md;
}

/* 时间分隔 */
.time-divider {
  text-align: center;
  padding: $sp-md 0;
}

.time-divider-text {
  font-size: $fs-xs;
  color: $text-tertiary;
  background: $bg-card;
  padding: 6rpx 20rpx;
  border-radius: $radius-full;
}

/* 消息行 */
.msg-row {
  display: flex;
  align-items: flex-start;
  gap: $sp-sm;
  margin-bottom: $sp-md;
}

.msg-row-self {
  flex-direction: row-reverse;
}

/* 头像 */
.msg-avatar-wrap {
  flex-shrink: 0;
}

.msg-avatar {
  width: 72rpx;
  height: 72rpx;
  border-radius: 50%;
}

.msg-avatar-ph {
  background: linear-gradient(135deg, rgba(232,168,56,0.15), rgba(139,133,184,0.15));
  display: flex;
  align-items: center;
  justify-content: center;
}

.msg-avatar-self {
  background: linear-gradient(135deg, rgba(232,168,56,0.25), rgba(232,168,56,0.1));
}

.msg-avatar-text {
  font-size: $fs-sm;
  font-weight: $fw-bold;
  color: $amber;
}

/* 气泡 */
.msg-bubble {
  max-width: 65%;
  padding: $sp-md $sp-lg;
  border-radius: $radius-lg;
  word-break: break-all;
}

.msg-bubble-peer {
  background: $bg-card-alt;
  border-top-left-radius: 8rpx;
}

.msg-bubble-self {
  background: $amber-glow;
  border: 1rpx solid rgba(232,168,56,0.2);
  border-top-right-radius: 8rpx;
}

.msg-text {
  font-size: $fs-base;
  color: $text-primary;
  line-height: $lh-normal;
}

.msg-image {
  max-width: 360rpx;
  border-radius: $radius-md;
}

/* 消息状态 */
.msg-status {
  text-align: right;
  padding-right: 100rpx;
  margin-top: -8rpx;
  margin-bottom: $sp-sm;
}

.msg-status-text {
  font-size: $fs-xs;
  color: $text-tertiary;
}

.msg-status-fail .msg-status-text {
  color: $coral;
}

/* 正在输入动画 */
.msg-typing {
  display: flex;
  align-items: center;
  gap: 6rpx;
  padding: $sp-md $sp-lg;
}

.msg-typing-dot {
  font-size: $fs-xl;
  color: $text-tertiary;
  animation: typingBlink 1.4s infinite;

  &:nth-child(2) {
    animation-delay: 0.2s;
  }
  &:nth-child(3) {
    animation-delay: 0.4s;
  }
}

@keyframes typingBlink {
  0%, 60%, 100% { opacity: 0.3; }
  30% { opacity: 1; }
}

/* 底部输入栏 */
.chat-input-bar {
  display: flex;
  align-items: center;
  gap: $sp-md;
  padding: $sp-md $sp-lg;
  padding-bottom: calc(env(safe-area-inset-bottom) + #{$sp-md});
  background: $bg-base;
  border-top: 1rpx solid var(--border-faint, rgba(255,255,255,0.08));
  transition: padding-bottom 0.15s ease-out;
}

.chat-input-wrap {
  flex: 1;
  background: $bg-card;
  border-radius: $radius-full;
  border: 1rpx solid var(--border-faint, rgba(255,255,255,0.08));
  padding: 0 $sp-lg;
  height: 80rpx;
  display: flex;
  align-items: center;
}

.chat-input {
  width: 100%;
  height: 80rpx;
  font-size: $fs-base;
  color: $text-primary;
}

.chat-input-ph {
  color: $text-tertiary;
}

.chat-send-btn {
  flex-shrink: 0;
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background: $bg-card;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all $duration-fast $ease-out;
}

.chat-send-active {
  background: linear-gradient(135deg, $amber, $amber-deep);
  box-shadow: $shadow-amber;
}

.chat-send-icon {
  font-size: 32rpx;
  color: $text-tertiary;

  .chat-send-active & {
    color: $text-on-amber;
  }
}
</style>
