<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import BowTarget from "@/components/BowTarget.vue";
import ScorePanel2 from "@/components/ScorePanel2.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,
  endPractiseAPI,
  getPractiseAPI,
  startPractiseAPI,
} from "@/apis";
import { connectMatchWebSocket, closeMatchWebSocket } from "@/matchWebsocket";
import { sharePractiseData } from "@/canvas";
import { wxShare, debounce } from "@/util";
import { MESSAGETYPESV2, roundsName } from "@/constants";

import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user, device } = storeToRefs(store);

const start = ref(false);
const scores = ref([]);
const isSvip = ref(false);
const total = 12;
const practiseResult = ref({});
const practiseId = ref("");
const showGuide = ref(false);
const tips = ref("");
const targetType = ref(1);
const sharing = ref(false);
const exiting = ref(false);
const RESULT_TIP_CDN = "https://static.shelingxingqiu.com/shootmini/static";

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

const createPractise = async () => {
  closeMatchWebSocket({ reason: "practice-recreate" });
  const result = await createPractiseAPI(
    total,
    120,
    targetType.value,
    device.value.deviceId
  );
  if (result?.id) practiseId.value = result.id;
  if (!result?.serverAddr) {
    uni.showToast({
      title: "练习连接信息异常，请重试",
      icon: "none",
    });
    return null;
  }
  connectMatchWebSocket({
    serverAddr: result.serverAddr,
    matchId: result.id,
    userId: user.value.id,
  });
  return result;
};

const beginPractise = async () => {
  if (!practiseId.value) {
    uni.showToast({
      title: "练习未创建，请重试",
      icon: "none",
    });
    return false;
  }
  await startPractiseAPI(practiseId.value);
  return true;
};

const onReady = async () => {
  const result = await beginPractise();
  if (!result) return;
  scores.value = [];
  isSvip.value = false;
  start.value = true;
  audioManager.play("练习开始");
};

const onOver = async (message) => {
  practiseResult.value = Array.isArray(message?.details)
    ? message
    : await getPractiseAPI(practiseId.value);
  start.value = false;
};

async function onReceiveMessage(msg) {
  if (msg.type === MESSAGETYPESV2.ShootResult) {
    isSvip.value = msg.sVip === true;
    scores.value = Array.isArray(msg.details) ? msg.details : scores.value;
  } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
    setTimeout(() => onOver(msg), 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 = [];
    isSvip.value = false;
    await createPractise();
  }
}

async function exitPractise() {
  if (exiting.value) return;
  exiting.value = true;

  try {
    if (practiseId.value && !practiseResult.value?.details) {
      await endPractiseAPI(practiseId.value);
    }
  } catch (error) {
    console.error("Failed to stop practice", error);
  } finally {
    uni.navigateBack();
  }
}

const getResultTipSrc = (result = {}) => {
  const validCount = (result.details || []).filter(
    (arrow) => arrow.x !== -30 && arrow.y !== -30
  ).length;
  return `${RESULT_TIP_CDN}/${validCount < total ? "un" : ""}finish-tip.png`;
};

const onClickShare = debounce(async () => {
  if (sharing.value) return;
  sharing.value = true;
  try {
    await sharePractiseData("shareCanvas", 2, user.value, practiseResult.value);
    await wxShare("shareCanvas");
  } catch (e) {
    uni.showToast({
      title: "海报生成失败，请稍后重试",
      icon: "none",
    });
  } finally {
    sharing.value = false;
  }
});

onMounted(async () => {
  void audioManager.warmAll();
  // audioManager.play("第一轮");
  uni.setKeepScreenOn({
    keepScreenOn: true,
  });
  uni.$on("socket-inbox", onReceiveMessage);
  uni.$on("share-image", onClickShare);
  await createPractise();
});

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

<template>
  <Container
    :bgType="1"
    title="个人单组练习"
    :showBottom="!start && !scores.length"
    :onBack="exitPractise"
  >
    <view>
      <TestDistance v-if="!start && !practiseResult.id" />
      <block v-else>
        <ShootProgress
          :tips="`${
            !start || scores.length === 12
              ? ''
              : `请开始射箭第${
                  roundsName[Math.ceil((scores.length + 1) / 3)]
                }轮`
          }`"
          :start="start"
          :onStop="onOver"
          end-audio-key="练习结束"
        />
        <view class="user-row">
          <Avatar :src="user.avatar" :size="35" />
          <BubbleTip v-if="showGuide" type="normal2">
            <text>还有两场，坚持</text>
            <text>就是胜利！💪</text>
          </BubbleTip>
          <BowPower />
        </view>
        <BowTarget
          :totalRound="start ? total / 4 : 0"
          :currentRound="scores.length % 3"
          :scores="scores"
          :isSvip="isSvip"
        />
        <ScorePanel2 :arrows="scores" />
        <ScoreResult
          v-if="practiseResult.details"
          :rowCount="6"
          :total="total"
          :onClose="onComplete"
          :result="practiseResult"
          :tipSrc="getResultTipSrc(practiseResult)"
        />
        <canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
      </block>
    </view>
    <template #bottom>
      <SButton :onClick="onReady">准备好了，直接开始</SButton>
    </template>
  </Container>
</template>

<style scoped></style>
