<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from "vue";
import Container from "@/components/Container.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import BowTarget from "@/components/BowTarget.vue";
import ScorePanel from "@/components/ScorePanel.vue";
import ScoreResult from "@/components/ScoreResult.vue";
import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue";
import BowPower from "@/components/BowPower.vue";
import TestDistance from "@/components/TestDistance.vue";
import BubbleTip from "@/components/BubbleTip.vue";
import audioManager from "@/audioManager";

import {
  createPractiseAPI,
  startPractiseAPI,
  endPractiseAPI,
  getPractiseAPI,
} from "@/apis";
import { sharePractiseData } from "@/canvas";
import { wxShare, debounce } from "@/util";
import { MESSAGETYPESV2 } from "@/constants";

import useStore from "@/store";
import { storeToRefs } from "pinia";
import {onLoad} from "@dcloudio/uni-app";
const store = useStore();
const { user } = storeToRefs(store);

const start = ref(false);
const scores = ref([]);
const total = 36;
/** 当前练习中连续 X 环计数，用于触发 tententen 音效 */
const xRingStreak = ref(0);
const practiseResult = ref({});
const practiseId = ref("");
const showGuide = ref(false);
const targetType = ref(1);

onLoad((options) => {
  if (options.target) {
    targetType.value = Number(options.target);
  }
});

const onReady = async () => {
  await startPractiseAPI();
  scores.value = [];
  xRingStreak.value = 0; // 新一局开始，重置 X 环连续计数
  start.value = true;
  audioManager.play("练习开始");
};

const onOver = async () => {
  practiseResult.value = await getPractiseAPI(practiseId.value);
  start.value = false;
};

/**
 * 检测连续 X 环是否达到 3 箭，达到则播放 tententen 音效
 * @param {boolean} isXRing - 本次射击是否为 X 环
 */
function checkAndPlayTententen(isXRing) {
  if (isXRing) {
    xRingStreak.value += 1;
    // 连续 3 箭均为 X 环，在环数播报入队后追加 tententen，避免播放顺序颠倒
    if (xRingStreak.value >= 3) {
      xRingStreak.value = 0;
      nextTick(() => audioManager.play("tententen", false));
    }
  } else {
    // 非 X 环则重置连续计数
    xRingStreak.value = 0;
  }
}

async function onReceiveMessage(msg) {
  if (msg.type === MESSAGETYPESV2.ShootResult) {
    const prevLen = scores.value.length;
    scores.value = msg.details;
    // 有新箭时取最后一箭判断是否 X 环并检测连续计数
    if (scores.value.length > prevLen) {
      const latestArrow = scores.value[scores.value.length - 1];
      checkAndPlayTententen(!!(latestArrow?.ringX && latestArrow?.ring));
    }
  } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
    setTimeout(onOver, 1500);
  }
  // messages.forEach((msg) => {
  //   if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
  //     if (scores.value.length < total) {
  //       scores.value.push(msg.target);
  //       if (practiseId && scores.value.length === total / 2) {
  //         showGuide.value = true;
  //         setTimeout(() => {
  //           showGuide.value = false;
  //         }, 3000);
  //       }
  //       if (scores.value.length === total) {
  //         setTimeout(onOver, 1500);
  //       }
  //     }
  //   }
  // });
}

async function onComplete() {
  const validArrows = (practiseResult.value.details || []).filter(
    (a) => a.x !== -30 && a.y !== -30
  );
  if (validArrows.length === total) {
    uni.navigateBack();
  } else {
    practiseId.value = "";
    practiseResult.value = {};
    start.value = false;
    scores.value = [];
    xRingStreak.value = 0; // 重新开始练习，重置 X 环连续计数
    const result = await createPractiseAPI(total, 3600);
    if (result) practiseId.value = result.id;
  }
}

const onClickShare = debounce(async () => {
  await sharePractiseData("shareCanvas", 3, user.value, practiseResult.value);
  await wxShare("shareCanvas");
});

onMounted(async () => {
  uni.setKeepScreenOn({
    keepScreenOn: true,
  });
  uni.$on("socket-inbox", onReceiveMessage);
  uni.$on("share-image", onClickShare);
  const result = await createPractiseAPI(total, 3600, targetType.value);
  if (result) practiseId.value = result.id;
});

onBeforeUnmount(() => {
  uni.setKeepScreenOn({
    keepScreenOn: false,
  });
  uni.$off("socket-inbox", onReceiveMessage);
  uni.$off("share-image", onClickShare);
  audioManager.stopAll();
  endPractiseAPI();
});
</script>

<template>
  <Container
    :bgType="1"
    title="日常耐力挑战"
    :showBottom="!start && !scores.length"
  >
    <view>
      <TestDistance v-if="!start && !practiseResult.id" />
      <block v-else>
        <ShootProgress
          :tips="`请连续射${total}支箭`"
          :start="start"
          :total="3600"
          :onStop="onOver"
        />
        <view class="user-row">
          <Avatar :src="user.avatar" :size="35" />
          <BubbleTip v-if="showGuide" type="normal2">
            <text>完成过半，胜利</text>
            <text>在望！💪</text>
          </BubbleTip>
          <BowPower />
        </view>
        <BowTarget
          :currentRound="scores.length"
          :totalRound="start ? total : 0"
          :scores="scores"
        />
        <ScorePanel
          v-if="start"
          :arrows="scores"
          :total="total"
          :rowCount="total / 4"
          :margin="1.5"
          :font-size="20"
        />
        <ScoreResult
          v-if="practiseResult.details"
          :total="total"
          :rowCount="9"
          :onClose="onComplete"
          :result="practiseResult"
          :tipSrc="`../static/${
            practiseResult.details.filter(
              (arrow) => arrow.x !== -30 && arrow.y !== -30
            ).length < total
              ? '2un'
              : ''
          }finish-tip.png`"
        />
        <canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
      </block>
    </view>
    <template #bottom>
      <SButton :onClick="onReady">准备好了，直接开始</SButton>
    </template>
  </Container>
</template>

<style scoped></style>
