<template>
  <info-window :elderMode="elderMode" :visible="infoVisible" :order="consult" @close="infoVisible = false" />
  <full-page ref="pageRef" mainStyle="background:#fff">
    <template #header>
      <consult-head v-if="consult" :consult="consult" @viewSummary="viewSummary" />
    </template>
    <scroll-view scroll-y class="message-scroll-view" :scroll-into-view="scrollToMessageID"
      :scroll-with-animation="true" :enable-back-to-top="true" @scrolltoupper="onScrollToUpper"
      @refresherrefresh="onRefresh" refresher-enabled :refresher-triggered="isRefreshing" ref="scrollViewRef">
      <!-- 将网络错误提示移到scroll-view内部顶部 -->
      <view v-if="!networkAvailable" class="network-error" :class="{ 'network-error--elder': elderMode }">
        <view class="network-error-content" :class="{ 'network-error-content--elder': elderMode }">
          <text :class="{ 'text--elder': elderMode }">网络连接异常，请检查网络</text>
          <button class="retry-btn" :class="{ 'retry-btn--elder': elderMode }" @click="retryConnection">重试</button>
        </view>
      </view>

      <!-- 消息接收超时提示 -->
      <view v-if="messageReceiveTimeout && networkAvailable" class="message-timeout-error"
        :class="{ 'message-timeout-error--elder': elderMode }">
        <view class="message-timeout-content" :class="{ 'message-timeout-content--elder': elderMode }">
          <text :class="{ 'text--elder': elderMode }">长时间未收到消息，连接可能已断开</text>
          <button class="retry-btn" :class="{ 'retry-btn--elder': elderMode }" @click="handleMessageTimeout">
            重连
          </button>
        </view>
      </view>
      <view style="padding: 20rpx 30rpx" :class="{ 'message-container--elder': elderMode }">
        <view v-if="isMore" class="system-message" :class="{ 'system-message--elder': elderMode }"
          style="margin-top: 20rpx" @click="loadMoreMessages">
          <text v-if="loading" :class="{ 'text--elder': elderMode }">加载中...</text>
          <text v-else :class="{ 'text--elder': elderMode }">查看更多</text>
        </view>
        <view v-for="(item, index) in messageList" :id="`msg-${item.ID}`" :key="item.ID || index"
          :class="'message-li ' + item.flow + (elderMode ? ' message-li--elder' : '')">
          <view v-if="messageTime[item.ID]" class="time-message" :class="{ 'time-message--elder': elderMode }">
            {{ messageTime[item.ID] }}
          </view>
          <chat-message v-if="item.type === 'TIMImageElem' || item.type === 'TIMTextElem'" :message="item" />
          <ConsultMessageCustom v-else-if="item.type === 'TIMCustomElem'" :content="item" :messageItem="item"
            :partnerAvatar="partnerInfo && partnerInfo.avatar" />
        </view>
        <!-- 添加一个底部元素，用于滚动到最底部 -->
        <view id="msg-bottom" style="height: 20px"></view>
      </view>
    </scroll-view>
    <template #footer>
      <consult-countdown :expireTime="consult?.expireTime" @countdown-finished="closeChat" v-if="
        consult?.orderStatus === 'processing' ||
        consult?.orderStatus === 'completed'
      ">
      </consult-countdown>
      <view v-if="canSendMessage && footerBtnMode === 'settle'" class="bg-light-gray px-15 pb-10"
        :style="elderVarStyle">
        <view class="flex mb-10">
          <view class="border bg-white inline px-10 py-5 rounded-full text-base text-dark"
            @click="footerBtnMode = 'input'">回复医生</view>
        </view>
        <view class="w-full py-12 text-center text-base text-white bg-primary rounded" @click="settleRx()">
          {{ orderRx.btnText }}
        </view>
      </view>
      <template v-else-if="canSendMessage && footerBtnMode === 'input'">
        <view v-if="orderRx && orderRx.prescriptionType === 'onlineMedicinePurchase'" class="px-15 flex bg-light-gray"
          :style="elderVarStyle">
          <view class="px-10 py-5 rounded-full bg-primary text-base text-white" @click="settleRx()">
            {{ orderRx.btnText }}
          </view>
        </view>
        <!-- 若处于接听模式，则不显示输入框 -->
        <input-bar v-if="!rtcPendingOrderId && !rtcConnected && !rtcConfig" @sendImage="chooseImage"
          @sendMessage="sendTextMessage" />
      </template>
    </template>
  </full-page>
</template>

<script setup>
import { ref, computed, nextTick, watch, onMounted, onUnmounted } from "vue";
import { storeToRefs } from "pinia";
import { onLoad, onUnload, onHide,onShow } from "@dcloudio/uni-app";
import dayjs from "dayjs";
import { useIMStore } from "@/store/tim";
import useElder from "@/hooks/useElder";
import useUser from "@/hooks/useUser";
import {
  getPatientOrder,
  getMrtcConfig,
  notifyVideoRoomEnded,
  getRxMedicinePurchaseOrderId,
  getRxMedicineOrderStatus
} from "@/utils/api";
import { toast, loading as showLoading, hideLoading } from "@/utils/widget";
import formatMessageTime from "./formatMessageTime";

import fullPage from "@/components/full-page.vue";
import chatMessage from "./chat-message.vue";
import consultHead from "./consult-head.vue";
import consultCountdown from "@/components/consult-countdown.vue";
import inputBar from "./input-bar.vue";
import infoWindow from "./info-window.vue";

import ConsultMessageCustom from "@/components/custom-message/consult-message-custom.vue";

// 长辈模式状态
const { elderMode, elderVarStyle } = storeToRefs(useElder());
const { userInfo } = useUser();

const imStore = useIMStore();
const conversationID = ref("");
const scrollToMessageID = ref("");
const partnerInfo = ref(null);
const consult = ref(null);
const pageRef = ref();
const orderId = ref("");
const loading = ref(false);
const isCompleted = ref(false); // 是否已加载完所有历史消息
const networkAvailable = ref(true); // 网络状态
const isRefreshing = ref(false); // 下拉刷新状态
const pollingTimer = ref(null); // 轮询定时器
const reconnectAttempts = ref(0); // 重连尝试次数
const MAX_RECONNECT_ATTEMPTS = 5; // 最大重连次数
const POLLING_INTERVAL = 10000; // 轮询间隔 10 秒
const infoVisible = ref(false);

// 消息接收超时检测相关变量
const lastMessageTime = ref(Date.now()); // 最后一次收到消息的时间
const messageTimeoutTimer = ref(null); // 消息超时检测定时器
const messageReceiveTimeout = ref(false); // 是否消息接收超时
const MESSAGE_TIMEOUT = 30000; // 30秒无消息判定为超时
const orderRx = ref(null);
const footerBtnMode = ref('input'); // input settle

// 来电铃声（静态资源，支持循环播放；部分机型可能需要用户交互后才能播放）
let rtcRingtoneCtx = null;
function startRtcRingtone() {
  try {
    if (!uni || typeof uni.createInnerAudioContext !== "function") return;
    if (!rtcRingtoneCtx) {
      rtcRingtoneCtx = uni.createInnerAudioContext();
      rtcRingtoneCtx.loop = true;
      rtcRingtoneCtx.src = "/static/audio/phone_ringing.mp3";
    }
    if (typeof rtcRingtoneCtx.play === "function") {
      rtcRingtoneCtx.play();
    }
  } catch (e) {
    console.warn("[VIDEO][APP] startRtcRingtone failed", e);
  }
}

function stopRtcRingtone() {
  try {
    if (!rtcRingtoneCtx) return;
    if (typeof rtcRingtoneCtx.stop === "function") {
      rtcRingtoneCtx.stop();
    }
  } catch (e) {
    console.warn("[VIDEO][APP] stopRtcRingtone failed", e);
  }
}

// 音视频问诊相关状态
const rtcVisible = ref(false); // 兼容旧逻辑，当前不再控制界面显示
const rtcConnected = ref(false); // 是否已经接通
const rtcMinimized = ref(false); // 是否处于小窗模式（当前不再使用）
const rtcConfig = ref(null); // 当前通话使用的 Config
const rtcPendingConfig = ref(null); // 来电待接通时保存的 Config
const rtcPendingOrderId = ref(""); // 来电对应的订单号
const rtcSessionActive = ref(false); // 是否存在进行中/待接通的通话会话（用于兜底同步挂断）
const rtcCallMode = ref("join"); // 'start' | 'join'，默认患者加入房间
const rtcCurrentUserId = ref(""); // 当前用户在音视频服务中的 userId
const rtcCallDuration = ref(0); // 通话时长（秒）
let rtcDurationTimer = null;
const rtcMiniPosition = ref({ x: 12, y: 120 }); // 小窗位置（px）
const rtcDragging = ref(false);
const rtcDragStart = ref({ x: 0, y: 0, originX: 0, originY: 0 });
let rtcMiniBoundsInited = false;
const rtcMiniBounds = {
  maxX: 0,
  maxY: 0,
};
const RTC_MINI_WIDTH = 160; // px
const RTC_MINI_HEIGHT = 220; // px

// 通话时长展示
const rtcDurationText = computed(() => {
  const total = rtcCallDuration.value || 0;
  const minutes = String(Math.floor(total / 60)).padStart(2, "0");
  const seconds = String(total % 60).padStart(2, "0");
  return `${minutes}:${seconds}`;
});

// 小窗样式
const rtcMiniStyle = computed(() => ({
  top: `${rtcMiniPosition.value.y}px`,
  left: `${rtcMiniPosition.value.x}px`,
}));

// 规范化医生展示名称：避免显示类似 30127 这种纯工号
function normalizeDoctorName(raw) {
  const name = (raw || "").trim();
  if (!name) return "互联网医院医生";
  // 纯数字视为工号，用统一文案替代
  if (/^\d+$/.test(name)) return "互联网医院医生";
  return name;
}

// 来电界面展示的医生名称与医院名称
const doctorDisplayName = computed(() => {
  if (!consult.value) return "";
  const raw =
    consult.value.doctorName ||
    consult.value.doctorRealName ||
    consult.value.doctor ||
    "";
  return normalizeDoctorName(raw);
});

const doctorHospitalText = computed(() => {
  // 如后续有真实医院字段，可替换为 consult.value.xxx
  return "震元堂互联网医院";
});

// 视频问诊信令类型
const VIDEO_SIGNAL = {
  INVITE: "VIDEO_CONSULT_INVITE",
  CANCEL: "VIDEO_CONSULT_CANCEL",
  REJECT: "VIDEO_CONSULT_REJECT",
  ACCEPT: "VIDEO_CONSULT_ACCEPT",
  HANGUP: "VIDEO_CONSULT_HANGUP",
  BUSY: "VIDEO_CONSULT_BUSY",
};

function isHiddenRtcSignalMessage(msg) {
  try {
    if (!msg || msg.type !== "TIMCustomElem") return false;
    const p = msg.payload || {};
    if (p.description !== "VIDEO_CONSULT") return false;
    const ext = typeof p.extension === "string" ? p.extension.trim() : "";
    return !ext;
  } catch (e) {
    return false;
  }
}

// 消息列表：raw 用于业务处理，display 用于列表展示（过滤掉仅用于信令的空消息）
const messageListRaw = computed(() => imStore.messageList);
const messageList = computed(() => {
  const list = messageListRaw.value || [];
  return list.filter((m) => !isHiddenRtcSignalMessage(m));
});
const messageTime = computed(() =>
  messageList.value.reduce((acc, item, index) => {
    const preTime = messageList.value[index - 1]
      ? messageList.value[index - 1].time
      : 0;
    acc[item.ID] = formatMessageTime(item.time, preTime);
    return acc;
  }, {})
);

// 是否显示"查看更多"按钮
const isMore = computed(() => {
  return messageList.value.length >= 15 && !isCompleted.value;
});

// 监听收到的消息
watch(
  () => messageListRaw.value.length,
  async (newLength, oldLength) => {
    if (newLength > 0) {
      // 如果是新消息（消息长度增加）
      if (newLength > oldLength) {
        // 获取最新的一条消息
        const lastMessage = messageListRaw.value[newLength - 1];
        await scrollToLatestMessage();

        if (lastMessage && lastMessage.type === "TIMCustomElem") {
          handleCustomMessage(lastMessage);
          getOrderDetail();
        }

        // 成功接收到消息，重置重连尝试次数和更新最后消息时间
        reconnectAttempts.value = 0;
        lastMessageTime.value = Date.now();
        messageReceiveTimeout.value = false; // 重置超时状态
      }
    }
  }
);

const canSendMessage = computed(
  () => consult.value && !["cancelled", "finished"].includes(consult.value.orderStatus)
);

// 处理 TIM 自定义消息（包含视频问诊信令）
function handleCustomMessage(message) {
  const payload = message.payload || {};
  const type = payload.data;

  console.log("[VIDEO][APP] handleCustomMessage", {
    id: message && message.ID,
    type: message && message.type,
    payload,
  });

  if (!type) return;
  if (payload.description !== "VIDEO_CONSULT") return;
  // 只处理来自对端（医生）的信令，避免自己发送的信令触发本地逻辑
  if (message && message.flow && message.flow !== "in") return;

  switch (type) {
    case VIDEO_SIGNAL.INVITE:
      handleRtcIncomingInvite(payload);
      break;
    case VIDEO_SIGNAL.CANCEL:
      // 只有当前仍存在会话时才触发关闭，避免历史通话记录再次触发
      if (rtcSessionActive.value) {
        handleRtcRemoteHangup("通话已结束，返回聊天界面");
      }
      break;
    case VIDEO_SIGNAL.HANGUP:
      if (rtcSessionActive.value) {
        handleRtcRemoteHangup("通话已结束，返回聊天界面");
      }
      break;
    default:
      console.log("[VIDEO][APP] custom message not video signal", type);
      break;
  }
}


// 收到医生发起的视频问诊邀请
function handleRtcIncomingInvite(payload) {
  // 已有通话或待接通时通知医生忙线（不区分界面是否可见）
  if (rtcConnected.value || rtcPendingOrderId.value) {
    sendRtcSignal(VIDEO_SIGNAL.BUSY).catch((error) => {
      console.error("发送忙线信令失败:", error);
    });
    return;
  }

  // 使用当前页面的 orderId 记录待接通会话
  rtcPendingOrderId.value = orderId.value || "";
  rtcPendingConfig.value = null;
  rtcCallMode.value = "join";
  rtcSessionActive.value = true;
  // 不再自动接听，交给自研来电 UI 中的“接听/拒绝”按钮触发 handleRtcAccept/handleRtcReject
  startRtcRingtone();
}

// 发送视频问诊信令消息
const sendRtcSignal = async (signal) => {
  if (!conversationID.value) {
    console.warn("[VIDEO][APP] sendRtcSignal no conversationID", signal);
    return;
  }

  // 信令消息仅用于驱动通话状态，不在聊天列表中展示（通话记录由医生端统一发送）
  const extensionText = "";
  console.log("[VIDEO][APP] sendRtcSignal", {
    signal,
    conversationID: conversationID.value,
    extensionText,
  });

  try {
    await imStore.sendCustomMessage(
      {
        data: signal,
        extension: extensionText,
        description: "VIDEO_CONSULT",
      },
      conversationID.value
    );
  } catch (error) {
    console.error("发送视频问诊信令失败:", error);
  }
};

// 构建音视频通话 Config，补齐 displayInfo 等满足业务要求
function buildRtcConfig(baseConfig) {
  const config = { ...(baseConfig || {}) };

  // 基础必填参数：userId / appId
  if (!config.userId) {
    // 优先用当前通话 userId，否则用 IM 的 userId，再退回占位
    config.userId =
      rtcCurrentUserId.value ||
      (imStore.userInfo &&
        (imStore.userInfo.userID || imStore.userInfo.userId)) ||
      "mockUser";
  }
  if (!config.appId) {
    // 使用当前小程序 appId，来自 manifest.json mp-alipay.appid
    config.appId = "2021005110656858";
  }

  // 一些默认的媒体参数
  if (typeof config.resolution === "undefined") {
    // 2 = 1280x720，测试 720P 画质
    config.resolution = 2;
  }
  if (typeof config.fps === "undefined") {
    config.fps = 30;
  }

  // streamInfo 默认参数（只在缺失时补充，真实环境请用后端下发的参数覆盖）
  const streamInfo = config.streamInfo || {};
  streamInfo.serverUrl =
    streamInfo.serverUrl || "wss://cn-hangzhou-mrtc.cloud.alipay.com/ws";
  config.streamInfo = streamInfo;

  // 使用插件作为媒体组件：关闭接听页，自定义通话中控制按钮
  const displayInfo = config.displayInfo || {};
  displayInfo.showFullScreen = {
    visible: true, // 显示全部画面，不裁切
  };
  displayInfo.callPage = {
    ...(displayInfo.callPage || {}),
    // 关闭插件接听页，避免与自研来电弹窗冲突
    visible: false,
  };
  displayInfo.answer = {
    ...(displayInfo.answer || {}),
    // 默认全屏展示医生画面（player），本地画面（pusher）以小窗显示
    pusher: {
      visible: true,
      isMini: true,
      ...(displayInfo.answer && displayInfo.answer.pusher),
    },
    player: {
      visible: true,
      isMini: false,
      ...(displayInfo.answer && displayInfo.answer.player),
    },
    // 通话中按钮权限：只保留翻转摄像头和挂断，其余全部隐藏
    actions: {
      ...(displayInfo.answer && displayInfo.answer.actions),
      hangup: {
        ...(displayInfo.answer && displayInfo.answer.actions && displayInfo.answer.actions.hangup),
        visible: true,
      },
      mute: {
        visible: false,
      },
      screenshot: {
        visible: false,
      },
      enableCamera: {
        visible: false,
      },
      switchCamera: {
        ...(displayInfo.answer && displayInfo.answer.actions && displayInfo.answer.actions.switchCamera),
        visible: true,
      },
      switchScreenCapture: {
        visible: false,
      },
    },
    // 不展示插件自带的用户列表，避免在通话界面露出纯数字 uid（如 30127）
    users: {
      ...(displayInfo.answer && displayInfo.answer.users),
      visible: false,
    },
  };
  // 挂断后的 end 页面仅配置空文案，实际 UI 通过本地浮层控制，不再依赖插件页
  displayInfo.end = {
    ...(displayInfo.end || {}),
    visible: false,
    information: "视频问诊已结束，请返回聊天页面",
  };
  config.displayInfo = displayInfo;
  // 兼容文档中的 users_visible 开关，进一步关闭用户列表
  config.users_visible = false;

  config.controlInfo = {
    ...(config.controlInfo || {}),
    enableCamera: true,
  };
  // 启动时默认打开摄像头（对应文档中的 controlInfo_enableCamera）
  config.controlInfo_enableCamera = true;

  // 接听界面提示文案，使用医生名称
  if (consult.value) {
    const rawDoctorName =
      consult.value.doctorName ||
      consult.value.doctorRealName ||
      consult.value.doctor ||
      "";
    const doctorName = normalizeDoctorName(rawDoctorName);
    if (doctorName) {
      const text = `${doctorName}发起的视频问诊`;
      // 兼容 calling_information 与 displayInfo.calling.information 两种配置方式
      if (!config.calling_information) {
        config.calling_information = text;
      }
      config.displayInfo.calling = {
        ...(config.displayInfo.calling || {}),
        information: text,
      };
    }
  }

  return config;
}

// 启动通话时长计时
function startRtcDurationTimer() {
  stopRtcDurationTimer();
  rtcCallDuration.value = 0;
  rtcDurationTimer = setInterval(() => {
    rtcCallDuration.value += 1;
  }, 1000);
}

function stopRtcDurationTimer() {
  if (rtcDurationTimer) {
    clearInterval(rtcDurationTimer);
    rtcDurationTimer = null;
  }
}

// 初始化小窗边界与默认位置
function initRtcMiniBounds() {
  if (rtcMiniBoundsInited) return;
  try {
    const info = uni.getSystemInfoSync();
    rtcMiniBounds.maxX = Math.max(0, info.windowWidth - RTC_MINI_WIDTH - 12);
    rtcMiniBounds.maxY = Math.max(
      0,
      info.windowHeight - RTC_MINI_HEIGHT - 120
    );
    rtcMiniPosition.value = {
      x: rtcMiniBounds.maxX,
      y: rtcMiniBounds.maxY,
    };
    rtcMiniBoundsInited = true;
  } catch (error) {
    console.error("获取窗口信息失败:", error);
  }
}

// 结束通话统一清理
function endRtcSession() {
  stopRtcDurationTimer();
  rtcConnected.value = false;
  rtcMinimized.value = false;
  rtcPendingConfig.value = null;
  rtcPendingOrderId.value = "";
  rtcVisible.value = false;
  rtcConfig.value = null;
  rtcSessionActive.value = false;
  stopRtcRingtone();
}

// 页面加载
onLoad(async (options) => {
  uni.$on('rxHasAuditPassed', (rx) => {
    orderRx.value = rx;
    orderRx.value.btnText = '医保结算';
    footerBtnMode.value = 'settle';
    getMedicineOrderStatus()
  });
  if (!imStore.isLogin || !imStore.isSDKReady) {
    uni.reLaunch({
      url: "/pages/home/home",
    });
    return;
  }
  // 监听全局长辈模式变化事件

  orderId.value = options.orderId;
  getOrderDetail(true);
  conversationID.value = options.conversationID;

  // 监听网络状态
  startNetworkListener();

  try {
    // 进入会话
    await imStore.enterConversation(conversationID.value);

    // 获取对方信息
    if (conversationID.value.startsWith("C2C")) {
      const userID = conversationID.value.replace("C2C", "");
      try {
        const { data } = await imStore.tim.getUserProfile({
          userIDList: [userID],
        });
        if (data.length > 0) {
          partnerInfo.value = data[0];
        }
      } catch (error) {
        console.error("获取用户资料失败:", error);
        uni.showToast({
          title: "获取用户资料失败，请重试",
          icon: "none",
        });
      }
    }

    // 初始加载完成后，滚动到最新消息
    setTimeout(() => {
      scrollToLatestMessage();
    }, 500);

    // 启动轮询获取新消息
    startPollingMessages();

    // 启动消息超时检测
    startMessageTimeoutDetection();
  } catch (error) {
    console.error("聊天室初始化失败:", error);
    networkAvailable.value = false;
    uni.showToast({
      title: "聊天室初始化失败，请检查网络",
      icon: "none",
    });
  }
});

onShow(() => {
  getMedicineOrderStatus();
})

async function settleRx() {
  showLoading();
  const res = await getRxMedicinePurchaseOrderId({
    accountId: userInfo.value.userId,
    rpNo: orderRx.value.id
  });
  hideLoading()
  if (res && res.success) {
    if (res.status === 'unpay') {
      uni.navigateTo({
        url: `/pages/consult/drug-purchase-order/drug-purchase-order?id=${res.id}`
      })
    }
    else if (res.status === 'expired') {
      toast('订单已过期');
    }
    else {
      uni.navigateTo({
        url: `/pages/consult/drug-purchase-list/detail?id=${res.id}`
      })
    }
  } else {
    toast(res.message || '获取在线配药订单失败');
  }
}

async function getMedicineOrderStatus() {
  if (orderRx.value && orderRx.value.id) {
    const res = await getRxMedicineOrderStatus({
      accountId: userInfo.value.userId,
      id: orderRx.value.id
    });
    if (res && res.success) {
      const { expired, orderStatus } = res.data;
      if (!expired && ['none', 'unpay'].includes(orderStatus)) {
        orderRx.value.btnText = '医保结算';
      } else {
        orderRx.value.btnText = '查看订单';
      }
    }
  }

}

// 在页面挂载完成后也尝试滚动到底部
onMounted(() => {
  setTimeout(() => {
    scrollToLatestMessage();
  }, 1000);
});

// 页面卸载
onUnload(() => {
  uni.$off('rxHasAuditPassed');
  // 清空当前会话
  imStore.currentConversation = null;
  // 停止轮询
  stopPollingMessages();
  // 移除网络状态监听
  stopNetworkListener();
  // 停止消息超时检测
  stopMessageTimeoutDetection();
  // 结束可能存在的视频问诊：交由插件自身的 onHangup/onError 事件处理，不在页面卸载时强制挂断，
  // 避免与插件的接听/通话流程冲突导致刚接通就被立即挂断。
  endRtcSession();
});

// 页面隐藏或返回上一页时，也确保挂断并清理通话状态
onHide(() => {
  // 避免通话中页面隐藏导致状态被清空，从而无法处理“医生挂断”的同步信令
  if (!rtcSessionActive.value) {
    endRtcSession();
  }
});

// 组件销毁时清理
onUnmounted(() => {
  stopPollingMessages();
  stopNetworkListener();
  stopMessageTimeoutDetection();
  endRtcSession();
});

// 滚动到顶部时触发加载更多
const onScrollToUpper = () => {
  if (isMore.value && !loading.value) {
    loadMoreMessages();
  }
};

// 滚动到最新消息 - 改进版
const scrollToLatestMessage = async () => {
  await nextTick();

  return new Promise((resolve) => {
    setTimeout(() => {
      if (messageList.value.length > 0) {
        // 优先尝试滚动到底部元素
        scrollToMessageID.value = "msg-bottom";

        // 如果有消息，也可以尝试滚动到最后一条消息
        const lastMessage = messageList.value[messageList.value.length - 1];
        if (lastMessage) {
          scrollToMessageID.value = `msg-${lastMessage.ID}`;
        }

        // 使用 pageRef 的 scrollToBottom 方法作为备选
        if (pageRef.value && pageRef.value.scrollToBottom) {
          pageRef.value.scrollToBottom();
        }

        // 在小程序/app环境下，尝试使用uni的API滚动
        // #ifdef MP || APP-PLUS
        const query = uni.createSelectorQuery();
        query
          .select("#msg-bottom")
          .boundingClientRect((data) => {
            if (data) {
              uni.pageScrollTo({
                scrollTop: data.bottom,
                duration: 300,
              });
            }
          })
          .exec();
        // #endif
      }

      resolve();
    }, 100);
  });
};

// 加载更多消息
const loadMoreMessages = async () => {
  if (messageList.value.length === 0 || loading.value || isCompleted.value)
    return;

  loading.value = true;

  try {
    const firstMessage = messageList.value[0];
    const res = await imStore.getMessageList(
      conversationID.value,
      50,
      firstMessage.ID
    );

    // 更新是否已加载完所有消息的状态
    isCompleted.value = res.data?.isCompleted || false;

    if (res.data && res.data.messageList && res.data.messageList.length > 0) {
      // 滚动到新加载的第一条消息
      setTimeout(() => {
        const firstVisible = res.data.messageList.find((m) => !isHiddenRtcSignalMessage(m)) || res.data.messageList[0];
        if (firstVisible && firstVisible.ID) {
          scrollToMessageID.value = `msg-${firstVisible.ID}`;
        }
      }, 100);
    } else {
      // 没有更多消息了
      isCompleted.value = true;
      uni.showToast({
        title: "没有更多消息了",
        icon: "none",
      });
    }
  } catch (error) {
    console.error("加载更多消息失败:", error);
    uni.showToast({
      title: "加载失败，请重试",
      icon: "none",
    });
  } finally {
    loading.value = false;
  }
};

// 发送文本消息
const sendTextMessage = async (inputMessage) => {
  if (!inputMessage || inputMessage.trim() === "") return;

  try {
    await imStore.sendTextMessage(inputMessage, conversationID.value);
    // 发送成功后滚动到底部
    await scrollToLatestMessage();
  } catch (error) {
    console.error("发送文本消息失败:", error);
    uni.showToast({
      title: "发送失败",
      icon: "none",
    });
  }
};

// 选择图片
const chooseImage = (source) => {
  uni.chooseImage({
    count: 1,
    sizeType: ["compressed"],
    sourceType: [source],
    success: async (res) => {
      try {
        if (res.tempFiles && res.tempFiles.length > 0) {
          const file = res;
          await imStore.sendImageMessage(file, conversationID.value);
          // 发送成功后滚动到底部
          await scrollToLatestMessage();
        } else {
          uni.showToast({
            title: "未选择图片",
            icon: "none",
          });
        }
      } catch (error) {
        console.error("发送图片消息失败:", error);
        uni.showToast({
          title: "发送失败",
          icon: "none",
        });
      }
    },
  });
};

function viewSummary() {
  uni.setStorageSync("chat-room-consult", JSON.stringify(consult.value));
  uni.navigateTo({
    url: "/pages/record/disease-summary",
  });
}

function closeChat() {
  uni.reLaunch({
    url: "/pages/home/home",
  });
}

async function getOrderDetail(showInfoWindow = false) {
  const { success, data, message } = await getPatientOrder({
    orderId: orderId.value,
  });
  if (success) {
    consult.value = data;
    if (showInfoWindow) {
      judgeDisplayInfoWindow(data);
    }
  } else {
    consult.value = null;
  }
}

function judgeDisplayInfoWindow(order) {
  let list = [];
  try {
    let displayRecord = JSON.parse(uni.getStorageSync("info-window-display-record") || '[]');
    list = Array.isArray(displayRecord) ? displayRecord : [];
  } catch (e) { };
  const displayed = list.some(item => item.orderId === order.orderId && order.orderId);
  const shouldDisplay = ['pending', 'processing', 'completed'].includes(order.orderStatus);
  if (displayed || !shouldDisplay) return;
  const date = dayjs().format('YYYY-MM-DD');
  list.push({ date, orderId: order.orderId });
  uni.setStorageSync("info-window-display-record", JSON.stringify(list.filter(item => item.date === date)));
  infoVisible.value = true;
}

// 启动网络状态监听
const startNetworkListener = () => {
  uni.onNetworkStatusChange(({ isConnected }) => {
    networkAvailable.value = isConnected;

    if (isConnected) {
      // 网络恢复时自动重试连接
      retryConnection();
    } else {
      // 网络断开时停止轮询
      stopPollingMessages();
      uni.showToast({
        title: "网络连接已断开",
        icon: "none",
      });
    }
  });

  // 初始检查网络状态
  uni.getNetworkType({
    success: ({ networkType }) => {
      networkAvailable.value = networkType !== "none";
    },
  });
};

// 停止网络状态监听
const stopNetworkListener = () => {
  uni.offNetworkStatusChange();
};

// 启动轮询获取新消息
const startPollingMessages = () => {
  // 清除可能存在的旧定时器
  stopPollingMessages();

  // 创建新的轮询定时器
  pollingTimer.value = setInterval(async () => {
    if (networkAvailable.value && conversationID.value) {
      try {
        // 刷新消息列表
        await imStore.enterConversation(conversationID.value);

        // 检查是否长时间没有新消息
        checkMessageReceiveTimeout();
      } catch (error) {
        console.error("轮询获取消息失败:", error);
        reconnectAttempts.value++;

        if (reconnectAttempts.value >= MAX_RECONNECT_ATTEMPTS) {
          stopPollingMessages();
          networkAvailable.value = false;
          uni.showToast({
            title: "消息同步失败，请手动刷新",
            icon: "none",
          });
        }
      }
    }
  }, POLLING_INTERVAL);
};

// 停止轮询
const stopPollingMessages = () => {
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value);
    pollingTimer.value = null;
  }
};

// 重试连接
const retryConnection = async () => {
  uni.showLoading({ title: "正在重新连接..." });

  try {
    // 检查网络状态
    const { networkType } = await new Promise((resolve) => {
      uni.getNetworkType({ success: resolve });
    });

    if (networkType !== "none") {
      networkAvailable.value = true;

      // 重新初始化 IM 连接
      if (!imStore.isSDKReady || !imStore.isLogin) {
        await imStore.initTIM();
      }

      // 重新进入会话
      await imStore.enterConversation(conversationID.value);

      // 重新获取订单信息
      await getOrderDetail();

      // 重新启动轮询
      startPollingMessages();

      // 重新启动消息超时检测
      startMessageTimeoutDetection();

      // 重置状态
      reconnectAttempts.value = 0;
      messageReceiveTimeout.value = false;

      uni.showToast({
        title: "连接已恢复",
        icon: "success",
      });
    } else {
      networkAvailable.value = false;
      uni.showToast({
        title: "网络连接失败，请检查网络设置",
        icon: "none",
      });
    }
  } catch (error) {
    console.error("重连失败:", error);
    networkAvailable.value = false;
    uni.showToast({
      title: "重连失败，请稍后再试",
      icon: "none",
    });
  } finally {
    uni.hideLoading();
  }
};

// 下拉刷新处理
const onRefresh = async () => {
  isRefreshing.value = true;

  try {
    // 尝试重新连接并刷新消息
    await retryConnection();

    // 再次获取消息列表
    await imStore.enterConversation(conversationID.value);

    uni.showToast({
      title: "刷新成功",
      icon: "success",
    });
  } catch (error) {
    console.error("刷新失败:", error);
    uni.showToast({
      title: "刷新失败，请重试",
      icon: "none",
    });
  } finally {
    isRefreshing.value = false;
  }
};

// 启动消息超时检测
const startMessageTimeoutDetection = () => {
  // 停止可能存在的旧定时器
  stopMessageTimeoutDetection();

  // 设置新消息的最后接收时间
  lastMessageTime.value = Date.now();

  // 创建新的检测定时器
  messageTimeoutTimer.value = setInterval(() => {
    checkMessageReceiveTimeout();
  }, MESSAGE_TIMEOUT / 2); // 每隔半个超时时间检查一次
};

// 停止消息超时检测
const stopMessageTimeoutDetection = () => {
  if (messageTimeoutTimer.value) {
    clearInterval(messageTimeoutTimer.value);
    messageTimeoutTimer.value = null;
  }
};

// 检查消息接收是否超时
const checkMessageReceiveTimeout = () => {
  // 只有在网络可用但长时间没收到消息的情况下才判定为超时
  if (
    networkAvailable.value &&
    Date.now() - lastMessageTime.value > MESSAGE_TIMEOUT
  ) {
    messageReceiveTimeout.value = true;
    console.log("消息接收超时，可能需要重连");
  }
};

// 处理消息超时
const handleMessageTimeout = async () => {
  uni.showLoading({ title: "正在重新连接..." });

  try {
    // 重新进入会话获取最新消息
    await imStore.enterConversation(conversationID.value);

    // 更新最后消息时间
    lastMessageTime.value = Date.now();

    // 重置超时状态
    messageReceiveTimeout.value = false;

    uni.showToast({
      title: "连接已恢复",
      icon: "success",
    });
  } catch (error) {
    console.error("重连失败:", error);
    uni.showToast({
      title: "重连失败，请稍后再试",
      icon: "none",
    });

    // 如果连续失败次数过多，可能是网络问题
    reconnectAttempts.value++;
    if (reconnectAttempts.value >= MAX_RECONNECT_ATTEMPTS) {
      networkAvailable.value = false;
    }
  } finally {
    uni.hideLoading();
  }
};
</script>

<style>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.message-scroll-view {
  height: 100%;
  width: 100%;
}

.chat-header {
  height: 90rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #eee;
  background-color: #fff;
}

.title {
  font-size: 34rpx;
  font-weight: bold;
}

.message-list {
  flex: 1;
  padding: 20rpx;
  background-color: #f5f5f5;
}

.message-item {
  display: flex;
  margin-bottom: 30rpx;
}

.message-item.self {
  flex-direction: row-reverse;
}

.avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  margin: 0 20rpx;
}

.message-content {
  max-width: 60%;
}

.text-message {
  background-color: #fff;
  padding: 20rpx;
  border-radius: 10rpx;
  word-break: break-all;
}

.message-item.self .text-message {
  background-color: #95ec69;
}

.image-message {
  background-color: #fff;
  padding: 10rpx;
  border-radius: 10rpx;
  overflow: hidden;
}

.image-message image {
  max-width: 100%;
  border-radius: 5rpx;
}

.unsupported-message {
  background-color: #fff;
  padding: 20rpx;
  border-radius: 10rpx;
  color: #999;
}

.input-area {
  display: flex;
  padding: 20rpx;
  background-color: #f5f5f5;
  border-top: 1px solid #eee;
}

.input-box {
  flex: 1;
  display: flex;
  background-color: #fff;
  border-radius: 10rpx;
  padding: 0 20rpx;
  align-items: center;
}

input {
  flex: 1;
  height: 80rpx;
}

.tools {
  display: flex;
}

.tool-item {
  padding: 0 20rpx;
  font-size: 40rpx;
}

.send-btn {
  width: 120rpx;
  height: 80rpx;
  margin-left: 20rpx;
  background-color: #07c160;
  color: #fff;
  font-size: 28rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10rpx;
}

.time-message {
  font-size: 24rpx;
  color: 999;
  padding: 24rpx 30rpx;
  text-align: center;
}

.system-message {
  font-size: 28rpx;
  color: #666;
  padding: 24rpx 30rpx;
  text-align: center;
  background-color: rgba(0, 0, 0, 0.05);
  border-radius: 10rpx;
  margin-bottom: 20rpx;
}

.system-message:active {
  background-color: rgba(0, 0, 0, 0.1);
}

.network-error {
  width: 100%;
  background-color: rgba(255, 0, 0, 0.1);
  z-index: 100;
  padding: 20rpx;
  box-sizing: border-box;
  /* 取消fixed定位，改用相对定位 */
  position: relative;
}

.network-error-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #fff1f0;
  border: 1px solid #ffccc7;
  border-radius: 8rpx;
  padding: 20rpx 30rpx;
  flex-wrap: nowrap;
}

.retry-btn {
  background-color: #ff4d4f;
  color: white;
  font-size: 24rpx;
  padding: 12rpx 24rpx;
  margin-left: 20rpx;
  border-radius: 8rpx;
  line-height: 1.4;
  min-width: 100rpx;
  white-space: nowrap;
  border: none;
  display: inline-block;
  text-align: center;
  flex-shrink: 0;
}

.message-timeout-error {
  width: 100%;
  background-color: rgba(255, 165, 0, 0.1);
  z-index: 100;
  padding: 20rpx;
  box-sizing: border-box;
  position: relative;
}

.message-timeout-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #fff7e6;
  border: 1px solid #ffe7ba;
  border-radius: 8rpx;
  padding: 20rpx 30rpx;
  flex-wrap: nowrap;
}

.message-timeout-error .retry-btn {
  background-color: #fa8c16;
}

/* 长辈模式样式 */
.text--elder {
  font-size: 32rpx !important;
  /* 28rpx * 1.14 */
  font-weight: 500 !important;
}

.message-container--elder {
  padding: 28rpx 40rpx !important;
  /* 增加内边距 */
}

.system-message--elder {
  font-size: 36rpx !important;
  /* 28rpx * 1.3 */
  padding: 32rpx 40rpx !important;
  /* 增加内边距 */
  border-radius: 12rpx !important;
  font-weight: 500 !important;
}

.time-message--elder {
  font-size: 30rpx !important;
  /* 24rpx * 1.25 */
  padding: 30rpx 40rpx !important;
  font-weight: 500 !important;
}

.message-li--elder {
  margin-bottom: 40rpx !important;
  /* 增加消息间距 */
}

.network-error--elder {
  padding: 28rpx !important;
}

.network-error-content--elder {
  padding: 28rpx 40rpx !important;
  border-radius: 12rpx !important;
}

.message-timeout-error--elder {
  padding: 28rpx !important;
}

.message-timeout-content--elder {
  padding: 28rpx 40rpx !important;
  border-radius: 12rpx !important;
}

.retry-btn--elder {
  font-size: 30rpx !important;
  /* 24rpx * 1.25 */
  padding: 18rpx 40rpx !important;
  /* 增加按钮内边距 */
  border-radius: 12rpx !important;
  line-height: 1.4 !important;
  font-weight: bold !important;
  min-width: 140rpx !important;
  white-space: nowrap !important;
  text-align: center !important;
  flex-shrink: 0 !important;
}

.bg-light-gray {
  background: #f0f0f0;
}
</style>
