<script setup>
import { computed, 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 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, roundsName } from "@/constants";

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

const sound = ref(true);
const start = ref(false);
const pageStages = Object.freeze({
  DISTANCE: "distance",
  SHOOTING: "shooting",
  RESULT: "result",
  LOADING: "loading",
});
const pageStage = ref(pageStages.DISTANCE);
const scores = ref([]);
const defaultTotal = 12;
const defaultShootTime = 120;
const defaultTargetType = 1;
const total = ref(defaultTotal);
const shootTime = ref(defaultShootTime);
const practiseResult = ref({});
const practiseId = ref("");
const showGuide = ref(false);
const tips = ref("");
const targetType = ref(defaultTargetType);
const trainingParams = ref({});
const trainingDifficultyRefreshEvent = "training-difficulty-refresh";
const useHighlightTest = ref(false);
const highlightTestTimer = ref(null);

const env = computed(() => {
  try {
    return uni.getAccountInfoSync().miniProgram.envVersion;
  } catch (error) {
    return "release";
  }
});

const isDistanceStage = computed(() => pageStage.value === pageStages.DISTANCE);
const isShootingStage = computed(() => pageStage.value === pageStages.SHOOTING);
const hasPractiseResult = computed(() => !!practiseResult.value?.details);
const showResult = computed(
  () => pageStage.value === pageStages.RESULT && hasPractiseResult.value
);

const defaultHighlightAreas = [{ quadrant: 1, rings: [7] }];

// 临时高亮测试数据：第 N 项对应第 N 箭，每箭展示一个不同区域。
const highlightTestAreas = [
  { arrowIndex: 1, quadrant: 1, rings: [10] },
  { arrowIndex: 2, quadrant: 2, rings: [9, 10] },
  { arrowIndex: 3, quadrant: 3, rings: [8, 9] },
  { arrowIndex: 4, quadrant: 4, rings: [7, 8] },
  { arrowIndex: 5, quadrant: 1, rings: [6, 7] },
  { arrowIndex: 6, quadrant: 2, rings: [5, 6] },
  { arrowIndex: 7, quadrant: 3, rings: [4, 5] },
  { arrowIndex: 8, quadrant: 4, rings: [3, 4] },
  { arrowIndex: 9, quadrant: 1, rings: "all", scope: "sector" },
  { arrowIndex: 10, quadrant: 2, rings: "all", scope: "sector" },
  { arrowIndex: 11, quadrant: 3, rings: "all", scope: "sector" },
  { arrowIndex: 12, quadrant: 4, rings: "all", scope: "sector" },
];

const targetHighlightAreas = computed(() => {
  return useHighlightTest.value ? highlightTestAreas : defaultHighlightAreas;
});

const toRouteNumber = (value, fallback = 0) => {
  const numberValue = Number(value);
  return Number.isFinite(numberValue) ? numberValue : fallback;
};

const toPositiveRouteNumber = (value, fallback) => {
  const numberValue = toRouteNumber(value, fallback);
  return numberValue > 0 ? numberValue : fallback;
};

const createPractice = async () => {
  const result = await createPractiseAPI(
    total.value,
    shootTime.value,
    targetType.value
  );

  if (result) practiseId.value = result.id;
};

const clearHighlightTestTimer = () => {
  if (highlightTestTimer.value) {
    clearInterval(highlightTestTimer.value);
    highlightTestTimer.value = null;
  }
};

const buildHighlightTestScore = (index) => ({
  playerId: user.value?.id,
  ring: 9,
  ringX: false,
  x: ((index % 4) - 1.5) * 2,
  y: (Math.floor(index / 4) - 1) * 2,
  angle: null,
});

const setHighlightTestArrow = (arrowIndex) => {
  const completedCount = Math.max(arrowIndex - 1, 0);
  scores.value = Array.from({ length: completedCount }, (_, index) =>
    buildHighlightTestScore(index)
  );
};

// 临时测试入口：自动切换第 1 到第 12 箭，让 BowTarget 按当前箭展示不同高亮。
const runHighlightTest = () => {
  clearHighlightTestTimer();
  useHighlightTest.value = true;
  practiseResult.value = {};
  pageStage.value = pageStages.SHOOTING;
  start.value = true;

  let arrowIndex = 1;
  setHighlightTestArrow(arrowIndex);

  highlightTestTimer.value = setInterval(() => {
    if (arrowIndex >= highlightTestAreas.length) {
      clearHighlightTestTimer();
      return;
    }

    arrowIndex += 1;
    setHighlightTestArrow(arrowIndex);
  }, 1000);
};

const resetHighlightTest = () => {
  clearHighlightTestTimer();
  useHighlightTest.value = false;
  scores.value = [];
};

onLoad((options = {}) => {
  targetType.value = toPositiveRouteNumber(options.target, defaultTargetType);
  total.value = toPositiveRouteNumber(options.arrows, defaultTotal);
  shootTime.value = toPositiveRouteNumber(options.time, defaultShootTime);
  trainingParams.value = {
    type: options.type || "",
    difficultyId: options.difficultyId || "",
    difficulty: toRouteNumber(options.difficulty),
    recordId: options.recordId || "",
    hitReq: toRouteNumber(options.hitReq),
    totalReq: toRouteNumber(options.totalReq),
    blocks: toRouteNumber(options.blocks),
    mode: toRouteNumber(options.mode),
  };
});

const onReady = async () => {
  pageStage.value = pageStages.LOADING;
  clearHighlightTestTimer();
  useHighlightTest.value = false;
  try {
    await startPractiseAPI();
    practiseResult.value = {};
    scores.value = [];
    start.value = true;
    pageStage.value = pageStages.SHOOTING;
    audioManager.play("练习开始");
  } catch (error) {
    start.value = false;
    pageStage.value = pageStages.DISTANCE;
    throw error;
  }
};

const onOver = async () => {
  if (!isShootingStage.value) return;

  clearHighlightTestTimer();
  pageStage.value = pageStages.LOADING;
  start.value = false;

  try {
    practiseResult.value = (await getPractiseAPI(practiseId.value)) || {};
    pageStage.value = hasPractiseResult.value
      ? pageStages.RESULT
      : pageStages.DISTANCE;
  } catch (error) {
    start.value = true;
    pageStage.value = pageStages.SHOOTING;
    throw error;
  }
};

async function onReceiveMessage(msg) {
  if (msg.type === MESSAGETYPESV2.ShootResult && isShootingStage.value) {
    scores.value = msg.details;
  } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
    // setTimeout(onOver, 1500);
  }
}

function onComplete() {
  pageStage.value = pageStages.LOADING;
  start.value = false;
  uni.$emit(trainingDifficultyRefreshEvent);
  uni.navigateBack();
}

async function onRetry() {
  pageStage.value = pageStages.LOADING;
  clearHighlightTestTimer();
  useHighlightTest.value = false;
  practiseId.value = "";
  practiseResult.value = {};
  start.value = false;
  scores.value = [];
  try {
    await createPractice();
  } finally {
    pageStage.value = pageStages.DISTANCE;
  }
}

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

function onAudioEnded(s) {
  if (s.indexOf("比赛结束") >= 0) {
    onOver()
  }
}

const updateSound = () => {
  sound.value = !sound.value;
  audioManager.setMuted(!sound.value);
};


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

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

<template>
  <Container
    :bgType="isDistanceStage ? 9 : 10"
    :showBottom="isDistanceStage"
    :scroll="!isShootingStage"
  >
    <view class="practise-content">
      <TestDistance v-if="isDistanceStage" />
      <view v-else-if="isShootingStage" class="shooting-layout">
        <view class="shooting-fixed">
          <ShootProgress
            :start="start"
            :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
            :totalRound="start ? total / 4 : 0"
            :currentRound="scores.length % 3"
            :scores="scores"
            :showCrosshair="false"
            :highlightAreas="targetHighlightAreas"
          />
          <view v-if="env !== 'release'" class="highlight-test-actions">
            <button
              class="highlight-test-btn"
              hover-class="none"
              @click="runHighlightTest"
            >
              高亮测试
            </button>
            <button
              class="highlight-test-btn"
              hover-class="none"
              @click="resetHighlightTest"
            >
              重置高亮
            </button>
          </view>
          <view class="sound-text-box">
            <button class="sound-btn" hover-class="none" @click="updateSound">
              <image
                class="sound-icon"
                :src="`/static/sound${sound ? '' : '-off'}-yellow.png`"
                mode="aspectFit"
              />
            </button>
            <view class="bat-text-big-box">
              <image
                class="dao-icon"
                src="../../static/training-difficulty-design/dao-icon.png"
                mode="widthFix"
              />
              <view class="bat-text-box">
                <view class="bat-text-small-box">
                  <view class="text-round-box">
                    <view class="text1">每箭命中9环之上</view>
                    <view class="text2">剩余<text class="text2-yellow">3</text>箭</view>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
        <scroll-view
          class="score-scroll"
          scroll-y
          :enhanced="true"
          :show-scrollbar="false"
        >
          <ScorePanel2 :arrows="scores" :total="total" />
        </scroll-view>
      </view>
      <ScoreResult
        v-else-if="showResult"
        :rowCount="6"
        :total="total"
        :onClose="onComplete"
        :onRetry="onRetry"
        :result="practiseResult"
      />
      <canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
    </view>
    <template #bottom>
      <view class="btn-box">
        <image
          class="btn-box-bg"
          src="../../static/training-difficulty-design/par-star.png"
          mode="widthFix"
        />
        <button class="btn" @click="onReady">准备好了，开始练习</button>
      </view>
    </template>
  </Container>
</template>

<style scoped>
.practise-content {
  height: 100%;
  min-height: 0;
}

.shooting-layout {
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.shooting-fixed {
  flex-shrink: 0;
}

.score-scroll {
  flex: 1;
  height: 0;
  min-height: 0;
  overflow: hidden;
}

.btn-box{
  width: 488rpx;
  height: 234rpx;
  position: fixed;
  bottom: 130rpx;
  left: 50%;
  transform: translateX(-50%);
}
.btn-box-bg{
  width: 100%;
}
.btn{
  width: 330rpx;
  height: 70rpx;
  line-height: 70rpx;
  background: #FED847;
  border-radius: 44rpx;
  text-align: center;
  color: #000000;
  font-size: 28rpx;
  font-weight: 500;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: -36rpx;
}

.highlight-test-actions {
  display: flex;
  justify-content: center;
  margin-top: -24rpx;
  position: relative;
  z-index: 10;
}

.highlight-test-btn {
  width: 150rpx;
  height: 48rpx;
  line-height: 48rpx;
  padding: 0;
  border-radius: 24rpx;
  background: rgba(0, 0, 0, 0.48);
  color: #fed847;
  font-size: 22rpx;
}

.highlight-test-btn::after {
  border: none;
}

.highlight-test-btn + .highlight-test-btn {
  margin-left: 16rpx;
}

.sound-text-box{
  height: 125rpx;
  padding: 0 56rpx;
  display: flex;
  align-items: flex-end;
}
.sound-btn {
  width: 76rpx;
  height: 70rpx;
  border: none;
}

.sound-btn::after {
  border: none;
}

.sound-icon {
  width: 76rpx;
  height: 70rpx;
}
.bat-text-big-box{
  flex: 1;
  position: relative;
}
.dao-icon{
  width: 160rpx;
  height: 125rpx;
  position: absolute;
  left: 0;
  bottom: 0;
}
.text-round-box{
  width: 100%;
}
.bat-text-box{
  display: flex;
}
.bat-text-small-box{
  background: rgba(0, 0, 0, 0.5);
  width: auto;
  min-width: 100rpx;
  border-radius: 16rpx 60rpx 60rpx 16rpx;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: 176rpx;
  height: 112rpx;
  padding-right: 30rpx;
  font-size: 30rpx;
  color: #E7BA80;
}
.text1{
  font-size: 30rpx;
  font-weight: 400;
  color: #E7BA80;
  line-height: 42rpx;
}
.text2{
  color: #FFFFFF;
  font-size: 26rpx;
  font-weight: 400;
  line-height: 36rpx;
}
.text2-yellow{
  font-size: 30rpx;
  color: #FFD947;
  font-weight: 500;
  margin: 0 4rpx;
}
</style>
