<script setup>
import { nextTick, onMounted, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import TargetPicker from "@/components/TargetPicker.vue";
import { getPersonalTrainingAPI } from "@/apis";

const checkedIcon = "../../static/training-home/done.png";
const missedIcon = "../../static/training-home/missed.png";
// 后端训练项目 id 与难度页 mode 参数的映射关系。
const trainingModeRouteMap = {
  base: "basic",
  endurance: "endurance",
  precision: "precision",
  rhythm: "rhythm",
  strength: "power",
};
// 训练项目卡片右侧主图标。
const trainingModeIconMap = {
  base_bow: "../../static/training-home/img_22.png",
  bow: "../../static/training-home/img_3.png",
  target: "../../static/training-home/img_4.png",
  wave: "../../static/training-home/img_5.png",
  muscle: "../../static/training-home/img_6.png",
};
// 训练项目卡片标题图，按接口 id 映射本地资源。
const trainingModeTitleImageMap = {
  endurance: "../../static/training-home/nailixunlian.png",
  precision: "../../static/training-home/jingzhunxunlian.png",
  rhythm: "../../static/training-home/jiezouxunlian.png",
  strength: "../../static/training-home/liliangxulian.png",
};
const defaultWeekDays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
const defaultRadarDimensions = [
  { name: "基础", score: 0 },
  { name: "精准", score: 0 },
  { name: "力量", score: 0 },
  { name: "节奏", score: 0 },
  { name: "耐力", score: 0 },
];

// 页面始终直接消费接口字段，这里只保留一份兜底结构，避免模板访问空值。
const createDefaultTrainingData = () => ({
  week_days: defaultWeekDays.map((day) => ({ day, status: "cross" })),
  stats: {
    total_training_days: 0,
    total_arrows: 0,
    hit_rate: 0,
    endurance_shoot_speed: 0,
    total_calories: 0,
    overtake_rate: 0,
  },
  radar: {
    dimensions: defaultRadarDimensions,
  },
  training_items: [],
});

const trainingData = ref(createDefaultTrainingData());
const pageMounted = ref(false);
const showRoutineTargetPicker = ref(false);
const trainingRadarCanvasId = "training-home-radar";
const radarImageWidth = 225;
const radarImageHeight = 224;
const radarFigureWidthRpx = 448;
const radarFigureHeightRpx = Math.round(
  (radarFigureWidthRpx * radarImageHeight) / radarImageWidth
);
const radarCanvasWidth = Math.round(uni.upx2px(radarFigureWidthRpx));
const radarCanvasHeight = Math.round(uni.upx2px(radarFigureHeightRpx));
const radarScaleX = radarCanvasWidth / radarImageWidth;
const radarScaleY = radarCanvasHeight / radarImageHeight;
const radarScale = Math.min(radarScaleX, radarScaleY);
const radarCenterX = 112.0624 * radarScaleX;
const radarCenterY = 111.4645 * radarScaleY;
const radarStrokeWidth = Math.max(1, 2 * radarScale);
const radarPointRadius = Math.max(2.5, 3.5 * radarScale);
const radarOuterRadiusX = 110.7089 * radarScaleX;
const radarOuterRadiusY = 110.7089 * radarScaleY;
const radarMaxValue = 100;
const radarFigureStyle = {
  width: `${radarFigureWidthRpx}rpx`,
  height: `${radarFigureHeightRpx}rpx`,
};

const formatValue = (value, digits = 1) => {
  const numberValue = Number(value);
  if (!Number.isFinite(numberValue)) return "--";
  return String(Number(numberValue.toFixed(digits)));
};

const getLevelText = (item) => {
  if (!item) return "";
  const level = Number(item.current_level) || 0;
  return item.is_locked ? `Coming! LV${level}` : `当前进度 LV${level} >`;
};

// 卡路里字段按需求做 K / W 缩写展示。
const getCaloriesValue = (value) => {
  const numberValue = Number(value);
  if (!Number.isFinite(numberValue)) return "--";
  if (numberValue >= 10000) return `${formatValue(numberValue / 10000)}W`;
  if (numberValue >= 1000) return `${formatValue(numberValue / 1000)}K`;
  return formatValue(numberValue, 0);
};

const getTrainingIcon = (item = {}) =>
  trainingModeIconMap[item.icon] || trainingModeIconMap.bow;

const getTrainingTitleImage = (item = {}) =>
  trainingModeTitleImageMap[item.id] || "";

const getTrainingMode = (item = {}) =>
  trainingModeRouteMap[item.id] || item.id || "";

const getRadarPoint = (centerX, centerY, radiusX, radiusY, angle) => ({
  x: centerX + radiusX * Math.cos(angle),
  y: centerY + radiusY * Math.sin(angle),
});

// 雷达图直接使用接口的 5 维 score，按 0-100 等比映射到顶点位置。
const drawRadar = () => {
  const dimensions = Array.isArray(trainingData.value.radar?.dimensions)
    ? trainingData.value.radar.dimensions.slice(0, 5)
    : [];

  if (dimensions.length !== 5) return;

  const ctx = uni.createCanvasContext(trainingRadarCanvasId);
  const angles = dimensions.map(
    (_, index) => (-90 + index * 72) * (Math.PI / 180)
  );

  ctx.clearRect(0, 0, radarCanvasWidth, radarCanvasHeight);

  const points = dimensions.map((item, index) => {
    const normalized = Math.max(
      0,
      Math.min(Number(item.score) || 0, radarMaxValue)
    );
    const progress = normalized / radarMaxValue;

    return getRadarPoint(
      radarCenterX,
      radarCenterY,
      radarOuterRadiusX * progress,
      radarOuterRadiusY * progress,
      angles[index]
    );
  });

  ctx.beginPath();
  points.forEach((point, index) => {
    if (index === 0) ctx.moveTo(point.x, point.y);
    else ctx.lineTo(point.x, point.y);
  });
  ctx.closePath();
  ctx.setFillStyle("rgba(255, 209, 154, 0.26)");
  ctx.fill();
  ctx.setStrokeStyle("rgba(220, 162, 92, 0.92)");
  ctx.setLineWidth(radarStrokeWidth);
  ctx.stroke();

  points.forEach((point) => {
    ctx.beginPath();
    ctx.arc(point.x, point.y, radarPointRadius, 0, 2 * Math.PI);
    ctx.setFillStyle("rgba(221, 162, 90, 1)");
    ctx.fill();
  });

  ctx.beginPath();
  ctx.arc(radarCenterX, radarCenterY, radarPointRadius, 0, 2 * Math.PI);
  ctx.setFillStyle("rgba(125, 107, 83, 0.65)");
  ctx.fill();
  ctx.draw();
};

// 小程序 canvas 首次渲染时机不稳定，延后一帧再绘制更稳。
const refreshRadar = async () => {
  await nextTick();
  setTimeout(() => {
    drawRadar();
  }, 30);
};

const loadPersonalTrainingData = async () => {
  try {
    const result = await getPersonalTrainingAPI();
    trainingData.value = {
      week_days:
        Array.isArray(result?.week_days) && result.week_days.length
          ? result.week_days
          : createDefaultTrainingData().week_days,
      stats: {
        total_training_days: result?.stats?.total_training_days ?? 0,
        total_arrows: result?.stats?.total_arrows ?? 0,
        hit_rate: result?.stats?.hit_rate ?? 0,
        endurance_shoot_speed: result?.stats?.endurance_shoot_speed ?? 0,
        total_calories: result?.stats?.total_calories ?? 0,
        overtake_rate: result?.stats?.overtake_rate ?? 0,
      },
      radar: {
        dimensions:
          Array.isArray(result?.radar?.dimensions) &&
          result.radar.dimensions.length === 5
            ? result.radar.dimensions
            : createDefaultTrainingData().radar.dimensions,
      },
      training_items: Array.isArray(result?.training_items)
        ? result.training_items
        : [],
    };
  } catch (error) {
    console.log("personal training load failed", error);
    trainingData.value = createDefaultTrainingData();
  } finally {
    await refreshRadar();
  }
};

const openTrainingRecord = () => {
  uni.navigateTo({
    url: "/pages/my-growth?tab=2",
  });
};

const openTrainingItem = (item = {}) => {
  const mode = getTrainingMode(item);
  if (!mode) return;

  if (item.is_locked) {
    uni.showToast({
      title: `${item.name || "训练"} 暂未开放`,
      icon: "none",
    });
    return;
  }

  uni.navigateTo({
    url: `/pages/training/difficulty?mode=${mode}`,
  });
};

const openRoutineTraining = () => {
  showRoutineTargetPicker.value = true;
};

const handleRoutineTargetConfirm = (target) => {
  showRoutineTargetPicker.value = false;
  uni.navigateTo({
    url: `/pages/practise-one?target=${target}`,
  });
};

// 首次进入页面时拉取数据并完成雷达图初始化。
onMounted(async () => {
  await loadPersonalTrainingData();
  pageMounted.value = true;
});

// 从其他页面返回时刷新训练数据，保持进度与推荐状态最新。
onShow(async () => {
  if (!pageMounted.value) return;
  await loadPersonalTrainingData();
});
</script>

<template>
  <Container :showBackToGame="true" :bgType="7" bgColor="#050b19">
    <view class="training-home">
      <view class="week-grid">
        <view
          v-for="item in trainingData.week_days"
          :key="item.day"
          class="week-item"
        >
          <view class="week-item-bg"></view>
          <image
            class="week-item-icon"
            :src="item.status === 'checked' ? checkedIcon : missedIcon"
            mode="widthFix"
          />
          <text
            class="week-item-label"
            :class="{ 'week-item-label-active': item.status === 'checked' }"
          >
            {{ item.day }}
          </text>
        </view>
      </view>

      <view class="stats-card">
        <view class="stats-card-bg"></view>
        <image
          class="stats-quote stats-quote-left"
          src="../../static/training-home/img_17.png"
          mode="widthFix"
        />
        <image
          class="stats-quote stats-quote-right"
          src="../../static/training-home/img_16.png"
          mode="widthFix"
        />
        <view class="stats-grid">
          <view class="stats-item">
            <view class="stats-value-row">
              <view class="stats-value-group">
                <text class="stats-value">
                  {{ formatValue(trainingData.stats.total_training_days, 0) }}
                </text>
                <text class="stats-unit">天</text>
                <view class="stats-value-decoration"></view>
              </view>
            </view>
            <text class="stats-label">共训练</text>
          </view>

          <view class="stats-item">
            <view class="stats-value-row">
              <view class="stats-value-group">
                <text class="stats-value">
                  {{ formatValue(trainingData.stats.total_arrows, 0) }}
                </text>
                <text class="stats-unit">支</text>
                <view class="stats-value-decoration"></view>
              </view>
            </view>
            <text class="stats-label">累计射箭</text>
          </view>

          <view class="stats-item">
            <view class="stats-value-row">
              <view class="stats-value-group">
                <text class="stats-value">
                  {{ formatValue(trainingData.stats.hit_rate) }}
                </text>
                <text class="stats-unit">%</text>
                <view class="stats-value-decoration"></view>
              </view>
            </view>
            <text class="stats-label">命中率</text>
          </view>

          <view class="stats-item">
            <view class="stats-value-row">
              <view class="stats-value-group">
                <text class="stats-value">
                  {{ formatValue(trainingData.stats.endurance_shoot_speed, 0) }}
                </text>
                <text class="stats-unit">支/分钟</text>
                <view class="stats-value-decoration"></view>
              </view>
            </view>
            <text class="stats-label">耐力射击</text>
          </view>

          <view class="stats-item">
            <view class="stats-value-row">
              <view class="stats-value-group">
                <text class="stats-value">
                  {{ getCaloriesValue(trainingData.stats.total_calories) }}
                </text>
                <text class="stats-unit">卡路里</text>
                <view class="stats-value-decoration"></view>
              </view>
            </view>
            <text class="stats-label">共消耗</text>
          </view>
        </view>
      </view>

      <view class="radar-section">
        <view class="record-bubble" @click="openTrainingRecord">
          <image
            class="record-bubble-bg"
            src="../../static/training-home/img_28.png"
            mode="widthFix"
          />
          <view class="record-bubble-copy">
            <view class="record-main">
              已超越<text class="record-main-highlight">{{ formatValue(trainingData.stats.overtake_rate) }}%</text>对手
            </view>
            <view class="record-sub-row">
              <text class="record-sub-text">我的训练记录</text>
              <image
                class="record-arrow"
                src="../../static/training-home/img_7.png"
                mode="widthFix"
              />
            </view>
          </view>
        </view>

        <view class="radar-board">
          <text class="radar-label radar-label-top">
            {{ trainingData.radar.dimensions[0].name }}
          </text>
          <text class="radar-label radar-label-right">
            {{ trainingData.radar.dimensions[1].name }}
          </text>
          <text class="radar-label radar-label-bottom-right">
            {{ trainingData.radar.dimensions[2].name }}
          </text>
          <text class="radar-label radar-label-bottom-left">
            {{ trainingData.radar.dimensions[3].name }}
          </text>
          <text class="radar-label radar-label-left">
            {{ trainingData.radar.dimensions[4].name }}
          </text>

          <view class="radar-figure" :style="radarFigureStyle">
            <image
              class="radar-grid-image"
              :style="radarFigureStyle"
              src="../../static/training-home/img_19.png"
            />
            <canvas
              :canvas-id="trainingRadarCanvasId"
              :id="trainingRadarCanvasId"
              class="radar-canvas"
              :style="radarFigureStyle"
              :width="radarCanvasWidth"
              :height="radarCanvasHeight"
            />
            <image
              class="radar-mascot"
              src="../../static/training-home/img_21.png"
              mode="widthFix"
            />
          </view>
        </view>
      </view>

      <view class="featured-card" @click="openRoutineTraining">
        <image
          class="featured-card-bg"
          src="../../static/training-home/img_22.png"
          mode="widthFix"
        />
        <view class="featured-card-mask"></view>
        <view class="featured-card-copy">
          <text class="featured-card-title">常规训练</text>
          <text class="featured-card-subtitle">12箭练习</text>
        </view>
      </view>

      <view class="mode-grid">
        <view
          v-for="item in trainingData.training_items.filter((item) => item.id !== 'strength')"
          :key="item.id"
          class="mode-card"
          @click="openTrainingItem(item)"
        >
          <view v-if="item.is_recommended" class="mode-tag">推荐</view>
          <view class="mode-card-copy">
            <image
              v-if="getTrainingTitleImage(item)"
              class="mode-card-title-image"
              :src="getTrainingTitleImage(item)"
              mode="widthFix"
            />
            <text v-else class="mode-card-title">{{ item.name }}</text>
            <text class="mode-card-progress">{{ getLevelText(item) }}</text>
          </view>
          <image
            class="mode-card-icon"
            :src="getTrainingIcon(item)"
            mode="aspectFit"
          />
        </view>
      </view>
    </view>
    <TargetPicker
      :show="showRoutineTargetPicker"
      :onClose="() => (showRoutineTargetPicker = false)"
      :onConfirm="handleRoutineTargetConfirm"
    />
  </Container>
</template>

<style scoped>
.training-home {
  position: relative;
  overflow: hidden;
  padding: 18rpx 20rpx 60rpx 20rpx;
}

.week-grid {
  display: flex;
  justify-content: space-between;
  margin-top: 18rpx;
}

.week-item {
  position: relative;
  width: 92rpx;
  height: 96rpx;
  border-radius: 16rpx;
  overflow: hidden;
}

.week-item-bg {
  width: 100%;
  height: 100%;
  background: linear-gradient(180deg, #2f2d2b 0%, #252831 100%);
  opacity: 0.5;
}

.week-item-icon {
  position: absolute;
  left: 28rpx;
  top: 14rpx;
  width: 36rpx;
}

.week-item-label {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 10rpx;
  color: rgba(255, 255, 255, 0.6);
  font-size: 20rpx;
  text-align: center;
  line-height: 28rpx;
}

.week-item-label-active {
  color: #e7ba80;
}

.stats-card {
  position: relative;
  margin-top: 32rpx;
  width: 100%;
  height: 124rpx;
  overflow: hidden;
  border-radius: 24rpx;
}

.stats-card-bg {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #2f2d2b 0%, #252831 100%);
  opacity: 0.5;
}

.stats-quote {
  position: absolute;
  z-index: 1;
  width: 53rpx;
  height: 50rpx;
}

.stats-quote-left {
  left: 4rpx;
  top: 4rpx;
}

.stats-quote-right {
  right: 4rpx;
  bottom: 4rpx;
}

.stats-grid {
  position: absolute;
  z-index: 1;
  left: 36rpx;
  right: 36rpx;
  top: 22rpx;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.stats-item {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.stats-value-row {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  width: 100%;
  height: 48rpx;
  line-height: 48rpx;
}

.stats-value-group {
  position: relative;
  display: inline-flex;
  align-items: flex-end;
  justify-content: center;
  min-width: 72rpx;
  white-space: nowrap;
}

.stats-value-decoration {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6rpx;
  min-width: 72rpx;
  height: 12rpx;
  border-radius: 6rpx;
  background: linear-gradient(133deg, #ffd19a 0%, #a17636 100%);
  opacity: 0.5;
}

.stats-value {
  position: relative;
  z-index: 1;
  color: #fff;
  font-size: 34rpx;
  font-family: Helvetica, Arial, sans-serif;
  font-weight: 500;
  line-height: 46rpx;
}

.stats-unit {
  position: relative;
  z-index: 1;
  margin-left: 4rpx;
  padding-bottom: 8rpx;
  color: #fff;
  font-size: 20rpx;
  line-height: 28rpx;
  opacity: 0.6;
}

.stats-label {
  display: inline-block;
  margin-top: 6rpx;
  color: #fcce96;
  font-size: 20rpx;
  line-height: 28rpx;
  opacity: 0.6;
}

.radar-section {
  position: relative;
  padding-top: 34rpx;
}

.record-bubble {
  position: absolute;
  right: 0;
  top: 10rpx;
  width: 202rpx;
  height: 122rpx;
  z-index: 3;
}

.record-bubble-bg {
  width: 202rpx;
}

.record-bubble-copy {
  position: absolute;
  left: 0;
  right: 0;
  top: 24rpx;
  text-align: center;
}

.record-main {
  color: #fff;
  font-size: 24rpx;
  line-height: 30rpx;
}

.record-main-highlight {
  color: #e7ba80;
}

.record-sub-row {
  margin-top: 4rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.record-sub-text {
  color: #ffd947;
  font-size: 24rpx;
  height: 30rpx;
  line-height: 30rpx;
}

.record-arrow {
  width: 24rpx;
}

.radar-board {
  position: relative;
  width: 100%;
  height: 514rpx;
}

.radar-label {
  position: absolute;
  color: rgba(255, 255, 255, 0.78);
  font-size: 28rpx;
  line-height: 40rpx;
}

.radar-label-top {
  left: 350rpx;
  top: 14rpx;
  transform: translateX(-50%);
  opacity: 0.5;
}

.radar-label-right {
  right: 77rpx;
  top: 190rpx;
  opacity: 0.5;
}

.radar-label-bottom-right {
  right: 170rpx;
  bottom: 18rpx;
  opacity: 0.5;
}

.radar-label-bottom-left {
  left: 170rpx;
  bottom: 18rpx;
  opacity: 0.5;
}

.radar-label-left {
  left: 75rpx;
  top: 180rpx;
  opacity: 0.5;
}

.radar-figure {
  position: absolute;
  left: 50%;
  top: 54rpx;
  transform: translateX(-50%);
  overflow: visible;
}

.radar-grid-image,
.radar-canvas {
  position: absolute;
  left: 0;
  top: 0;
}

.radar-mascot {
  position: absolute;
  right: 38rpx;
  top: 0;
  width: 92rpx;
}

.featured-card {
  position: relative;
  width: 100%;
  height: 150rpx;
  margin-top: 70rpx;
  border-radius: 16rpx;
  overflow: hidden;
}

.featured-card-bg {
  width: 100%;
}

.featured-card-mask {
  position: absolute;
  left: 0;
  top: 0;
  width: 278rpx;
  height: 150rpx;
  background: linear-gradient(90deg, #ffdaa0 0%, #f5c580 74%, rgba(245, 197, 128, 0) 100%);
}

.featured-card-copy {
  position: absolute;
  left: 30rpx;
  top: 34rpx;
  display: flex;
  flex-direction: column;
}

.featured-card-title {
  display: block;
  color: #895409;
  font-size: 34rpx;
  font-family: "AlimamaShuHeiTi-Bold", "PingFang SC", sans-serif;
  font-weight: 700;
  line-height: 42rpx;
}

.featured-card-subtitle {
  display: block;
  margin-top: 10rpx;
  color: #895409;
  font-size: 22rpx;
  line-height: 32rpx;
  opacity: 0.72;
}

.mode-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16rpx 18rpx;
  margin-top: 16rpx;
}

.mode-card {
  position: relative;
  height: 150rpx;
  box-shadow: inset 2rpx 2rpx 6rpx 0rpx rgba(255, 255, 255, 0.27);
  border-radius: 16rpx;
  border: 2rpx solid rgba(235, 184, 123, 0.5);
  background: rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

.mode-tag {
  position: absolute;
  left: 0;
  top: 0;
  width: 72rpx;
  height: 34rpx;
  line-height: 34rpx;
  text-align: center;
  font-size: 20rpx;
  color: #000;
  border-bottom-right-radius: 16rpx;
  background: linear-gradient(133deg, #ffd19a 0%, #a17636 100%);
}

.mode-card-copy {
  position: absolute;
  left: 30rpx;
  top: 40rpx;
}

.mode-card-title {
  display: block;
  background-image: linear-gradient(
    133deg,
    rgba(235, 184, 123, 0.8) 0%,
    rgba(181, 140, 78, 0.8) 100%
  );
  color: #e7ba80;
  font-size: 32rpx;
  font-family: "AlimamaShuHeiTi-Bold", "PingFang SC", sans-serif;
  font-weight: 700;
  line-height: 38rpx;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.mode-card-title-image {
  display: block;
  width: 128rpx;
}

.mode-card-progress {
  display: block;
  margin-top: 14rpx;
  color: #fcce96;
  font-size: 22rpx;
  line-height: 32rpx;
  opacity: 0.5;
}

.mode-card-icon {
  position: absolute;
  right: 12rpx;
  top: 14rpx;
  width: 124rpx;
  height: 124rpx;
}
</style>
