<template>
  <div
    class="container"
    :style="{ height: `calc(100% - ${currentBottomHeight}px)` }"
  >
    <div class="chat-bg"></div>
    <!-- 顶部导航 -->
    <div class="header-chat">
      <svg-icon class="page-icon" name="lf-arrow" @click="goBack" />
      <div class="header-title">群聊2（{{ wsStore.messages.length }}）</div>
      <svg-icon class="page-icon" name="more" @click="goDetail" />
    </div>

    <!-- 聊天消息区域 -->
    <div class="chat-list" ref="chatListRef">
      <div v-for="(item, index) in wsStore.messages" :key="index">
        <div class="chat-time">
          {{ formatTime(item.timestamp || Date.now()) }}
        </div>
        <div class="box">
          <div
            class="list-item"
            :class="isSender(item.toUsername) ? '' : 'flex-reverse'"
          >
            <!-- 头像 -->
            <van-image
              class="list-img"
              :class="isSender(item.toUsername) ? 'mr12' : 'ml12'"
              round
              :src="item.avatar"
              @click="router.push('personal')"
            />
            <!-- 内容 -->
            <div class="list-cont">
              <div>{{ item.fromUsername || "匿名用户" }}</div>

              <!-- 文本消息 -->
              <div class="content" v-if="item.contentType === MSG_TYPE.TEXT">
                {{ item.content }}
              </div>

              <!-- 图片消息 -->
              <div
                class="img-message"
                v-else-if="item.contentType === MSG_TYPE.IMAGE"
              >
                <van-image
                  :src="item?.localUrl || IM_PATH + item.url"
                  style="max-width: 120px; border-radius: 8px"
                  @click="previewImage(item)"
                />
              </div>

              <!-- 名片消息 -->
              <div
                class="content card-message"
                v-else-if="item.contentType === 3"
              >
                <div class="card-title">名片</div>
                <div class="card-name">{{ item.content }}</div>
              </div>

              <!-- 录音消息 -->
              <div
                class="audio-message"
                v-else-if="item.contentType === MSG_TYPE.AUDIO"
              >
                <!-- <audio
                  v-if="item.localUrl"
                  :src="item.localUrl"
                  controls
                  style="width: 200px"
                />
                <audio
                  v-else
                  :src="IM_PATH + item.url"
                  controls
                  style="width: 200px"
                /> -->
                <messageAudio
                  :src="item?.localUrl || IM_PATH + item.url"
                  :isSender="isSender(item.toUsername)"
                />
              </div>

              <!-- 其他未知类型 -->
              <div class="content" v-else>[未知消息类型]</div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 输入框 -->
    <div class="page-foot">
      <div class="flex-box">
        <svg-icon
          type="button"
          class="page-icon"
          name="voice"
          @mousedown="startAudio"
          @touchstart="startAudio"
          @mouseup="sendAudioMessage"
          @touchend="sendAudioMessage"
        />
        <van-field
          rows="1"
          type="textarea"
          :border="false"
          autosize
          class="input"
          v-model="text"
          @focus="onFocus"
          placeholder="输入文本"
          @keyup.enter="sendMessage"
        />
        <svg-icon
          class="page-icon mr12 emoji-toggle"
          name="emoji"
          @click="toggleAppBox(1)"
        />
        <svg-icon
          class="page-icon tools-toggle"
          name="add2"
          @click="toggleAppBox(2)"
        />
      </div>

      <!-- 表情面板 -->
      <div
        class="app-box"
        v-show="showEmoji"
        :style="{ height: `${appBoxHeight}px` }"
        ref="emojiRef"
      >
        😀 😃 😄 😁 😆 😅 😂 🤣 😊 😇 🙂 🙃 😉 😌 😍
      </div>

      <!-- 工具栏面板 -->
      <div
        class="app-box"
        v-show="showTools"
        :style="{ height: `${appBoxHeight}px` }"
        ref="toolsRef"
      >
        <div class="tool-btn">
          <van-uploader :after-read="afterRead" :before-read="beforeRead">
            <svg-icon class="tool-icon" name="tp" />
          </van-uploader>
          <div>图片</div>
        </div>
        <div class="tool-btn">
          <svg-icon class="tool-icon" name="ps" />
          <div>拍摄</div>
        </div>
        <div class="tool-btn">
          <svg-icon class="tool-icon" name="yyth" @click="startAudioOnline" />
          <div>语音通话</div>
        </div>
        <div class="tool-btn">
          <svg-icon class="tool-icon" name="spth" />
          <div>视频通话</div>
        </div>
        <div class="tool-btn">
          <svg-icon class="tool-icon" name="mp" />
          <div>名片</div>
        </div>
      </div>
    </div>
    <CallController
      :visible="rtcStore.imSate.videoCallModal"
      :inCall="inCall"
      :callName="rtcStore.imSate.callName"
      :callAvatar="rtcStore.imSate.callAvatar"
      @accept="acceptCall"
      @reject="rejectCall"
      @hangup="hangupCall"
    ></CallController>
    <!-- 来电弹窗 -->
    <!-- <div v-if="rtcStore.imSate.videoCallModal && !inCall" class="call-modal">
      <p>{{ rtcStore.imSate.callName }} 正在呼叫你</p>
      <button @click="acceptCall">接听</button>
      <button @click="rejectCall">拒接</button>
    </div> -->

    <!-- 通话中显示挂断按钮 -->
    <!-- <div v-if="inCall" class="call-modal">
      <p>与 {{ rtcStore.imSate.callName }} 通话中...</p>
      <button @click="hangupCall">挂断</button>
    </div> -->
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, onBeforeUnmount } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useWebSocketStore } from "@/stores/modules/webSocketStore.js";
import { useWalletStore } from "@/stores/modules/walletStore.js";
import { Keyboard } from "@capacitor/keyboard";
import { Capacitor } from "@capacitor/core";
import { MSG_TYPE, MESSAGE_TYPE_USER } from "@/common/constant/msgType";
import messageAudio from "@/views/im/components/messageAudio/index.vue";
import { showToast, showImagePreview } from "vant";
import { useWebRTCStore } from "@/stores/modules/webrtcStore";
import CallController from "@/views/im/components/CallController/index.vue";
import * as Constant from "@/common/constant/Constant";

const IM_PATH = import.meta.env.VITE_IM_PATH_FIlE;
// 路由 & store
const router = useRouter();
const route = useRoute();
const wsStore = useWebSocketStore();
const walletStore = useWalletStore();
const rtcStore = useWebRTCStore();

// 输入框文本
const text = ref("");

// 状态管理
const keyboardHeight = ref(0);
const showEmoji = ref(false);
const showTools = ref(false);
const appBoxHeight = ref(210);
const chatListRef = ref(null);
const emojiRef = ref(null);
const toolsRef = ref(null);
const inCall = ref(false); // 是否处于通话中

// 示例用户
const currentUser = ref({
  avatar: "https://example.com/avatar.jpg",
  nickname: "张三",
});

const isSender = (toUsername) => {
  return walletStore.account === toUsername;
};

// 滚动到底部
const scrollToBottom = () => {
  nextTick(() => {
    if (chatListRef.value) {
      const el = chatListRef.value;
      el.scrollTop = el.scrollHeight;
    }
  });
};

watch(
  () => wsStore.messages.length,
  () => {
    scrollToBottom();
  }
);

// 平台判断
const isMobile = Capacitor.getPlatform() !== "web";

// 语音
const isTouchDevice = ref(false);
const mediaRecorder = ref(null); // 录音对象
const audioChunks = ref([]); // 录音数据

// 计算当前底部总高度
const currentBottomHeight = computed(() => {
  if (keyboardHeight.value > 0) return keyboardHeight.value;
  if (showEmoji.value || showTools.value) return appBoxHeight.value;
  return 0;
});

// 切换表情/工具面板
const toggleAppBox = async (type) => {
  if (isMobile) await Keyboard.hide();
  keyboardHeight.value = 0;
  if (type === 1) {
    showEmoji.value = !showEmoji.value;
    showTools.value = false;
  } else {
    showTools.value = !showTools.value;
    showEmoji.value = false;
  }
  scrollToBottom();
};

// 预览图片
const previewImage = (item) => {
  const imageList = wsStore.messages
    .filter((m) => m.contentType === MSG_TYPE.IMAGE)
    .map((m) => m.localUrl || IM_PATH + m.url);

  const index = imageList.findIndex(
    (url) => url === (item.localUrl || IM_PATH + item.url)
  );

  showImagePreview({
    images: imageList,
    startPosition: index,
  });
};

const onFocus = () => {
  // 隐藏所有面板
  showEmoji.value = false;
  showTools.value = false;
  if (isMobile) setupKeyboardListeners();
  scrollToBottom();
};

// 键盘监听
const setupKeyboardListeners = async () => {
  Keyboard.addListener("keyboardWillShow", (info) => {
    keyboardHeight.value = info.keyboardHeight;
  });

  Keyboard.addListener("keyboardWillHide", () => {
    keyboardHeight.value = 0;
  });
};

// 录音
const startAudio = async (event) => {
  if (event.type === "touchstart") {
    isTouchDevice.value = true;
  }

  // 如果是触摸设备且事件是鼠标事件，则忽略
  if (isTouchDevice.value && event.type === "mousedown") {
    return;
  }
  try {
    // 请求麦克风权限
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });

    // 创建 MediaRecorder 实例
    mediaRecorder.value = new MediaRecorder(stream, {
      mimeType: "audio/webm; codecs=opus",
    });

    // 收集音频数据
    mediaRecorder.value.ondataavailable = (e) => {
      audioChunks.value.push(e.data);
    };

    mediaRecorder.value.start(1000); // 每1秒收集一次数据
    console.log("Recording started");
  } catch (error) {
    console.error("Error accessing microphone:", error);
  }
};
// 停止录音
const stopRecording = async () => {
  return new Promise(async (resolve) => {
    if (!mediaRecorder.value) {
      resolve(new Uint8Array());
      return;
    }
    // 停止录音
    mediaRecorder.value.stop();
    mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());

    // 等待最后的数据可用
    mediaRecorder.value.onstop = async () => {
      // 合并所有音频片段
      const audioBlob = new Blob(audioChunks.value, { type: "audio/webm" });
      // 转换为 Uint8Array
      const arrayBuffer = await audioBlob.arrayBuffer();
      const audioData = new Uint8Array(arrayBuffer);

      resolve(audioData);
    };
  });
};

// 发送音频消息
const sendAudioMessage = async (event) => {
  if (isTouchDevice.value && event.type === "mouseup") {
    return;
  }
  console.log("发送音频消息");
  try {
    // 1. 停止录音并获取音频数据
    const audioData = await stopRecording();

    // 2. 准备消息体
    const message = {
      content: text.value, // 如果有文本内容
      contentType: MSG_TYPE.AUDIO, // 音频消息类型
      messageType: MESSAGE_TYPE_USER, // 单聊消息

      fileSuffix: "wav", // 使用webm后缀更准确
      file: audioData, // 将Uint8Array转为普通数组
    };

    // 3. 通过WebSocket发送
    wsStore.sendMessage(message);

    // 4. 重置状态
    mediaRecorder.value = null;
    audioChunks.value = [];
  } catch (error) {
    console.error("Error sending audio message:", error);
  }
};
// 发送消息
const sendMessage = () => {
  if (!text.value.trim()) return;
  const message = {
    content: text.value,
    contentType: MSG_TYPE.TEXT, // 1: 文本消息
    messageType: MESSAGE_TYPE_USER, // 1: 单聊天
  };
  wsStore.sendMessage(message);
  text.value = "";
  scrollToBottom();
};

// 发送图片消息
const afterRead = async (file) => {
  const arrayBuffer = await file.file.arrayBuffer();
  const message = {
    content: text.value, // 如果有文本内容
    contentType: MSG_TYPE.IMAGE, // 音频消息类型
    messageType: MESSAGE_TYPE_USER, // 单聊消息
    fileSuffix: file.type, // 使用webm后缀更准确
    file: new Uint8Array(arrayBuffer), // 将Uint8Array转为普通数组
  };

  wsStore.sendMessage(message);
};
// 图片类型
const beforeRead = (file) => {
  const realFile = file.file || file;
  const type = realFile.type;
  const name = realFile.name || "";

  if (type === "image/svg+xml" || name.endsWith(".svg")) {
    showToast("不支持上传 SVG 格式的图片");
    return false;
  }
  return true;
};

//  创建呼叫:开启语音电话: 调试用，正式逻辑读src/views/im/hook/messagesHook.js
// ==== 1. 发起语音通话 ====
const startAudioOnline = async () => {
  inCall.value = true;
  rtcStore.imSate.videoCallModal = true;
  rtcStore.imSate.callAvatar = wsStore.toUserInfo.avatar;
  wsStore.sendMessage({
    messageType: MESSAGE_TYPE_USER, // 单聊消息
    contentType: Constant.DIAL_AUDIO_ONLINE,
    type: Constant.MESSAGE_TRANS_TYPE,
    avatar: walletStore.avatar,
  });
};
// ==== 2. 接听来电 ====
async function acceptCall() {
  try {
    // 标记为通话中状态
    inCall.value = true;

    // 发送接听消息给对方
    wsStore.sendMessage({
      messageType: MESSAGE_TYPE_USER, // 单聊消息
      contentType: Constant.ACCEPT_AUDIO_ONLINE, // 接听语音通话的消息类型
      type: Constant.MESSAGE_TRANS_TYPE, // webrtc类型
    });

    // 这里你可以加上开启 WebRTC 连接或媒体流处理逻辑
    // 例如调用 rtcStore 的方法，启动本地音频/视频流
    // await rtcStore.startLocalAudio();
  } catch (error) {
    console.error("接听失败", error);
    // 如果接听失败，考虑重置状态或提示用户
    inCall.value = false;
  }
}

// ==== 3. 拒接来电 ====
function rejectCall() {
  wsStore.sendMessage({
    messageType: MESSAGE_TYPE_USER, // 单聊消息
    contentType: Constant.REJECT_AUDIO_ONLINE,
    type: Constant.MESSAGE_TRANS_TYPE,
  });
  // 隐藏弹窗
  rtcStore.imSate.videoCallModal = false;
  inCall.value = false;
}

// ==== 4. 挂断通话 ====
function hangupCall() {
  rtcStore.cleanup();
  // 隐藏弹窗
  rtcStore.imSate.videoCallModal = false;
  inCall.value = false;
  wsStore.sendMessage({
    messageType: MESSAGE_TYPE_USER, // 单聊消息
    contentType: Constant.CANCELL_AUDIO_ONLINE,
    type: Constant.MESSAGE_TRANS_TYPE,
  });
}

// 时间格式化
const formatTime = (timestamp) => {
  const date = new Date(timestamp);
  const h = date.getHours().toString().padStart(2, "0");
  const m = date.getMinutes().toString().padStart(2, "0");
  return `${h}:${m}`;
};

// 页面生命周期
onMounted(() => {
  wsStore.toUserInfo.uuid = route.query.uuid;
  wsStore.getMessages({
    uuid: walletStore.account,
    messageType: 1,
    friendUsername: route.query.uuid,
  });
  scrollToBottom();
  document.addEventListener("click", handleClickOutside);
});

onUnmounted(() => {
  if (isMobile) Keyboard.removeAllListeners();
});
onBeforeUnmount(() => {
  document.removeEventListener("click", handleClickOutside);
});

// 判断是否点击在元素外
const handleClickOutside = (event) => {
  const emojiEl = emojiRef.value;
  const toolsEl = toolsRef.value;
  const target = event.target;

  if (
    showEmoji.value &&
    emojiEl &&
    !emojiEl.contains(target) &&
    !target.closest(".emoji-toggle")
  ) {
    showEmoji.value = false;
  }

  if (
    showTools.value &&
    toolsEl &&
    !toolsEl.contains(target) &&
    !target.closest(".tools-toggle")
  ) {
    showTools.value = false;
  }
};

// 页面跳转
const goBack = () => router.push("im");
const goDetail = () => router.push("detail");
</script>

<style lang="less" scoped>
.mr12 {
  margin-right: 12px;
}
.ml12 {
  margin-left: 12px;
}
.text-right {
  text-align: right;
}
.page-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
}
.container {
  display: flex;
  flex-direction: column;
  .chat-bg {
    height: 126px;
    background: linear-gradient(90deg, @theme-color1 0%, #40a4fb 100%);
    position: absolute;
    left: 0;
    right: 0;
    z-index: -1;
  }
  .header-chat {
    padding-top: 56px;
    margin: 0 16px;
    display: flex;
    align-items: center;
    color: @theme-color1;
    .header-title {
      flex: 1;
      font-family:
        PingFang SC,
        PingFang SC;
      font-weight: 500;
      font-size: 19px;
      color: #ffffff;
      text-align: center;
    }
  }
  .chat-list {
    background: #f7f8fa;
    border-radius: 30px 30px 0 0;
    flex: 1;
    overflow: auto;
    margin-top: 20px;
    padding: 0 16px 24px;
    .chat-time {
      font-family:
        PingFang SC,
        PingFang SC;
      font-weight: 400;
      font-size: 12px;
      color: #8d8d8d;
      text-align: center;
      margin: 20px 0;
    }
    .box {
      .list-item {
        display: flex;
        margin-bottom: 24px;
        .list-img {
          width: 44px;
          height: 44px;
          flex-shrink: 0;
        }
        .list-cont {
          font-family:
            PingFang SC,
            PingFang SC;
          font-weight: 400;
          font-size: 12px;
          color: #8d8d8d;
          max-width: 70%;
          display: flex;
          flex-direction: column;
          align-items: flex-start;
          .business-card {
            width: 199px;
            height: 93px;
            background: #ffffff;
            border-radius: 10px;
            margin-top: 8px;
            padding: 10px;
            box-sizing: border-box;
            .business-card-cont {
              display: flex;
              align-items: center;
              font-family:
                PingFang SC,
                PingFang SC;
              font-weight: 400;
              font-size: 15px;
              color: #000000;
            }
            .line {
              height: 1px;
              background: #f2f2f2;
              margin: 10px 0 6px;
            }
            .business-card-text {
              font-family:
                PingFang SC,
                PingFang SC;
              font-weight: 400;
              font-size: 10px;
              color: #8d8d8d;
            }
          }
          .content {
            background: #ffffff; // 对方消息背景白色
            color: #000;
            border-radius: 10px;
            margin-top: 8px;
            padding: 8px 17px;
            word-break: break-word;
            white-space: pre-wrap;
            max-width: 100%;
            font-family:
              PingFang SC,
              PingFang SC;
            font-weight: 400;
            font-size: 15px;
          }
          .img-message {
            margin-top: 8px;
          }
        }
      }
      .withdrawal {
        display: flex;
        justify-content: center;
        margin-bottom: 24px;
        .withdrawal-text {
          width: 142px;
          height: 29px;
          line-height: 29px;
          box-sizing: border-box;
          background: #f2f2f2;
          border-radius: 4px;
          font-family:
            PingFang SC,
            PingFang SC;
          font-weight: 400;
          font-size: 12px;
          color: #8d8d8d;
          text-align: center;
        }
      }
      .flex-reverse {
        flex-direction: row-reverse;
      }
      .flex-reverse .list-cont {
        align-items: flex-end;
        .content {
          background: #4d71ff; // 自己的消息是蓝色
          color: #ffffff; // 白字
        }
      }
    }
  }
  .chat-list::-webkit-scrollbar {
    width: 0;
  }
  .page-foot {
    position: relative;
    background-color: #fff;
    .flex-box {
      padding: 8px 16px;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      .input {
        flex: 1;
        background: #f2f2f2;
        border-radius: 17px;
        border: 1px solid #d8d8d8;
        padding: 6px 16px;
        font-weight: 500;
        font-size: 15px;
        margin: 0 12px;
        overflow-y: auto;
      }
    }
  }
}
.app-box {
  position: fixed;
  bottom: 210px;
  left: 0;
  right: 0;
  background: white;
  transition: transform 0.3s ease;
  transform: translateY(100%);
  display: flex;
  flex-wrap: wrap;
  padding: 10px 0 0 32px;

  &.visible {
    transform: translateY(0);
  }
  .tool-btn {
    margin-right: 32px;
    display: flex;
    flex-direction: column;
    align-items: center;
    font-family:
      PingFang SC,
      PingFang SC;
    font-weight: 400;
    font-size: 12px;
    color: #000000;
    .tool-icon {
      width: 56px;
      height: 56px;
      margin-bottom: 4px;
    }
  }
}

.page-foot {
  position: relative;
  z-index: 10; /* 确保输入框在上层 */
}
</style>
