<template>
  <view ref="conversationListInnerDomRef" class="tui-conversation-list">
    <ActionsMenu
      v-if="isShowOverlay"
      :selectedConversation="currentConversation"
      :actionsMenuPosition="actionsMenuPosition"
      :selectedConversationDomRect="currentConversationDomRect"
      @closeConversationActionMenu="closeConversationActionMenu"
    />
    <!-- <cb-empty
      v-if="conversationList.length === 0"
      name="您还没有好友"
    ></cb-empty> -->
    <view
      class="tui-conversation-item"
      @click="navigateTo('/pages/my-index/set-up/message/index')"
    >
      <aside class="left">
        <Avatar url="/static/images/message.svg" size="40px" />
        <!-- 通知数量 -->
        <!-- <span class="num">2</span> -->
        <!-- <span class="num-notify" /> -->
      </aside>
      <view class="content">
        <view class="content-header">
          <view class="content-header-label">
            <text class="name">消息通知</text>
          </view>
          <view class="middle-box">
            <div class="middle-box-content">[系统消息]</div>
          </view>
        </view>
        <!-- <view class="content-footer">
          <span class="time">20秒前</span>
        </view> -->
      </view>
    </view>
    <view
      v-for="(conversation, index) in conversationList"
      :id="`convlistitem-${index}`"
      :key="index"
      :class="[
        'tui-conversation-content',
        isMobile && 'tui-conversation-content-h5 disable-select'
      ]"
    >
      <div
        :class="[
          isPC && 'isPC',
          'tui-conversation-item',
          currentConversationID === conversation.conversationID &&
            'tui-conversation-item-selected',
          conversation.isPinned && 'tui-conversation-item-pinned'
        ]"
        @click="enterConversationChat(conversation.conversationID)"
        @longpress="
          showConversationActionMenu($event, conversation, index)
        "
        @contextmenu="
          showConversationActionMenu($event, conversation, index, true)
        "
      >
        <aside class="left">
          <Avatar
            useSkeletonAnimation
            :url="conversation.getAvatar()"
            size="40px"
          />
          <div
            v-if="
              userOnlineStatusMap && isShowUserOnlineStatus(conversation)
            "
            :class="[
              'online-status',
              Object.keys(userOnlineStatusMap).length > 0 &&
              Object.keys(userOnlineStatusMap).includes(
                conversation.userProfile.userID
              ) &&
              userOnlineStatusMap[conversation.userProfile.userID]
                .statusType === 1
                ? 'online-status-online'
                : 'online-status-offline'
            ]"
          />
          <span
            v-if="conversation.unreadCount > 0 && !conversation.isMuted"
            class="num"
          >
            {{
              conversation.unreadCount > 99
                ? '99+'
                : conversation.unreadCount
            }}
          </span>
          <span
            v-if="conversation.unreadCount > 0 && conversation.isMuted"
            class="num-notify"
          />
        </aside>
        <view class="content">
          <view class="content-header">
            <label class="content-header-label">
              <p class="name">{{ conversation.getShowName() }}</p>
            </label>
            <view v-if="isRedEnvelope(conversation)" class="middle-box">
              <div class="middle-box-content">
                {{ redEnvelopeText(conversation) }}
              </div>
            </view>
            <view v-else class="middle-box">
              <span
                v-if="
                  conversation.draftText &&
                  conversation.conversationID !== currentConversationID
                "
                class="middle-box-draft"
              >
                {{ TUITranslateService.t('TUIChat.[草稿]') }}
              </span>
              <span
                v-else-if="
                  conversation.type === 'GROUP' &&
                  conversation.groupAtInfoList &&
                  conversation.groupAtInfoList.length > 0
                "
                class="middle-box-at"
              >
                {{ conversation.getGroupAtInfo() }}
              </span>
              <view class="middle-box-content">
                {{
                  isFirstCreateGroup(conversation) ||
                  conversation.getLastMessage('text')
                }}
              </view>
            </view>
          </view>
          <view class="content-footer">
            <span class="time">
              {{ conversation.getLastMessage('time') }}
            </span>
            <Icon
              v-if="conversation.isMuted"
              :file="muteIcon"
              size="16px"
            />
          </view>
        </view>
      </div>
    </view>
  </view>
</template>

<script lang="ts" setup>
  interface IUserStatus {
    statusType: number
    customStatus: string
  }

  interface IUserStatusMap {
    [userID: string]: IUserStatus
  }

  import { ref, onMounted, onUnmounted } from '../../../adapter-vue'
  import TUIChatEngine, {
    TUIStore,
    StoreName,
    TUIConversationService,
    TUITranslateService,
    IConversationModel
  } from '@tencentcloud/chat-uikit-engine-lite'
  import {
    TUIGlobal,
    isIOS,
    addLongPressListener
  } from '@tencentcloud/universal-api'
  import Icon from '../../common/Icon.vue'
  import Avatar from '../../common/Avatar/index.vue'
  import ActionsMenu from '../actions-menu/index.vue'
  import muteIcon from '../../../assets/icon/mute.svg'
  import {
    isPC,
    isH5,
    isUniFrameWork,
    isMobile
  } from '../../../utils/env'
  import { CHAT_MSG_CUSTOM_TYPE } from '../../../constant'
  import { navigateTo } from '../../../../utils/router'

  const emits = defineEmits(['handleSwitchConversation', 'getPassingRef'])
  const currentConversation = ref<IConversationModel>()
  const currentConversationID = ref<string>()
  const currentConversationDomRect = ref<DOMRect>()
  const isShowOverlay = ref<boolean>(false)
  const conversationList = ref<IConversationModel[]>([])
  const conversationListDomRef = ref<HTMLElement | undefined>()
  const conversationListInnerDomRef = ref<HTMLElement | undefined>()
  const actionsMenuPosition = ref<{
    top: number
    left: number | undefined
    conversationHeight: number | undefined
  }>({
    top: 0,
    left: undefined,
    conversationHeight: undefined
  })
  const displayOnlineStatus = ref(false)
  const userOnlineStatusMap = ref<IUserStatusMap>()

  let lastestOpenActionsMenuTime: number | null = null

  onMounted(() => {
    TUIStore.watch(StoreName.CONV, {
      currentConversationID: onCurrentConversationIDUpdated,
      conversationList: onConversationListUpdated,
      currentConversation: onCurrentConversationUpdated
    })

    TUIStore.watch(StoreName.USER, {
      displayOnlineStatus: onDisplayOnlineStatusUpdated,
      userStatusList: onUserStatusListUpdated
    })

    if (!isUniFrameWork && isIOS && !isPC) {
      addLongPressHandler()
    }
  })

  onUnmounted(() => {
    TUIStore.unwatch(StoreName.CONV, {
      currentConversationID: onCurrentConversationIDUpdated,
      conversationList: onConversationListUpdated,
      currentConversation: onCurrentConversationUpdated
    })

    TUIStore.unwatch(StoreName.USER, {
      displayOnlineStatus: onDisplayOnlineStatusUpdated,
      userStatusList: onUserStatusListUpdated
    })
  })

  const isShowUserOnlineStatus = (
    conversation: IConversationModel
  ): boolean => {
    return (
      displayOnlineStatus.value &&
      conversation.type === TUIChatEngine.TYPES.CONV_C2C
    )
  }

  const showConversationActionMenu = (
    event: Event,
    conversation: IConversationModel,
    index: number,
    isContextMenuEvent?: boolean
  ) => {
    if (isContextMenuEvent) {
      event.preventDefault()
      if (isUniFrameWork) {
        return
      }
    }
    currentConversation.value = conversation
    lastestOpenActionsMenuTime = Date.now()
    getActionsMenuPosition(event, index)
  }

  const closeConversationActionMenu = () => {
    // Prevent continuous triggering of overlay tap events
    if (
      lastestOpenActionsMenuTime &&
      Date.now() - lastestOpenActionsMenuTime > 300
    ) {
      currentConversation.value = undefined
      isShowOverlay.value = false
    }
  }

  const getActionsMenuPosition = (event: Event, index: number) => {
    if (isUniFrameWork) {
      if (typeof conversationListDomRef.value === 'undefined') {
        emits('getPassingRef', conversationListDomRef)
      }
      const query = TUIGlobal?.createSelectorQuery().in(
        conversationListDomRef.value
      )
      query
        .select(`#convlistitem-${index}`)
        .boundingClientRect(data => {
          if (data) {
            actionsMenuPosition.value = {
              // The uni-page-head of uni-h5 is not considered a member of the viewport, so the height of the head is manually increased.
              top: data.bottom - 44,
              // @ts-expect-error in uniapp event has touches property
              left: event.touches[0].pageX,
              conversationHeight: data.height
            }
            isShowOverlay.value = true
          }
        })
        .exec()
    } else {
      const rect =
        (
          (event.currentTarget || event.target) as HTMLElement
        )?.getBoundingClientRect() || {}
      if (rect) {
        actionsMenuPosition.value = {
          top: rect.bottom,
          left: isPC ? (event as MouseEvent).clientX : undefined,
          conversationHeight: rect.height
        }
      }
      isShowOverlay.value = true
    }
  }

  const enterConversationChat = (conversationID: string) => {
    emits('handleSwitchConversation', conversationID)
    TUIConversationService.switchConversation(conversationID)
  }

  function addLongPressHandler() {
    if (!conversationListInnerDomRef.value) {
      return
    }
    addLongPressListener({
      element: conversationListInnerDomRef.value,
      onLongPress: (event, target) => {
        const index = (
          Array.from(
            conversationListInnerDomRef.value!.children
          ) as HTMLElement[]
        ).indexOf(target!)
        showConversationActionMenu(
          event,
          conversationList.value[index],
          index
        )
      },
      options: {
        eventDelegation: {
          subSelector: '.tui-conversation-content'
        }
      }
    })
  }

  function onCurrentConversationUpdated(
    conversation: IConversationModel
  ) {
    currentConversation.value = conversation
  }

  /** 是否红包 */
  const isRedEnvelope = (item: IConversationModel) => {
    if (
      item?.lastMessage?.payload?.data &&
      item?.lastMessage?.type === 'TIMCustomElem'
    ) {
      const businessID = JSON?.parse(
        item?.lastMessage?.payload?.data
      )?.businessID
      return businessID === CHAT_MSG_CUSTOM_TYPE.RED_ENVELOPE
    }
    return false
  }

  /** 红包文案 */
  const redEnvelopeText = (item: IConversationModel) => {
    const payload = JSON.parse(item.lastMessage?.payload?.data)
    const text = item.getLastMessage('text')?.split(':')

    if (text && text.length > 1) {
      return `${text[0]}:[积分红包] ${payload.title}`
    } else {
      return `[积分红包] ${payload.title}`
    }
  }

  /** 是否最开始创建群聊 */
  const isFirstCreateGroup = (item: IConversationModel) => {
    // if (item.type === 'GROUP' && item?.lastMessage?.payload?.data) {
    //   const data = JSON.parse(item?.lastMessage?.payload?.data)
    //   return data.content === 'Create Group'
    //     ? `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
    //     : ''
    // }
    if (item?.lastMessage?.payload?.data) {
      const data = JSON.parse(item?.lastMessage?.payload?.data)
      const text = item.getLastMessage('text')?.split(':')
      const isText = text && text.length > 1
      if (data.businessID === CHAT_MSG_CUSTOM_TYPE.GOODS) {
        if (isText) {
          return `${text[0]}:[商品信息] ${data.title}`
        } else {
          return `[商品信息]:${data.title}`
        }
      }
      if (data.content === 'Create Group' && item.type === 'GROUP') {
        return `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
      }
      return ''
    }
    return ''
  }

  function onConversationListUpdated(list: IConversationModel[]) {
    conversationList.value = list
  }

  function onCurrentConversationIDUpdated(id: string) {
    currentConversationID.value = id
  }

  function onDisplayOnlineStatusUpdated(status: boolean) {
    displayOnlineStatus.value = status
  }

  function onUserStatusListUpdated(list: Map<string, IUserStatus>) {
    if (list.size !== 0) {
      userOnlineStatusMap.value = [...list.entries()].reduce(
        (obj, [key, value]) => {
          obj[key] = value
          return obj
        },
        {} as IUserStatusMap
      )
    }
  }
  // Expose to the parent component and close actionsMenu when a sliding event is detected
  defineExpose({ closeChildren: closeConversationActionMenu })
</script>

<style lang="scss" scoped src="./style/index.scss"></style>
<style lang="scss" scoped>
  .disable-select {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }
  .tui-conversation-item {
    &::after {
      display: none !important;
    }
    &:active {
      background: #f4f4f4 !important;
    }
  }
</style>
