<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
import { onShow, onShareAppMessage, onShareTimeline } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import PointRecord from "@/components/PointRecord.vue";
import RingBarChart from "@/components/RingBarChart.vue";
import SModal from "@/components/SModal.vue";
import Signin from "@/components/Signin.vue";
import ScreenHint2 from "@/components/ScreenHint2.vue";
import RewardUs from "@/components/RewardUs.vue";

import {
  getHomeData,
  getPointBookConfigAPI,
  getPointBookListAPI,
  getPointBookStatisticsAPI,
  removePointRecord,
} from "@/apis";

import { getElementRect } from "@/util";

import { generateKDEHeatmapImage } from "@/kde-heatmap";

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

const isIOS = computed(() => {
  const systemInfo = uni.getDeviceInfo();
  return systemInfo.osName === "ios";
});

const loadImage = ref(false);
const showModal = ref(false);
const showTip = ref(false);
const showTip2 = ref(false);
const data = ref({
  weeksCheckIn: [],
});

const list = ref([]);
const bowTargetSrc = ref("");
const heatMapImageSrc = ref(""); // 存储热力图图片地址
const canvasVisible = ref(false); // 控制canvas显示状态
const removeId = ref("");

const toListPage = () => {
  uni.navigateTo({
    url: "/pages/point-book-list",
  });
};

const onSignin = () => {
  showModal.value = true;
};

const startScoring = () => {
  if (user.value.id) {
    const draft = uni.getStorageSync("last-point-record");
    if (draft) {
      showTip2.value = true;
      return;
    }
    toScorePage();
  } else {
    showModal.value = true;
  }
};

const toScorePage = (withDraft) => {
  showTip2.value = false;
  if (withDraft) {
    return uni.navigateTo({
      url: "/pages/point-book-edit?withDraft=true",
    });
  }
  uni.removeStorageSync("last-point-record");
  return uni.navigateTo({
    url: "/pages/point-book-create",
  });
};

const closeHint = () => {
  showTip.value = false;
  showTip2.value = false;
};

const loadData = async () => {
  const result = await getPointBookListAPI(1);
  list.value = result.slice(0, 3);
  const result2 = await getPointBookStatisticsAPI();
  data.value = result2;

  const rect = await getElementRect(".heat-map");
  let hot = 0;
  if (result2.checkInCount > -3 && result2.checkInCount < 3) hot = 1;
  else if (result2.checkInCount >= 3) hot = 2;
  else if (result2.checkInCount >= 5) hot = 3;
  else if (result2.checkInCount === 7) hot = 4;
  uni.$emit("update-hot", hot);
  loadImage.value = true;
  const generateHeatmapAsync = async () => {
    const weekArrows = result2.weekArrows
      .filter((item) => item.x && item.y)
      .map((item) => [item.x, item.y]);

    try {
      // 渐进式渲染：数据量大时先快速渲染粗略版本
      if (weekArrows.length > 1000) {
        const quickPath = await generateKDEHeatmapImage(
          "heatMapCanvas",
          rect.width,
          rect.height,
          weekArrows
        );
        heatMapImageSrc.value = quickPath;
        // 延迟后再渲染精细版本
        await new Promise((resolve) => setTimeout(resolve, 500));
      }

      // 渲染最终精细版本
      const finalPath = await generateKDEHeatmapImage(
        "heatMapCanvas",
        rect.width,
        rect.height,
        weekArrows,
        {
          range: [0, 1],
          gridSize: 120, // 更高的网格密度，减少锯齿
          bandwidth: 0.15, // 稍小的带宽，让热力图更细腻
          showPoints: false,
        }
      );
      heatMapImageSrc.value = finalPath;
      loadImage.value = false;
      console.log("热力图图片地址:", finalPath);
    } catch (error) {
      console.error("生成热力图图片失败:", error);
      loadImage.value = false;
    }
  };

  // 异步生成热力图，不阻塞UI
  generateHeatmapAsync();
};

watch(
  () => user.value.id,
  (id) => {
    if (id) loadData();
  }
);

onShow(async () => {
  uni.removeStorageSync("point-book");
  if (user.value.id) loadData();
});

onMounted(async () => {
  uni.$on("point-book-signin", onSignin);
  const token = uni.getStorageSync(
    `${uni.getAccountInfoSync().miniProgram.envVersion}_token`
  );
  if (!user.value.id && token) {
    const data = await getHomeData();
    if (data.user) updateUser(data.user);
  }
  const config = await getPointBookConfigAPI();
  uni.setStorageSync("point-book-config", config);
  if (config.targetOption && config.targetOption[0]) {
    bowTargetSrc.value = config.targetOption[0].icon;
  }
});

onBeforeUnmount(() => {
  uni.$off("point-book-signin", onSignin);
});

onShareAppMessage(() => {
  return {
    title: "高效记录每一次射箭，深度分析助你提升！",
    path: "pages/point-book",
    imageUrl:
      "https://static.shelingxingqiu.com/attachment/2025-09-22/dcz4m4nbgycqqwknrv.png",
  };
});
onShareTimeline(() => {
  return {
    title: "高效记录每一次射箭，深度分析助你提升！",
    query: "from=timeline",
    imageUrl:
      "https://static.shelingxingqiu.com/attachment/2025-09-22/dcz4m4nbgycqqwknrv.png",
  };
});
</script>

<template>
  <Container :bgType="4" bgColor="#F5F5F5" :whiteBackArrow="false" title="">
    <view class="container">
      <view class="daily-signin">
        <view>
          <image src="../static/week-check.png" />
        </view>
        <view :class="data.weeksCheckIn[0] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[0]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周一</text>
        </view>
        <view :class="data.weeksCheckIn[1] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[1]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周二</text>
        </view>
        <view :class="data.weeksCheckIn[2] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[2]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周三</text>
        </view>
        <view :class="data.weeksCheckIn[3] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[3]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周四</text>
        </view>
        <view :class="data.weeksCheckIn[4] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[4]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周五</text>
        </view>
        <view :class="data.weeksCheckIn[5] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[5]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周六</text>
        </view>
        <view :class="data.weeksCheckIn[6] ? 'checked' : ''">
          <image
            v-if="data.weeksCheckIn[6]"
            src="../static/checked-green2.png"
            mode="widthFix"
          />
          <view v-else></view>
          <text>周日</text>
        </view>
      </view>
      <view class="statistics">
        <view>
          <text>{{ data.todayTotalArrow || "-" }}</text>
          <text>今日射箭(箭)</text>
        </view>
        <view>
          <text>{{ data.totalArrow || "-" }}</text>
          <text>累计射箭(箭)</text>
        </view>
        <view>
          <text>{{ data.totalDay || "-" }}</text>
          <text>已训练天数(天)</text>
        </view>
        <view>
          <text>{{ data.averageRing || "-" }}</text>
          <text>平均环数(箭)</text>
        </view>
        <view>
          <text>{{
            data.yellowRate !== undefined
              ? Number((data.yellowRate * 100).toFixed(2)) + "%"
              : "-"
          }}</text>
          <text>黄心率</text>
        </view>
        <view>
          <button hover-class="none" @click="startScoring">
            <image src="../static/start-scoring.png" mode="widthFix" />
          </button>
        </view>
      </view>
      <view class="title" :style="{ marginBottom: 0 }">
        <image src="../static/point-book-title1.png" mode="widthFix" />
      </view>
      <view class="heat-map">
        <image
          :src="bowTargetSrc || '../static/bow-target.png'"
          mode="widthFix"
        />
        <image
          v-if="heatMapImageSrc"
          :src="heatMapImageSrc"
          mode="aspectFill"
        />
        <view v-if="loadImage" class="load-image">
          <text>生成中...</text>
        </view>
        <canvas
          id="heatMapCanvas"
          type="2d"
          style="
            width: 100%;
            height: 100%;
            position: absolute;
            top: -1000px;
            left: 0;
            z-index: 2;
          "
        />
      </view>
      <view class="reward" v-if="data.totalArrow">
        <button hover-class="none" @click="showTip = true">
          <image src="../static/reward-us.png" mode="widthFix" />
        </button>
      </view>
      <RingBarChart :data="data.ringRate" v-if="user.id" />
      <view class="title" v-if="user.id">
        <image src="../static/point-book-title2.png" mode="widthFix" />
      </view>
      <block v-for="(item, index) in list" :key="item.id">
        <PointRecord :data="item" />
        <view
          v-if="index < list.length - 1"
          :style="{ height: '25rpx' }"
        ></view>
      </block>
      <view
        class="see-more"
        @click="toListPage"
        v-if="list.length"
        :style="{ marginBottom: isIOS ? '10rpx' : 0 }"
      >
        <text>查看所有记录</text>
        <image src="../static/enter-arrow-blue.png" mode="widthFix" />
      </view>
    </view>
    <SModal :show="showModal" :onClose="() => (showModal = false)" :noBg="true">
      <Signin :onClose="() => (showModal = false)" :noBg="true" />
    </SModal>
    <ScreenHint2 :show="showTip || showTip2" :onClose="closeHint">
      <RewardUs
        v-if="showTip"
        :show="showTip"
        :onClose="() => (showTip = false)"
      />
      <view class="tip-content" v-if="showTip2">
        <text>发现未完成的记分，是否继续编辑？</text>
        <view>
          <button hover-class="none" @click="toScorePage(false)">
            重新计分
          </button>
          <button hover-class="none" @click="toScorePage(true)">
            继续编辑
          </button>
        </view>
      </view>
    </ScreenHint2>
  </Container>
</template>

<style scoped>
.container {
  width: calc(100% - 50rpx);
  padding: 25rpx;
}
.statistics {
  border-radius: 25rpx;
  border-bottom-left-radius: 50rpx;
  border-bottom-right-radius: 50rpx;
  border: 4rpx solid #fed848;
  background: #fff;
  font-size: 22rpx;
  display: flex;
  flex-wrap: wrap;
  padding: 25rpx 0;
  margin-bottom: 10rpx;
}
.statistics > view {
  width: 33.33%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.statistics > view:nth-child(-n + 3) {
  margin-bottom: 25rpx;
}
.statistics > view:nth-child(2),
.statistics > view:nth-child(5) {
  border-left: 1rpx solid #eeeeee;
  border-right: 1rpx solid #eeeeee;
  box-sizing: border-box;
}
.statistics > view > text {
  text-align: center;
  font-size: 22rpx;
  color: #333333;
}
.statistics > view > text:first-child {
  font-weight: 500;
  font-size: 40rpx;
  margin-bottom: 10rpx;
}
.statistics > view:last-child > button > image {
  width: 164rpx;
}
.daily-signin {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 10rpx;
  border-radius: 20rpx;
  margin-bottom: 25rpx;
}
.daily-signin > view {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 12rpx;
  box-sizing: border-box;
}
.daily-signin > view:not(:first-child) {
  background: #f8f8f8;
  box-sizing: border-box;
  width: 78rpx;
  height: 94rpx;
  padding-top: 10rpx;
}
.daily-signin > view:not(:first-child) > image {
  width: 32rpx;
  height: 32rpx;
}
.daily-signin > view:not(:first-child) > view {
  width: 32rpx;
  height: 32rpx;
  border-radius: 50%;
  box-sizing: border-box;
  border: 2rpx solid #333;
}
.daily-signin > view > text {
  font-size: 20rpx;
  color: #999999;
  font-weight: 500;
  text-align: center;
  margin-top: 10rpx;
}
.daily-signin > view:first-child > image {
  width: 72rpx;
  height: 94rpx;
}
.checked {
  border: 2rpx solid #000;
}
.checked > text {
  color: #333 !important;
}
.title {
  width: 100%;
  display: flex;
  justify-content: center;
  margin: 25rpx 0;
}
.title > image {
  width: 566rpx;
}
.heat-map {
  position: relative;
  margin: 0 auto;
  width: calc(100vw - 70rpx);
  height: calc(100vw - 70rpx);
  transform: scale(0.9);
  border-radius: 50%;
  overflow: hidden;
}
.heat-map > image {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
.load-image {
  position: absolute;
  width: 160rpx;
  top: calc(50% - 65rpx);
  left: calc(50% - 75rpx);
  color: #525252;
  font-size: 20rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.reward {
  width: 100%;
  display: flex;
  justify-content: flex-end;
  margin-top: -120rpx;
  position: relative;
  z-index: 10;
}
.reward > button {
  width: 100rpx;
}
.reward > button > image {
  width: 100%;
  height: 100%;
}
.tip-content {
  width: 100%;
  padding: 25px;
  display: flex;
  flex-direction: column;
  color: #000;
}
.tip-content > text {
  width: 100%;
  text-align: center;
  font-size: 14px;
  margin-top: 5px;
}
.tip-content > view {
  display: flex;
  justify-content: space-between;
  margin-top: 20px;
}
.tip-content > view > button {
  width: 48%;
  background: linear-gradient(180deg, #fbfbfb 0%, #f5f5f5 100%);
  border-radius: 22px;
  border: 1px solid #eeeeee;
  padding: 12px 0;
  font-size: 14px;
  color: #000;
}
.tip-content > view > button:last-child {
  background: #fed847;
}
</style>
