<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import BowTarget from "@/components/BowTarget.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import BattleHeader from "@/components/BattleHeader.vue";
import PlayerScore from "@/components/PlayerScore.vue";
import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import TestDistance from "@/components/TestDistance.vue";
import SModal from "@/components/SModal.vue";
import audioManager from "@/audioManager";
import { getBattleAPI, laserCloseAPI } from "@/apis";
import { MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user, online } = storeToRefs(store);
const title = ref("");
const start = ref(null);
const battleId = ref("");
/** 对战模式：1=好友约战 2=排位赛，用于结算页跳转判断 */
const way = ref(0);
const currentRound = ref(1);
const tips = ref("即将开始...");
const players = ref([]);
const playersSorted = ref([]);
const playersScores = ref([]);
const halfTimeTip = ref(false);
const halfRest = ref(false);
/** 控制设备离线提示弹窗的显示状态 */
const showOfflineModal = ref(false);

/**
 * 监听设备在线状态，大乱斗比赛进行中设备离线时弹窗提示用户
 */
watch(online, (newVal, oldVal) => {
  if (!newVal && oldVal && start.value === true) {
    showOfflineModal.value = true;
  }
});

function recoverData(battleInfo, { force = false } = {}) {
  if (!battleInfo) return;
  try {
    if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
    if (battleInfo.way === 2) title.value = "排位赛 - 大乱斗";
    // 保存 way 供结算跳转时使用
    way.value = battleInfo.way ?? 0;
    
    // 优先使用接口数据，否则使用缓存
    if (battleInfo.teams?.[0]?.players) {
      players.value = [...battleInfo.teams[0].players];
    } else {
      // 大乱斗可能存的是 players 列表
      // 这里的缓存逻辑根据 AboutToStart 消息结构可能不同，假设也是 teams[0]
      // 如果是从 match-page 过来的，match-page 只存了 teams[1] 和 [2] 给对抗模式
      // 大乱斗的匹配逻辑可能不同，暂时保持原样，只做安全保护
      players.value = []; 
    }
    
    start.value = battleInfo.status !== 0;

    if (battleInfo.status === 0) {
      const readyRemain = (Date.now() - (battleInfo.createTime || Date.now())) / 1000;
      if (readyRemain > 0 && readyRemain < 15) {
        setTimeout(() => uni.$emit("update-timer", 15 - readyRemain - 0.2), 200);
      }
      return;
    }

    tips.value =
      (battleInfo.rounds.length !== 2 ? "上" : "下") + "半场：请先射6箭";
    playersScores.value = battleInfo.rounds.map((r) => ({ ...r.shoots }));
    const totals = {};
    players.value.forEach((p) => {
      const total = playersScores.value.reduce((acc, round) => {
        const arr = round[p.id] || [];
        return acc + arr.length;
      }, 0);
      totals[p.id] = total;
    });
    playersSorted.value = players.value.slice().sort((a, b) => {
      return totals[b.id] - totals[a.id];
    });
    if (battleInfo.status === 3) {
      halfTimeTip.value = true;
      halfRest.value = true;
      tips.value = "准备下半场";
      // 剩余休息时间
      // const remain = (Date.now() - battleInfo.timeoutTime) / 1000;
      setTimeout(() => {
        uni.$emit("update-remain", 0);
      }, 200);
      return;
    }
    if (force) {
      const remain = (Date.now() - (battleInfo.current?.startTime || Date.now())) / 1000;
      console.log(`当前轮已进行${remain}秒`);
      if (remain > 0 && remain < 90) {
        setTimeout(() => {
          uni.$emit("update-remain", 90 - remain - 0.2);
        }, 200);
      }
    }
  } catch (err) {
    console.error("recoverData error:", err);
  }
}

onLoad(async (options) => {
  if (options.battleId) battleId.value = options.battleId;
  // uni.enableAlertBeforeUnload({
  //   message: "离开比赛可能导致比赛失败，是否继续？",
  //   success: (res) => {
  //     console.log("已启用离开提示");
  //   },
  // });
});

async function onReceiveMessage(msg) {
  if (Array.isArray(msg)) return;
  if (msg.type === MESSAGETYPESV2.BattleStart) {
    halfTimeTip.value = false;
    halfRest.value = false;
    recoverData(msg);
  } else if (msg.type === MESSAGETYPESV2.ShootResult) {
    recoverData(msg);
  } else if (msg.type === MESSAGETYPESV2.HalfRest) {
    halfTimeTip.value = true;
    halfRest.value = true;
    tips.value = "准备下半场";
  } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
    setTimeout(() => {
      // 全部跳转到新结算页
      uni.redirectTo({
        url: "/pages/friend-battle-result?battleId=" + msg.matchId,
      });
    }, 1000);
  }
}
onMounted(async () => {
  uni.setKeepScreenOn({
    keepScreenOn: true,
  });
  uni.$on("socket-inbox", onReceiveMessage);
  await laserCloseAPI();
});
onBeforeUnmount(() => {
  uni.setKeepScreenOn({
    keepScreenOn: false,
  });
  uni.$off("socket-inbox", onReceiveMessage);
  audioManager.stopAll();
});

onShow(async () => {
  if (battleId.value) {
    const result = await getBattleAPI(battleId.value);
    if (!result) return;
    if (result.status === 2) {
      uni.showToast({
        title: "比赛已结束",
        icon: "none",
      });
      uni.navigateBack({
        delta: 2,
      });
    } else {
      recoverData(result, { force: true });
    }
  }
});
</script>

<template>
  <Container :title="title" :bgType="1">
    <view class="container">
      <BattleHeader v-if="!start" :players="players" />
      <TestDistance v-if="start === false" :guide="false" :isBattle="true" />
      <ShootProgress
        :show="start"
        :start="start && !halfRest"
        :tips="tips"
        :total="90"
        :melee="true"
        :battleId="battleId"
      />
      <view v-if="start" class="user-row">
        <Avatar :src="user.avatar" :size="35" />
        <BowPower />
      </view>
      <BowTarget
        v-if="start"
        :currentRound="
          playersScores.map((s) => s[user.id].length).reduce((a, b) => a + b, 0)
        "
        :totalRound="12"
        :scores="playersScores.map((r) => r[user.id]).flat()"
        :stop="halfRest"
      />
      <view :style="{ paddingBottom: '20px' }">
        <PlayerScore
          v-if="start"
          v-for="(player, index) in playersSorted"
          :key="index"
          :player="player"
          :scores="playersScores.map((s) => s[player.id])"
        />
      </view>
      <ScreenHint
        :show="halfTimeTip"
        mode="small"
      >
        <view class="half-time-tip">
          <text>上半场结束，休息一下吧:）</text>
          <text>20秒后开始下半场</text>
        </view>
      </ScreenHint>
      <!-- 设备离线提示弹窗 -->
      <SModal
        :show="showOfflineModal"
        :noBg="true"
        height="360rpx"
        :onClose="() => (showOfflineModal = false)"
      >
        <view class="offline-modal">
          <text class="offline-title">设备已离线</text>
          <text class="offline-desc">检测到设备已断开连接，请检查设备后继续比赛</text>
          <SButton @click="showOfflineModal = false">我知道了</SButton>
        </view>
      </SModal>
    </view>
  </Container>
</template>

<style scoped>
.container {
  width: 100%;
  height: 100%;
}

.offline-modal {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 60rpx 40rpx 40rpx;
  gap: 24rpx;
}

.offline-title {
  font-size: 36rpx;
  font-weight: bold;
  color: #FED847;
}

.offline-desc {
  font-size: 28rpx;
  color: #CCCCCC;
  text-align: center;
  line-height: 1.6;
}
</style>
