<script setup lang="ts">
import CommentBox from '@/components/common/CommentBox/index.vue'
import { useUserStore } from '@/stores'
import dayjs from 'dayjs'
import { push } from 'notivue'
import { storeToRefs } from 'pinia'
import BackButton from '@/components/common/BackButton/index.vue'
import type { ScrollbarInstance } from 'element-plus'
type MessageCategory = 'anonymous' | 'realname'
type MessageSender = 'self' | 'other'

interface ChatMessage {
  id: number
  sender: MessageSender
  text: string
  images: string[]
  createdAt: string
}

interface ConversationItem {
  id: number
  category: MessageCategory
  name: string
  avatar: string
  badge: string
  subtitle: string
  sourceTitle: string
  sourceTypeLabel: string
  onlineStatus: string
  unread: number
  isPinned?: boolean
  messages: ChatMessage[]
}

const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)

const categoryTabs = [
  {
    key: 'anonymous' as MessageCategory,
    label: '匿名私信',
    description: '适用于除问吧、实践、专访文章以外的内容',
  },
  {
    key: 'realname' as MessageCategory,
    label: '实名私信',
    description: '适用于问吧、实践、专访文章',
  },
]

const conversationList = ref<ConversationItem[]>([
  {
    id: 1,
    category: 'realname',
    name: '陈菲',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=ChengFei',
    badge: '实名',
    subtitle: '你上次提到的培训案例已经补充好了',
    sourceTitle: '实践 · 从复盘到落地的团队协作方法',
    sourceTypeLabel: '实践',
    onlineStatus: '29分钟前活跃',
    unread: 2,
    isPinned: true,
    messages: [
      {
        id: 101,
        sender: 'other',
        text: '你好，这篇实践文章里提到的复盘模板能发我看一下吗？',
        images: [],
        createdAt: '2026-04-09 09:18',
      },
      {
        id: 102,
        sender: 'self',
        text: '可以，我整理完私信给你。',
        images: [],
        createdAt: '2026-04-09 09:22',
      },
      {
        id: 103,
        sender: 'other',
        text: '好的，我也很想看看你们怎么把共识拆成执行动作。',
        images: [],
        createdAt: '2026-04-09 09:24',
      },
    ],
  },
  {
    id: 2,
    category: 'anonymous',
    name: '树洞来信',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousA',
    badge: '匿名',
    subtitle: '谢谢你愿意认真回复我的困惑',
    sourceTitle: '案例库 · 一次被看见的小改变',
    sourceTypeLabel: '案例',
    onlineStatus: '刚刚',
    unread: 0,
    messages: [
      {
        id: 201,
        sender: 'other',
        text: '看到你的评论后想私信你，原来很多人也会经历类似阶段。',
        images: [],
        createdAt: '2026-04-09 08:31',
      },
      {
        id: 202,
        sender: 'self',
        text: '会的，所以别急着否定自己，先把能做的小事做起来。',
        images: [],
        createdAt: '2026-04-09 08:36',
      },
    ],
  },
  {
    id: 3,
    category: 'realname',
    name: '王守勇',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=WangShouYong',
    badge: '实名',
    subtitle: '关于专访提到的组织演进，我补了两张图',
    sourceTitle: '专访 · 从宏大叙事到实事求是',
    sourceTypeLabel: '专访',
    onlineStatus: '今天 08:45',
    unread: 1,
    messages: [
      {
        id: 301,
        sender: 'other',
        text: '这两张图是给你补充的版本，可以一起带给同事看。',
        images: [
          'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=600&q=80',
          'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?auto=format&fit=crop&w=600&q=80',
        ],
        createdAt: '2026-04-09 08:45',
      },
    ],
  },
  {
    id: 4,
    category: 'anonymous',
    name: '未署名同事',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousB',
    badge: '匿名',
    subtitle: '想继续请教你怎么带新人',
    sourceTitle: '视频 · 一次普通晨会为什么能开得更好',
    sourceTypeLabel: '视频',
    onlineStatus: '昨天',
    unread: 0,
    messages: [
      {
        id: 401,
        sender: 'other',
        text: '我发现自己总在说结论，带新人时对方不太能跟上。',
        images: [],
        createdAt: '2026-04-08 17:20',
      },
      {
        id: 402,
        sender: 'self',
        text: '可以先从为什么这么做开始讲，再拆成两个最关键动作。',
        images: [],
        createdAt: '2026-04-08 17:35',
      },
    ],
  },
  {
    id: 11,
    category: 'realname',
    name: '陈菲',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=ChengFei',
    badge: '实名',
    subtitle: '你上次提到的培训案例已经补充好了',
    sourceTitle: '实践 · 从复盘到落地的团队协作方法',
    sourceTypeLabel: '实践',
    onlineStatus: '29分钟前活跃',
    unread: 2,
    isPinned: true,
    messages: [
      {
        id: 101,
        sender: 'other',
        text: '你好，这篇实践文章里提到的复盘模板能发我看一下吗？',
        images: [],
        createdAt: '2026-04-09 09:18',
      },
      {
        id: 102,
        sender: 'self',
        text: '可以，我整理完私信给你。',
        images: [],
        createdAt: '2026-04-09 09:22',
      },
      {
        id: 103,
        sender: 'other',
        text: '好的，我也很想看看你们怎么把共识拆成执行动作。',
        images: [],
        createdAt: '2026-04-09 09:24',
      },
    ],
  },
  {
    id: 21,
    category: 'anonymous',
    name: '树洞来信',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousA',
    badge: '匿名',
    subtitle: '谢谢你愿意认真回复我的困惑',
    sourceTitle: '案例库 · 一次被看见的小改变',
    sourceTypeLabel: '案例',
    onlineStatus: '刚刚',
    unread: 0,
    messages: [
      {
        id: 201,
        sender: 'other',
        text: '看到你的评论后想私信你，原来很多人也会经历类似阶段。',
        images: [],
        createdAt: '2026-04-09 08:31',
      },
      {
        id: 202,
        sender: 'self',
        text: '会的，所以别急着否定自己，先把能做的小事做起来。',
        images: [],
        createdAt: '2026-04-09 08:36',
      },
    ],
  },
  {
    id: 31,
    category: 'realname',
    name: '王守勇',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=WangShouYong',
    badge: '实名',
    subtitle: '关于专访提到的组织演进，我补了两张图',
    sourceTitle: '专访 · 从宏大叙事到实事求是',
    sourceTypeLabel: '专访',
    onlineStatus: '今天 08:45',
    unread: 1,
    messages: [
      {
        id: 301,
        sender: 'other',
        text: '这两张图是给你补充的版本，可以一起带给同事看。',
        images: [
          'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=600&q=80',
          'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?auto=format&fit=crop&w=600&q=80',
        ],
        createdAt: '2026-04-09 08:45',
      },
    ],
  },
  {
    id: 41,
    category: 'anonymous',
    name: '未署名同事',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousB',
    badge: '匿名',
    subtitle: '想继续请教你怎么带新人',
    sourceTitle: '视频 · 一次普通晨会为什么能开得更好',
    sourceTypeLabel: '视频',
    onlineStatus: '昨天',
    unread: 0,
    messages: [
      {
        id: 401,
        sender: 'other',
        text: '我发现自己总在说结论，带新人时对方不太能跟上。',
        images: [],
        createdAt: '2026-04-08 17:20',
      },
      {
        id: 402,
        sender: 'self',
        text: '可以先从为什么这么做开始讲，再拆成两个最关键动作。',
        images: [],
        createdAt: '2026-04-08 17:35',
      },
    ],
  },
  {
    id: 12,
    category: 'realname',
    name: '陈菲',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=ChengFei',
    badge: '实名',
    subtitle: '你上次提到的培训案例已经补充好了',
    sourceTitle: '实践 · 从复盘到落地的团队协作方法',
    sourceTypeLabel: '实践',
    onlineStatus: '29分钟前活跃',
    unread: 2,
    isPinned: true,
    messages: [
      {
        id: 101,
        sender: 'other',
        text: '你好，这篇实践文章里提到的复盘模板能发我看一下吗？',
        images: [],
        createdAt: '2026-04-09 09:18',
      },
      {
        id: 102,
        sender: 'self',
        text: '可以，我整理完私信给你。',
        images: [],
        createdAt: '2026-04-09 09:22',
      },
      {
        id: 103,
        sender: 'other',
        text: '好的，我也很想看看你们怎么把共识拆成执行动作。',
        images: [],
        createdAt: '2026-04-09 09:24',
      },
    ],
  },
  {
    id: 22,
    category: 'anonymous',
    name: '树洞来信',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousA',
    badge: '匿名',
    subtitle: '谢谢你愿意认真回复我的困惑',
    sourceTitle: '案例库 · 一次被看见的小改变',
    sourceTypeLabel: '案例',
    onlineStatus: '刚刚',
    unread: 0,
    messages: [
      {
        id: 201,
        sender: 'other',
        text: '看到你的评论后想私信你，原来很多人也会经历类似阶段。',
        images: [],
        createdAt: '2026-04-09 08:31',
      },
      {
        id: 202,
        sender: 'self',
        text: '会的，所以别急着否定自己，先把能做的小事做起来。',
        images: [],
        createdAt: '2026-04-09 08:36',
      },
    ],
  },
  {
    id: 32,
    category: 'realname',
    name: '王守勇',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=WangShouYong',
    badge: '实名',
    subtitle: '关于专访提到的组织演进，我补了两张图',
    sourceTitle: '专访 · 从宏大叙事到实事求是',
    sourceTypeLabel: '专访',
    onlineStatus: '今天 08:45',
    unread: 1,
    messages: [
      {
        id: 301,
        sender: 'other',
        text: '这两张图是给你补充的版本，可以一起带给同事看。',
        images: [
          'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=600&q=80',
          'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?auto=format&fit=crop&w=600&q=80',
        ],
        createdAt: '2026-04-09 08:45',
      },
    ],
  },
  {
    id: 4,
    category: 'anonymous',
    name: '未署名同事',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousB',
    badge: '匿名',
    subtitle: '想继续请教你怎么带新人',
    sourceTitle: '视频 · 一次普通晨会为什么能开得更好',
    sourceTypeLabel: '视频',
    onlineStatus: '昨天',
    unread: 0,
    messages: [
      {
        id: 401,
        sender: 'other',
        text: '我发现自己总在说结论，带新人时对方不太能跟上。',
        images: [],
        createdAt: '2026-04-08 17:20',
      },
      {
        id: 402,
        sender: 'self',
        text: '可以先从为什么这么做开始讲，再拆成两个最关键动作。',
        images: [],
        createdAt: '2026-04-08 17:35',
      },
    ],
  },
  {
    id: 13,
    category: 'realname',
    name: '陈菲',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=ChengFei',
    badge: '实名',
    subtitle: '你上次提到的培训案例已经补充好了',
    sourceTitle: '实践 · 从复盘到落地的团队协作方法',
    sourceTypeLabel: '实践',
    onlineStatus: '29分钟前活跃',
    unread: 2,
    isPinned: true,
    messages: [
      {
        id: 101,
        sender: 'other',
        text: '你好，这篇实践文章里提到的复盘模板能发我看一下吗？',
        images: [],
        createdAt: '2026-04-09 09:18',
      },
      {
        id: 102,
        sender: 'self',
        text: '可以，我整理完私信给你。',
        images: [],
        createdAt: '2026-04-09 09:22',
      },
      {
        id: 103,
        sender: 'other',
        text: '好的，我也很想看看你们怎么把共识拆成执行动作。',
        images: [],
        createdAt: '2026-04-09 09:24',
      },
    ],
  },
  {
    id: 2,
    category: 'anonymous',
    name: '树洞来信',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousA',
    badge: '匿名',
    subtitle: '谢谢你愿意认真回复我的困惑',
    sourceTitle: '案例库 · 一次被看见的小改变',
    sourceTypeLabel: '案例',
    onlineStatus: '刚刚',
    unread: 0,
    messages: [
      {
        id: 201,
        sender: 'other',
        text: '看到你的评论后想私信你，原来很多人也会经历类似阶段。',
        images: [],
        createdAt: '2026-04-09 08:31',
      },
      {
        id: 202,
        sender: 'self',
        text: '会的，所以别急着否定自己，先把能做的小事做起来。',
        images: [],
        createdAt: '2026-04-09 08:36',
      },
    ],
  },
  {
    id: 3,
    category: 'realname',
    name: '王守勇',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=WangShouYong',
    badge: '实名',
    subtitle: '关于专访提到的组织演进，我补了两张图',
    sourceTitle: '专访 · 从宏大叙事到实事求是',
    sourceTypeLabel: '专访',
    onlineStatus: '今天 08:45',
    unread: 1,
    messages: [
      {
        id: 301,
        sender: 'other',
        text: '这两张图是给你补充的版本，可以一起带给同事看。',
        images: [
          'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=600&q=80',
          'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?auto=format&fit=crop&w=600&q=80',
        ],
        createdAt: '2026-04-09 08:45',
      },
    ],
  },
  {
    id: 4,
    category: 'anonymous',
    name: '未署名同事',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousB',
    badge: '匿名',
    subtitle: '想继续请教你怎么带新人',
    sourceTitle: '视频 · 一次普通晨会为什么能开得更好',
    sourceTypeLabel: '视频',
    onlineStatus: '昨天',
    unread: 0,
    messages: [
      {
        id: 401,
        sender: 'other',
        text: '我发现自己总在说结论，带新人时对方不太能跟上。',
        images: [],
        createdAt: '2026-04-08 17:20',
      },
      {
        id: 402,
        sender: 'self',
        text: '可以先从为什么这么做开始讲，再拆成两个最关键动作。',
        images: [],
        createdAt: '2026-04-08 17:35',
      },
    ],
  },
  {
    id: 1,
    category: 'realname',
    name: '陈菲',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=ChengFei',
    badge: '实名',
    subtitle: '你上次提到的培训案例已经补充好了',
    sourceTitle: '实践 · 从复盘到落地的团队协作方法',
    sourceTypeLabel: '实践',
    onlineStatus: '29分钟前活跃',
    unread: 2,
    isPinned: true,
    messages: [
      {
        id: 101,
        sender: 'other',
        text: '你好，这篇实践文章里提到的复盘模板能发我看一下吗？',
        images: [],
        createdAt: '2026-04-09 09:18',
      },
      {
        id: 102,
        sender: 'self',
        text: '可以，我整理完私信给你。',
        images: [],
        createdAt: '2026-04-09 09:22',
      },
      {
        id: 103,
        sender: 'other',
        text: '好的，我也很想看看你们怎么把共识拆成执行动作。',
        images: [],
        createdAt: '2026-04-09 09:24',
      },
    ],
  },
  {
    id: 23,
    category: 'anonymous',
    name: '树洞来信',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousA',
    badge: '匿名',
    subtitle: '谢谢你愿意认真回复我的困惑',
    sourceTitle: '案例库 · 一次被看见的小改变',
    sourceTypeLabel: '案例',
    onlineStatus: '刚刚',
    unread: 0,
    messages: [
      {
        id: 201,
        sender: 'other',
        text: '看到你的评论后想私信你，原来很多人也会经历类似阶段。',
        images: [],
        createdAt: '2026-04-09 08:31',
      },
      {
        id: 202,
        sender: 'self',
        text: '会的，所以别急着否定自己，先把能做的小事做起来。',
        images: [],
        createdAt: '2026-04-09 08:36',
      },
    ],
  },
  {
    id: 33,
    category: 'realname',
    name: '王守勇',
    avatar: 'https://api.dicebear.com/7.x/adventurer/svg?seed=WangShouYong',
    badge: '实名',
    subtitle: '关于专访提到的组织演进，我补了两张图',
    sourceTitle: '专访 · 从宏大叙事到实事求是',
    sourceTypeLabel: '专访',
    onlineStatus: '今天 08:45',
    unread: 1,
    messages: [
      {
        id: 301,
        sender: 'other',
        text: '这两张图是给你补充的版本，可以一起带给同事看。',
        images: [
          'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&w=600&q=80',
          'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?auto=format&fit=crop&w=600&q=80',
        ],
        createdAt: '2026-04-09 08:45',
      },
    ],
  },
  {
    id: 42,
    category: 'anonymous',
    name: '未署名同事',
    avatar: 'https://api.dicebear.com/7.x/shapes/svg?seed=AnonymousB',
    badge: '匿名',
    subtitle: '想继续请教你怎么带新人',
    sourceTitle: '视频 · 一次普通晨会为什么能开得更好',
    sourceTypeLabel: '视频',
    onlineStatus: '昨天',
    unread: 0,
    messages: [
      {
        id: 401,
        sender: 'other',
        text: '我发现自己总在说结论，带新人时对方不太能跟上。',
        images: [],
        createdAt: '2026-04-08 17:20',
      },
      {
        id: 402,
        sender: 'self',
        text: '可以先从为什么这么做开始讲，再拆成两个最关键动作。',
        images: [],
        createdAt: '2026-04-08 17:35',
      },
    ],
  },
])

const activeCategory = ref<MessageCategory>('anonymous')
const activeConversationId = ref<number>(2)
const keyword = ref('')
const draftText = ref('')
const draftImages = ref('')
const sending = ref(false)
const messageListRef = useTemplateRef<HTMLDivElement>('messageListRef')
const conversationBoxRef = useTemplateRef<ScrollbarInstance>('conversationBoxRef')

const filteredConversationList = computed(() => {
  const lowerKeyword = keyword.value.trim().toLowerCase()

  return conversationList.value
    .filter((item) => item.category === activeCategory.value)
    .filter((item) => {
      if (!lowerKeyword) return true
      return [item.name, item.subtitle, item.sourceTitle].some((field) =>
        field.toLowerCase().includes(lowerKeyword),
      )
    })
    .sort((a, b) => {
      if (!!a.isPinned !== !!b.isPinned) return a.isPinned ? -1 : 1
      return (
        dayjs(b.messages.at(-1)?.createdAt).valueOf() -
        dayjs(a.messages.at(-1)?.createdAt).valueOf()
      )
    })
})

const activeConversation = computed(() => {
  const current = filteredConversationList.value.find(
    (item) => item.id === activeConversationId.value,
  )
  return current || filteredConversationList.value[0] || null
})

const groupedMessages = computed(() => {
  if (!activeConversation.value) return []

  const groups: Array<{ label: string; items: ChatMessage[] }> = []

  activeConversation.value.messages.forEach((message) => {
    const label = dayjs(message.createdAt).format('YYYY-MM-DD HH:mm')
    const lastGroup = groups.at(-1)

    if (!lastGroup || lastGroup.label !== label) {
      groups.push({ label, items: [message] })
      return
    }

    lastGroup.items.push(message)
  })

  return groups
})

const currentUserName = computed(() => userInfo.value?.hiddenName || userInfo.value?.name || '我')
const currentUserAvatar = computed(
  () =>
    userInfo.value?.hiddenAvatar ||
    userInfo.value?.avatar ||
    'https://api.dicebear.com/7.x/adventurer/svg?seed=Me',
)

const conversationStats = computed(() => ({
  anonymous: conversationList.value.filter((item) => item.category === 'anonymous').length,
  realname: conversationList.value.filter((item) => item.category === 'realname').length,
}))

const canSend = computed(() => {
  return (
    !!activeConversation.value &&
    (!!draftText.value.trim() || !!draftImages.value.trim()) &&
    !sending.value
  )
})

watch(
  filteredConversationList,
  (list) => {
    if (!list.length) {
      activeConversationId.value = 0
      return
    }

    if (!list.some((item) => item.id === activeConversationId.value) && list[0]) {
      activeConversationId.value = list[0].id
    }
  },
  { immediate: true },
)

watch(
  () => activeConversation.value?.id,
  async (id) => {
    if (!id) return
    const current = conversationList.value.find((item) => item.id === id)
    if (current) current.unread = 0
    await nextTick()
    scrollToBottom()
  },
  { immediate: true },
)

const getConversationPreviewTime = (conversation: ConversationItem) => {
  const latest = conversation.messages.at(-1)?.createdAt
  if (!latest) return '--'

  const now = dayjs()
  const target = dayjs(latest)

  if (target.isSame(now, 'day')) return target.format('HH:mm')
  if (target.isSame(now.subtract(1, 'day'), 'day')) return '昨天'
  return target.format('MM-DD')
}

const getMessageText = (message: ChatMessage) => {
  if (message.text.trim()) return message.text
  if (message.images.length) return '[图片]'
  return '[新消息]'
}

const selectConversation = (id: number) => {
  activeConversationId.value = id
}

const switchCategory = (category: MessageCategory) => {
  activeCategory.value = category
  keyword.value = ''
}

const scrollToBottom = () => {
  const wrapper = conversationBoxRef.value
  console.log(wrapper, 'wrapper')
  if (!wrapper) return
  console.log(wrapper.$el.scrollHeight, 'wrapper.$el.scrollHeight')
  wrapper.scrollTo({
    top: wrapper.$el.scrollHeight,
    behavior: 'smooth',
  })
}

const handleSend = async () => {
  if (!canSend.value || !activeConversation.value) return

  sending.value = true
  try {
    const newMessage: ChatMessage = {
      id: Date.now(),
      sender: 'self',
      text: draftText.value.trim(),
      images: draftImages.value
        .split(',')
        .map((item) => item.trim())
        .filter(Boolean),
      createdAt: dayjs().format('YYYY-MM-DD HH:mm'),
    }

    activeConversation.value.messages.push(newMessage)
    activeConversation.value.subtitle = getMessageText(newMessage)
    draftText.value = ''
    draftImages.value = ''

    await nextTick()
    scrollToBottom()
    push.success('私信已发送')
  } finally {
    sending.value = false
  }
}

const handleInputKeydown = (event: KeyboardEvent) => {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault()
    handleSend()
  }
}
</script>

<template>
  <div class="rounded-lg relative">
    <BackButton />
    <section class="flex h-[calc(100vh-6.25rem)] gap-4 overflow-hidden">
      <aside
        class="flex-1/4 rounded-lg border border-[#d8e5f2] bg-[linear-gradient(180deg,#ffffff_0%,#f8fbff_100%)] p-4 shadow-[0_0.5rem_1.5rem_rgba(134,167,207,0.12)]"
      >
        <div class="flex h-full flex-col">
          <div>
            <div class="mb-4 flex items-start justify-between gap-3">
              <div>
                <h2 class="m-0 text-4.5 font-700 text-[#17305d]">私信列表</h2>
              </div>
            </div>

            <div class="mb-4 grid grid-cols-2 gap-2">
              <button
                v-for="item in categoryTabs"
                :key="item.key"
                class="cursor-pointer flex items-center justify-between rounded-lg border px-4 py-3 text-3.5 transition-all"
                :class="
                  activeCategory === item.key
                    ? 'border-[#8eadff] bg-[linear-gradient(180deg,#f4f8ff_0%,#eaf1ff_100%)] text-[#2f5ab7] shadow-[0_0.25rem_0.625rem_rgba(130,160,220,0.12)]'
                    : 'border-[#dfebf5] bg-[#f9fbfe] text-[#667b95]'
                "
                @click="switchCategory(item.key)"
              >
                <span>{{ item.label }}</span>
                <span
                  class="inline-flex h-6 min-w-6 items-center justify-center rounded-full bg-[#e8eff8] px-1.5 text-3 font-700"
                >
                  {{
                    item.key === 'anonymous'
                      ? conversationStats.anonymous
                      : conversationStats.realname
                  }}
                </span>
              </button>
            </div>

            <el-input
              v-model="keyword"
              size="large"
              clearable
              placeholder="搜索用户名"
              class="mb-4"
            >
              <template #prefix>
                <el-icon><IEpSearch /></el-icon>
              </template>
            </el-input>
          </div>
          <div class="min-h-0 flex-1">
            <el-scrollbar>
              <div v-if="filteredConversationList.length" class="space-y-3">
                <button
                  v-for="item in filteredConversationList"
                  :key="item.id"
                  class="w-full rounded-lg border p-3 text-left transition-all"
                  :class="
                    activeConversation?.id === item.id
                      ? 'border-[#cbdcff] bg-[linear-gradient(180deg,#f6faff_0%,#edf5ff_100%)] shadow-[0_0.5rem_1.125rem_rgba(134,167,207,0.15)]'
                      : 'border-transparent bg-transparent hover:border-[#dde8f3] hover:bg-[#f9fbfe]'
                  "
                  @click="selectConversation(item.id)"
                >
                  <div class="flex gap-3">
                    <div class="relative shrink-0">
                      <el-avatar :size="46" :src="item.avatar" />
                    </div>

                    <div class="min-w-0 flex-1">
                      <div class="flex items-center justify-between gap-2">
                        <div class="flex min-w-0 items-center gap-2">
                          <span class="max-w-[6.875rem] truncate text-4 font-700 text-[#17305d]">
                            {{ item.name }}
                          </span>
                        </div>
                        <span class="shrink-0 text-3 text-[#8ca0b8]">{{
                          getConversationPreviewTime(item)
                        }}</span>
                      </div>

                      <div class="mt-2 flex min-w-0 items-center gap-2">
                        <span
                          class="inline-flex h-5 shrink-0 items-center rounded-full bg-[#fff3dc] px-2 text-3 text-[#9a6817]"
                        >
                          {{ item.sourceTypeLabel }}
                        </span>
                        <span class="truncate text-3 text-[#7890aa]">{{ item.sourceTitle }}</span>
                      </div>
                    </div>
                  </div>
                </button>
              </div>

              <el-empty v-else description="没有找到匹配的会话" :image-size="90" />
            </el-scrollbar>
          </div>
        </div>
      </aside>

      <main
        class="overflow-hidden h-full flex-3/4 rounded-lg border border-[#d8e5f2] bg-[linear-gradient(180deg,#ffffff_0%,#f9fbff_100%)] shadow-[0_0.5rem_1.5rem_rgba(134,167,207,0.12)]"
      >
        <template v-if="activeConversation">
          <div class="flex h-full min-h-0 flex-col">
            <header
              class="flex flex-col gap-3 border-b border-[#e6eef6] bg-[linear-gradient(180deg,#f6faff_0%,#ffffff_100%)] px-5 py-4 md:flex-row md:items-center md:justify-between"
            >
              <div class="flex min-w-0 items-center gap-3">
                <el-avatar :size="50" :src="activeConversation.avatar" />
                <div class="min-w-0">
                  <div class="flex items-center gap-2">
                    <strong class="text-4.5 font-700 text-[#18305d]">{{
                      activeConversation.name
                    }}</strong>
                    <span
                      class="inline-flex h-6 items-center rounded-full px-2.5 text-3 font-700"
                      :class="
                        activeConversation.category === 'anonymous'
                          ? 'bg-[#e7f7ed] text-[#2a7f61]'
                          : 'bg-[#e8f0ff] text-[#3762c7]'
                      "
                    >
                      {{ activeConversation.badge }}
                    </span>
                  </div>
                  <p class="mt-1 truncate text-[0.8125rem] leading-[1.375rem] text-[#7588a3]">
                    来源：{{ activeConversation.sourceTitle }} ·
                    {{ activeConversation.onlineStatus }}
                  </p>
                </div>
              </div>

              <div class="text-[0.8125rem] text-[#6f84a4]">
                当前对话按
                <span class="mx-1 font-700 text-[#4a6fd2]">{{ activeConversation.badge }}</span>
                方式展示
              </div>
            </header>
            <div class="min-h-0 flex-1 overflow-hidden">
              <el-scrollbar ref="conversationBoxRef">
                <div class="bg-[linear-gradient(180deg,#fcfdff_0%,#f8fbff_100%)] px-5 py-5">
                  <div v-for="group in groupedMessages" :key="group.label" class="pb-3">
                    <div class="mb-4 text-center text-3 text-[#96a6bb]">
                      <span class="rounded-full bg-[#eef4fb] px-3 py-1">{{ group.label }}</span>
                    </div>

                    <div
                      v-for="message in group.items"
                      :key="message.id"
                      class="mb-4 flex items-start gap-3"
                      :class="{ 'flex-row-reverse': message.sender === 'self' }"
                    >
                      <el-avatar
                        :size="38"
                        :src="
                          message.sender === 'self' ? currentUserAvatar : activeConversation.avatar
                        "
                        class="shrink-0"
                      />

                      <div
                        class="flex max-w-[min(72%,38.75rem)] flex-col gap-1"
                        :class="{ 'items-end': message.sender === 'self' }"
                      >
                        <div class="text-3 text-[#8c9bb0]">
                          {{
                            message.sender === 'self' ? currentUserName : activeConversation.name
                          }}
                        </div>

                        <div
                          class="rounded-lg border px-4 py-3 shadow-[0_0.125rem_0.5rem_rgba(39,74,120,0.04)]"
                          :class="
                            message.sender === 'self'
                              ? 'rounded-tr-[0.375rem] border-[#d4e4ff] bg-[#dbeaff] text-[#1a3f73]'
                              : 'rounded-tl-[0.375rem] border-[#e7edf5] bg-white text-[#23364c]'
                          "
                        >
                          <p
                            v-if="message.text"
                            class="m-0 whitespace-pre-wrap break-words text-3.5 leading-[1.625rem]"
                          >
                            {{ message.text }}
                          </p>

                          <div v-if="message.images.length" class="mt-2 grid gap-2 sm:grid-cols-2">
                            <el-image
                              v-for="image in message.images"
                              :key="image"
                              :src="image"
                              fit="cover"
                              :preview-src-list="message.images"
                              preview-teleported
                              class="h-30 w-full overflow-hidden rounded-[0.875rem]"
                            />
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </el-scrollbar>
            </div>
            <footer class="border-t border-[#e6eef6] bg-white px-5 py-4 h-auto">
              <div
                class="mb-3 flex items-center justify-between gap-3 text-[0.8125rem] text-[#7690ac]"
              >
                <div class="flex items-center gap-1.5">
                  <el-icon><IEpInfoFilled /></el-icon>
                  <span>按 Enter 发送，Shift + Enter 换行</span>
                </div>
                <span>{{ draftText.length }} / 250</span>
              </div>

              <div class="self-message-commentbox" @keydown="handleInputKeydown">
                <CommentBox
                  v-model:inputText="draftText"
                  v-model:inputImg="draftImages"
                  :textAreaHeight="72"
                  placeholder="请输入回复内容，回车发送"
                >
                  <template #submit>
                    <button
                      type="button"
                      class="comment-publish-btn cursor-pointer disabled:opacity-50 px-6 py-2 text-white rounded-full text-sm hover:shadow-lg transition-all"
                      :disabled="!draftText?.trim() || sending"
                      @click="handleSend"
                    >
                      <div v-show="sending" class="flex items-center gap-2">
                        <el-icon><IEpLoading /></el-icon>
                        <span>发表中...</span>
                      </div>
                      <div v-show="!sending">发表</div>
                    </button>
                  </template>
                </CommentBox>
              </div>
            </footer>
          </div>
        </template>

        <div v-else class="flex h-full items-center justify-center">
          <el-empty description="选择一个会话开始查看私信内容" :image-size="120" />
        </div>
      </main>
    </section>
  </div>
</template>

<style scoped>
:deep(.self-message-commentbox textarea) {
  min-height: 4.25rem !important;
}

:deep(.self-message-commentbox .el-button--primary) {
  border-radius: 0.875rem;
  border-color: #85a7ff;
  background: linear-gradient(90deg, #71b6ff 0%, #7f92ff 100%);
  box-shadow: 0 0.375rem 1rem rgba(125, 146, 255, 0.2);
}

:deep(.self-message-commentbox .el-button--large) {
  min-width: 5.75rem;
}

@media (max-width: 64rem) {
  :deep(.self-message-commentbox .el-button--large) {
    width: 100%;
  }
}
/**
 * 发表按钮：不用纯 Uno 渐变工具类。
 * 旧版内核 / 部分企业微信 WebView 对「依赖 CSS 变量的 linear-gradient」解析失败时，
 * 背景会变成透明或无效，原生 button 呈白底，易出现「只剩阴影、几乎看不见按钮」。
 * 这里用实色 background-color 作兜底，并写死 hex + -webkit- 前缀渐变。
 */
.comment-publish-btn {
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
  border: 1px solid rgba(255, 255, 255, 0.35);
  /* 与 Tailwind blue-500 / purple-500 接近的实色兜底 */
  background-color: #6366f1;
  background-image: -webkit-linear-gradient(left, #3b82f6, #a855f7);
  background-image: linear-gradient(to right, #3b82f6, #a855f7);
  color: #ffffff;
}

.comment-publish-btn:disabled {
  cursor: not-allowed;
}
</style>
