<template>
  <div ref="conversationListInnerDomRef" class="flex flex-col tui-conversation-list h-full" :loading="loading">
    <div class="order-status flex-shrink-0">
      <el-radio-group v-model="mergeStatus" @change="updateMeageStatus">
        <!-- <el-radio-button label="全部" /> -->
        <el-badge :value="needDealMessageCount" class="item" v-if="needDealMessageCount > 0">
          <el-radio-button label="需处理" />
        </el-badge>
        <el-radio-button v-else label="需处理" />
        <el-radio-button label="已处理" />
      </el-radio-group>

      <el-switch v-model="isOnline" inline-prompt active-text="在线" inactive-text="下线" size="default"
        style="--el-switch-on-color: #0074ff; --el-switch-off-color: #999" @change="changeonlineStatus" />
    </div>
    <!-- <ActionsMenu v-if="isShowOverlay" :selectedConversation="currentConversation" :actionsMenuPosition="actionsMenuPosition" :selectedConversationDomRect="currentConversationDomRect" @closeConversationActionMenu="closeConversationActionMenu" /> -->
    <div class="flex-grow relative overflow-y-hidden">
      <div class="absolute inset-0">
        <div class="h-full overflow-y-auto">
          <div v-if="mergeStatus === '需处理'">
            <div v-if="myConversationList.length > 0" v-for="(conversation, index) in myConversationList"
              :id="`convlistitem-${index}`" :key="index"
              :class="['tui-conversation-content', isMobile && 'tui-conversation-content-h5 disable-select']"
              class="borderBottom">
              <div
                :class="[isPC && 'isPC', 'tui-conversation-item', currentConversationID === conversation.conversationID && 'tui-conversation-item-selected', conversation.isPinned && 'tui-conversation-item-pinned']"
                @click="enterConversationChat(conversation.conversationID, conversation.order)"
                @longpress="showConversationActionMenu($event, conversation, index)"
                @contextmenu="showConversationActionMenu($event, conversation, index, true)">
                <div class="content">
                  <div class="content-header">
                    <label class="content-header-label">
                      <aside class="left">
                        <p class="name">
                          <span v-if="conversation.order && conversation.order.consultType === 'onlineMedicinePurchase'"
                            class="purchase-tag">在线配药</span>
                          <span v-if="conversation.order && conversation.order.consultType === 'wineConsult'"
                            class="purchase-tag success">中药饮片</span>
                          {{ getShowName(conversation.order) }}
                          <span v-if="isVideoConsultingOrder(conversation.order)" class="video-consult-icon"
                            title="视频问诊中">
                            <svg viewBox="0 0 24 24" width="14" height="14">
                              <path
                                d="M3 5h13a2 2 0 0 1 2 2v2.5l3-2v9l-3-2V17a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2z"
                                fill="currentColor" />
                            </svg>
                          </span>
                        </p>
                        <span v-if="conversation.unreadCount > 0 && !conversation.isMuted" class="num">
                          {{ conversation.unreadCount > 99 ? "99+" : conversation.unreadCount }}
                        </span>
                      </aside>
                    </label>
                    <div 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>
                      <div class="middle-box-content">
                        <div v-if="conversation.lastMessage.type === 'TIMCustomElem'" class="customText">
                          {{ getLastMessageContent(conversation.lastMessage.payload) }}
                        </div>
                        <div v-else class="customText">{{ conversation.getLastMessage("text") }}</div>
                      </div>
                    </div>
                  </div>
                  <div class="content-footer">
                    <div style="font-size: 14px" :style="'color:' + conversation.order?.statusColor || 'red'">{{
                      conversation.order?.status }}</div>
                    <div class="time">{{ conversation.getLastMessage("time") }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div v-else>
              <EmptyData title="暂无会话" />
            </div>
          </div>
          <historyConversationList :orderList="orderList" class="h-full" v-else />
        </div>
      </div>
    </div>

  </div>
</template>

<script lang="ts" setup>
interface IUserStatus {
  statusType: number;
  customStatus: string;
}
interface IUserStatusMap {
  [userID: string]: IUserStatus;
}
import { ref, onMounted, onUnmounted, watch, computed } from "../../../adapter-vue";
import TUIChatEngine, { TUIStore, StoreName, TUIConversationService, TUITranslateService, IConversationModel } from "@tencentcloud/chat-uikit-engine";
import { TUIGlobal, isIOS, addLongPressListener } from "@tencentcloud/universal-api";
import historyConversationList from "@/views/hlw-hospital/components/history-conversation-list.vue";
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 { getConsultOrder, updateConsultOrderStatus } from "@/api/hlw";
import { inject } from "vue";
import { useVideoConsultStore } from "@/store/video-consult";
import { isPC, isH5, isUniFrameWork, isMobile } from "../../../utils/env";
import EmptyData from "@/components/empty-data.vue";
import dayjs from "dayjs";
import { Check, Close } from "@element-plus/icons-vue";

const emits = defineEmits(["handleSwitchConversation", "getPassingRef", "newConversationUpdated", "updateHlwDoctorOnlineStatus"]);
const currentConversation = ref<IConversationModel>();
const currentConversationID = ref<string>();
const isShowOverlay = ref<boolean>(false);
const conversationList = ref<any[]>([]);
const conversationListDomRef = ref<HTMLElement | undefined>();
const conversationListInnerDomRef = ref<HTMLElement | undefined>();
const videoConsultStore = useVideoConsultStore();
const orderList = inject("orderList") as any;
const mergeStatus = inject("mergeStatus") as any;
const onlineStatus = inject("onlineStatus") as any;
const loading = ref(true);
const isOnline = computed({
  get: () => onlineStatus.value === "online",
  set: () => { },
});
function updateMeageStatus(e: string) {
  currentConversationID.value = "";
  TUIConversationService.switchConversation("");
}

function changeonlineStatus(e: boolean) {
  emits("updateHlwDoctorOnlineStatus", e ? "online" : "offline");
}

function onRefresh() {
  emits("newConversationUpdated");
}

function getShowName(item: any) {
  if (!item) return "";
  return `${item.name}/${item.sex}/${item.age}`;
}

// 是否为当前进行视频问诊的订单（用于会话列表摄像头标识）
function isVideoConsultingOrder(order: any) {
  if (!order || !order.orderId) return false;
  return videoConsultStore.status !== "idle" && videoConsultStore.activeOrderId === order.orderId;
}

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(async () => {
  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 needDealConversationList = computed(() => {
  return conversationList.value.filter((item) => ["processing", "pending", "completed"].includes(item.order?.orderStatus));
});
const completedConversationList = computed(() => {
  return conversationList.value.filter((item) => !["processing", "pending", "completed"].includes(item.order?.orderStatus));
});
const myConversationList = computed(() => {
  conversationList.value.forEach((item) => {
    const { userID } = item.userProfile;
    item.order = orderList.value.find((order: any) => order.orderId === userID);
  });
  if (mergeStatus.value === "需处理") {
    return needDealConversationList.value;
  } else if (mergeStatus.value === "已处理") {
    return completedConversationList.value;
  } else {
    return [];
  }
});
const needDealMessageCount = computed(() => {
  return needDealConversationList.value.reduce((prev, current) => prev + current.unreadCount, 0);
});
const completedMessageCount = computed(() => {
  return completedConversationList.value.reduce((prev, current) => prev + current.unreadCount, 0);
});

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 = () => {
  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 + (isH5 ? 44 : 0),
            // @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 = async (conversationID: string, order: any) => {
  emits("handleSwitchConversation", conversationID, order);
  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;
}

function onConversationListUpdated(list: IConversationModel[]) {
  // 拿到会话
  console.log("onConversationListUpdated", list);

  console.log("conversationList.value", conversationList.value[0]);
  const conversation = conversationList.value[0];
  console.log("conversation", conversation);
  if (list.length !== conversationList.value.length || (conversation?.lastMessage && conversation?.lastMessage?.type === "TIMCustomElem" && conversation?.lastMessage?.payload.data === "CANCELLED")) emits("newConversationUpdated");
  conversationList.value = list;
}

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

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

function onUserStatusListUpdated(list: Map<string, IUserStatus>) {
  console.log("onUserStatusListUpdatedlist", list);
  if (list.size !== 0) {
    userOnlineStatusMap.value = [...list.entries()].reduce((obj, [key, value]) => {
      obj[key] = value;
      return obj;
    }, {} as IUserStatusMap);
  }
}

function parseMessageExtension(ext) {
  if (!ext || typeof ext !== "string") return ext;
  try {
    const obj = JSON.parse(ext);
    if (!obj || typeof obj !== "object") return ext;
    // 如果解析出来的对象包含 doctorText 或 patientText，返回 doctorText（侧边栏统一显示医生视角）
    if (obj.doctorText || obj.patientText) {
      return obj.doctorText || obj.patientText || "已结束";
    }
    return ext;
  } catch {
    return ext;
  }
}

function getLastMessageContent(payload) {
  if (payload.data === 'AUDIPASS') {
    return '处方审核通过'
  }
  // 解析 extension 字段，如果是 JSON 则提取文本
  return parseMessageExtension(payload.extension)
}
// 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;
}

.borderBottom {
  border-bottom: 1px solid #eee;
}

.order-status {
  padding: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.online {
  font-size: 14px;
  color: #006eff;
}

.customText {
  width: 210px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.refresh {
  font-size: 14px;
  color: #006eff;
  cursor: pointer;
}

.video-consult-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 4px;
  color: #0074ff;
}

.purchase-tag {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 4px;
  background: #b8956a;
  color: white;
  font-size: 12px;
}

.purchase-tag.success {
  background: #67c23a;
}
</style>
