<template>
  <div style="padding: 4vw 0">
    <div
      style="
        min-height: 18.54vw;
        width: 100vw;
        padding: 0 4vw;

        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 10vw;
      "
    >
      <div style="flex: 1; min-width: 0" @click="changeTag('weekly')">
        <img
          v-show="weeklyShow"
          v-smart-img
          :src="webpUrl(getImgName('rankingWeeklyBtActive'))"
          alt=""
          style="width: 100%; display: block; object-fit: cover"
        />
        <img
          v-show="!weeklyShow"
          v-smart-img
          :src="webpUrl(getImgName('rankingWeeklyBt'))"
          alt=""
          style="width: 100%; display: block; object-fit: cover"
        />
      </div>

      <div style="flex: 1; min-width: 0" @click="changeTag('season')">
        <img
          v-show="seasonShow"
          v-smart-img
          :src="webpUrl(getImgName('rankingSeasonBtActive'))"
          alt=""
          style="width: 100%; display: block; object-fit: cover"
        />
        <img
          v-show="!seasonShow"
          v-smart-img
          :src="webpUrl(getImgName('rankingSeasonBt'))"
          alt=""
          style="width: 100%; display: block; object-fit: cover"
        />
      </div>
    </div>

    <itemCenter
      style="min-height: 31.33vw"
      :imgUrl="webpUrl(`timeBg`)"
      :contentStyle="`inset:0 0 4vw;`"
    >
      <div v-show="weeklyShow" style="display: flex; justify-content: center; align-items: center">
        <div class="timeBox">
          <div class="timeText" style="">{{ WDays }}D</div>
          <div class="timeText timeGap"></div>
          <div class="timeText" style="">{{ WHours }}</div>
          <div class="timeText timeGap">:</div>
          <div class="timeText" style="">{{ WMinutes }}</div>
          <div class="timeText timeGap">:</div>
          <div class="timeText" style="">{{ WSeconds }}</div>
        </div>
      </div>
      <div v-show="seasonShow" style="display: flex; justify-content: center; align-items: center">
        <div class="timeBox">
          <div class="timeText" style="">{{ MDays }}D</div>
          <div class="timeText timeGap"></div>
          <div class="timeText" style="">{{ MHours }}</div>
          <div class="timeText timeGap">:</div>
          <div class="timeText" style="">{{ MMinutes }}</div>
          <div class="timeText timeGap">:</div>
          <div class="timeText" style="">{{ MSeconds }}</div>
        </div>
      </div>
    </itemCenter>

    <div style="position: relative; display: flex; flex-direction: column; gap: 2vw">
      <img v-smart-img :src="webpUrl('helpBt')" alt="" class="helpBt" @click="helpShow = true" />

      <itemCenter
        style="width: 9vw"
        class="rankingBg"
        :imgUrl="webpUrl(`top1RankingBg`)"
        :flip="true"
        :contentStyle="``"
      >
        <img v-smart-img :src="webpUrl('num1')" alt="" style="width: 3vw; display: block" />
      </itemCenter>

      <div style="margin-top: 2vw; display: flex; flex-direction: column; gap: 2vw">
        <TopUser
          :style="{ minHeight: index == 0 ? '58.51vw' : '39.07vw' }"
          v-for="(value, index) in 3"
          :ranking="index + 1 + ''"
          :rankingItem="RankingHasTop3[index] || {}"
          :rewards="showRewardsTop3[index] || {}"
        />
      </div>

      <itemCenter
        style="min-height: 25.92vw"
        v-for="item in showRanking"
        :imgUrl="webpUrl(`rankingItemBg`)"
        :flip="true"
        :contentStyle="`padding: 0 5%;justify-content: flex-start;`"
      >
        <itemCenter
          style="width: 9vw"
          :imgUrl="webpUrl(`top1RankingBg`)"
          :flip="true"
          :contentStyle="``"
        >
          <div class="rankingText">
            <img
              v-smart-img
              v-for="(digit, index) in getRankDigits(item.rank)"
              :src="getDigitImageUrl(digit)"
              style="display: block; width: 3vw; object-fit: cover"
            />
          </div>
        </itemCenter>

        <div style="width: 36vw">
          <div
            style="
              width: 100%;
              padding: 3vw 5vw;
              height: 80%;
              display: flex;
              justify-content: space-between;
              align-items: center;

              position: relative;
            "
          >
            <div
              style="
                position: absolute;
                z-index: 9;
                inset: 0;
                display: flex;
                justify-content: center;
                align-items: center;
              "
            >
              <div
                style="flex: 1; min-width: 0; align-self: stretch"
                @click="viewUserInfo(item.userId)"
              ></div>
              <div
                style="flex: 1; min-width: 0; align-self: stretch"
                @click="viewUserInfo(item.cpUserId)"
              ></div>
            </div>

            <div
              style="
                position: absolute;
                inset: 0;
                display: flex;
                justify-content: center;
                align-items: center;
              "
            >
              <img
                v-smart-img
                :src="webpUrl(`rankingCoupleSign`)"
                alt=""
                style="width: 15vw; display: block; object-fit: cover"
              />
            </div>

            <img
              :src="item.userAvatar || ''"
              alt=""
              style="
                display: block;
                min-width: 0;
                width: 12vw;
                object-fit: cover;
                aspect-ratio: 1/1;
                border-radius: 50%;
                border: 1px solid #fefa9f;
              "
              @error="handleAvatarImageError"
            />
            <img
              :src="item.cpUserAvatar || ''"
              alt=""
              style="
                display: block;
                min-width: 0;
                width: 12vw;
                object-fit: cover;
                aspect-ratio: 1/1;
                border-radius: 50%;
                border: 1px solid #fefa9f;
              "
              @error="handleAvatarImageError"
            />
          </div>
        </div>

        <div
          style="
            flex: 1;
            min-width: 0;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            gap: 1vw;
          "
        >
          <div style="width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">
            {{ item.userNickname || '' }}
          </div>
          <div style="width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">
            {{ item.cpUserNickname || '' }}
          </div>
        </div>

        <div style="width: auto; min-width: 0; display: flex; align-items: center">
          <img
            v-smart-img
            :src="webpUrl('distribution')"
            alt=""
            style="width: 10vw; display: block; object-fit: cover"
          />
          <div style="font-weight: 700">{{ item.total || '0' }}</div>
        </div>
      </itemCenter>
    </div>
  </div>
</template>

<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLangStore } from '@/stores/lang'
import { useI18n } from 'vue-i18n'
import { getWebpUrl } from '@/config/imagePaths.js'
import { setUserInfo } from '@/utils/userStore.js'
import { viewUserInfo } from '@/utils/appBridge.js'
import { connectToApp } from '@/utils/appConnector.js'
import { preloadImages } from '@/utils/image/imagePreloader.js'
import { formatUTCCustom } from '@/utils/utcFormat.js'
import { showError, showSuccess } from '@/utils/toast.js'
import { handleAvatarImageError, handleRewardImageError } from '@/utils/image/imageHandler.js'
import { useCoupleStore } from '@/stores/couple'
import { storeToRefs } from 'pinia'

import { apiGetCpRanking, apiGetCpRewardPool } from '@/api/couple.js'
import TopUser from './components/topUser.vue'
import itemCenter from '@/components/itemCenter.vue'
import maskLayer from '@/components/MaskLayer.vue'

const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const coupleStore = useCoupleStore()

const langStore = useLangStore()
// 当前语言
const currentLangType = computed(() => {
  return langStore.selectedLang?.type || 'en'
})

const isLoading = ref(true) // 预加载状态
const webpUrl = (filename) => getWebpUrl('Ranking/Couple/webp/', filename)

const getImgName = (filename) => {
  return currentLangType.value === 'ar' ? `${filename}_ar` : filename
}

const {
  helpShow, // 帮助弹窗
  myRanking, // 当前用户排名
} = storeToRefs(coupleStore)

const WDays = ref(0)
const WHours = ref(0)
const WMinutes = ref(0)
const WSeconds = ref(0)
let countdownTimer = null

const MDays = ref(0)
const MHours = ref(0)
const MMinutes = ref(0)
const MSeconds = ref(0)
let monthlyCountdownTimer = null // 月榜倒计时定时器

// 获取北京时间下一个周榜重置时间戳
const getNextWeekInBeijing = () => {
  const now = new Date()
  const targetDate = new Date(now.getTime())
  const utcTime = now.getTime() + now.getTimezoneOffset() * 60000
  const beijingTime = new Date(utcTime + 8 * 3600000) // 北京时间为 UTC+8

  const beijingDay = beijingTime.getDay() // 0=周日，1=周一，...，6=周六
  const beijingHour = beijingTime.getHours()

  // 归一化到周一为 0，周日为 6
  const normalizedDay = beijingDay === 0 ? 6 : beijingDay - 1

  let daysToAdd
  if (normalizedDay === 0) {
    // 周一
    if (beijingHour >= 5) {
      daysToAdd = 7
    } else {
      daysToAdd = 0
    }
  } else {
    daysToAdd = 7 - normalizedDay
  }

  targetDate.setDate(targetDate.getDate() + daysToAdd)
  targetDate.setHours(5, 0, 0, 0)
  return targetDate.getTime()
}

const targetTime = ref(getNextWeekInBeijing()) // 当前周榜目标时间戳

const formatTime = (value) => {
  return value < 10 ? `0${value}` : value
}

const getCountdown = () => {
  const now = Date.now()
  let diff = targetTime.value - now

  if (diff <= 0) {
    initData()

    targetTime.value += 7 * 86400000
    diff = targetTime.value - now
  }

  const totalSeconds = Math.floor(diff / 1000)
  WDays.value = Math.floor(totalSeconds / (24 * 3600))
  WHours.value = formatTime(Math.floor((totalSeconds % (24 * 3600)) / 3600))
  WMinutes.value = formatTime(Math.floor((totalSeconds % 3600) / 60))
  WSeconds.value = formatTime(Math.floor(totalSeconds % 60))
}

const startCountdown = () => {
  getCountdown()
  getMonthlyCountdown()
  countdownTimer = setInterval(getCountdown, 1000)
  monthlyCountdownTimer = setInterval(getMonthlyCountdown, 1000)
}

// 获取北京时间下一个月榜结算时间戳
const getNextMonthFirstInBeijing = () => {
  const now = new Date()
  const zodiacCutoffDates = [
    [1, 20],
    [2, 19],
    [3, 21],
    [4, 20],
    [5, 21],
    [6, 22],
    [7, 23],
    [8, 23],
    [9, 23],
    [10, 23],
    [11, 22],
    [12, 22],
  ]

  const beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000)
  const currentYear = beijingTime.getUTCFullYear()
  const currentMonth = beijingTime.getUTCMonth() + 1
  const currentDate = beijingTime.getUTCDate()
  const currentHour = beijingTime.getUTCHours()

  let targetDate = null
  let targetYear = currentYear

  for (const [cutoffMonth, cutoffDate] of zodiacCutoffDates) {
    if (
      currentMonth < cutoffMonth ||
      (currentMonth === cutoffMonth && currentDate < cutoffDate) ||
      (currentMonth === cutoffMonth && currentDate === cutoffDate && currentHour < 5)
    ) {
      targetDate = [cutoffMonth, cutoffDate]
      break
    }
  }

  if (!targetDate) {
    targetDate = [1, 20]
    targetYear = currentYear + 1
  }

  return Date.UTC(targetYear, targetDate[0] - 1, targetDate[1], 5, 0, 0) - 8 * 60 * 60 * 1000
}

const getMonthlyCountdown = () => {
  const now = Date.now()
  let diff = targetMonthTime.value - now

  if (diff <= 0) {
    // 当前时间已过期时，切到下一个月榜目标时间
    targetMonthTime.value = getNextMonthFirstInBeijing()
    diff = targetMonthTime.value - now
  }

  const totalSeconds = Math.floor(diff / 1000)

  // 总剩余天数
  const totalDays = Math.floor(totalSeconds / (24 * 3600))
  MDays.value = totalDays

  const remainingHours = Math.floor((totalSeconds % (24 * 3600)) / 3600)
  MHours.value = formatTime(remainingHours)

  const remainingMinutes = Math.floor((totalSeconds % 3600) / 60)
  MMinutes.value = formatTime(remainingMinutes)

  const remainingSeconds = totalSeconds % 60
  MSeconds.value = formatTime(remainingSeconds)
}

// 月榜目标时间戳
const targetMonthTime = ref(getNextMonthFirstInBeijing())

const weeklyShow = ref(true) // 周榜标签
const seasonShow = ref(false) // 月榜标签

const changeTag = (module) => {
  switch (module) {
    case 'weekly':
      if (weeklyShow.value) return
      weeklyShow.value = true
      seasonShow.value = false
      apiGetRanking()
      apiGetTop3Rewards()
      break
    case 'season':
      if (seasonShow.value) return
      weeklyShow.value = false
      seasonShow.value = true
      apiGetRanking()
      apiGetTop3Rewards()
      break
  }
}

const rewardsTop3 = ref([]) // 前三奖励配置
const showRewardsTop3 = computed(() => {
  // 先拷贝一份，避免直接改动原始奖励列表
  let newRewardsTop3 = JSON.parse(JSON.stringify(rewardsTop3.value))
  if (seasonShow.value) {
    newRewardsTop3[0].activityRewardProps.push(
      {
        cover: '',
        content: 'Banner*30Days',
        quantity: 0,
        type: 'GIFT',
      },
      {
        cover: '',
        content: 'ID: 7 digits * 1',
        quantity: 0,
        type: 'GIFT',
      },
    )
  }
  // 周榜额外奖励
  else {
    newRewardsTop3[0]?.activityRewardProps.push(
      {
        cover: new URL('/src/assets/icon/Aslan/coin.png', import.meta.url).href,
        content: t('heartbeat_value_points_4_percent', {
          amount: formatLargeNumber(Number(RankingHasTop3.value[0]?.totalNumber) * 0.04),
        }),
        quantity: 0,
        type: 'GIFT',
      },
      {
        cover: '',
        content: 'Homepage Ad* 7 days',
        quantity: 0,
        type: 'GIFT',
      },
    )
    newRewardsTop3[1]?.activityRewardProps.push({
      cover: new URL('/src/assets/icon/Aslan/coin.png', import.meta.url).href,
      content: t('heartbeat_value_points_3_percent', {
        amount: formatLargeNumber(Number(RankingHasTop3.value[1]?.totalNumber) * 0.03),
      }),
      quantity: 0,
      type: 'GIFT',
    })
    newRewardsTop3[2]?.activityRewardProps.push({
      cover: new URL('/src/assets/icon/Aslan/coin.png', import.meta.url).href,
      content: t('heartbeat_value_points_2_percent', {
        amount: formatLargeNumber(Number(RankingHasTop3.value[2]?.totalNumber) * 0.02),
      }),
      quantity: 0,
      type: 'GIFT',
    })
  }

  return newRewardsTop3
})

const Ranking = ref([]) // 原始排行榜数据

const RankingHasTop3 = computed(() => {
  let RankingShow = [...Ranking.value]
  if (Ranking.value.length < 3) {
    let addNullUser = Array.from({ length: 3 - Ranking.value.length }, () => ({
      rank: '',

      userAvatar: '',
      userId: '',
      userNickname: '',
      userSex: '',

      cpUserAvatar: '',
      cpUserId: '',
      cpUserNickname: '',
      cpUserSex: '',

      total: '0',
      totalNumber: '0',
    }))
    RankingShow.push(...addNullUser)
  }
  return RankingShow
})

// 渲染前三之外的排行榜列表
const showRanking = computed(() => {
  return Ranking.value.filter((_, index) => index >= 3)
})

const getRankDigits = (rank) => {
  return String(rank).split('')
}

// 根据名次数字获取对应的数字图片
const getDigitImageUrl = (digit) => {
  if (/^[0-9]$/.test(digit)) {
    return webpUrl(`num${digit}`)
  }
  return ''
}

// 奖励文案使用的大数字格式化
const formatLargeNumber = (num) => {
  if (typeof num !== 'number' || isNaN(num)) {
    return '0'
  }

  const absNum = Math.abs(num)

  if (absNum >= 1000000) {
    const millionValue = num / 1000000
    const roundedValue = Math.round(millionValue * 100) / 100
    return roundedValue.toFixed(2) + 'M'
  } else if (absNum >= 1000) {
    const thousandValue = num / 1000
    const roundedValue = Math.round(thousandValue * 100) / 100
    return roundedValue.toFixed(2) + 'K'
  } else {
    return Math.floor(num).toString()
  }
}

// 获取排行榜数据
const apiGetRanking = async () => {
  let type = weeklyShow.value ? 'WEEK' : 'SEASON'
  try {
    const response = await apiGetCpRanking(type)
    if (response.status && response.body) {
      Ranking.value = response.body.thisWeekUserTop || []
      myRanking.value = response.body.thisUser || {}
    }
  } catch (error) {
    showError(error.response.errorMsg)
  }
}

const apiGetTop3Rewards = async () => {
  let type = weeklyShow.value ? 'WEEK_CP_GIFT' : 'SEASON_CP_GIFT'
  try {
    const response = await apiGetCpRewardPool(type)
    if (response.status && response.body) {
      let rewards = response.body

      rewardsTop3.value = response.body || []
    }
  } catch (error) {
    showError(error.response.errorMsg)
  }
}

const initData = async () => {
  await Promise.all([apiGetRanking(), apiGetTop3Rewards()])
}

const preloadCriticalImages = async () => {
  const criticalImages = []

  const criticalImages_ar = []

  if (currentLangType.value == 'en') {
    await preloadImages(criticalImages)
  } else if (currentLangType.value == 'ar') {
    await preloadImages(criticalImages_ar)
  }
}

const completePreloading = async () => {
  try {
    // 首次进入时并行拉取数据和预加载图片
    await Promise.all([initData(), preloadCriticalImages()])
    console.log('Ranking preload completed')
  } catch (error) {
    console.error('Failed during ranking preload:', error)
  } finally {
    isLoading.value = false
  }
}

// 连接宿主 App
const connectToAppHandler = async () => {
  await connectToApp(() => {
    completePreloading()
  })
}

onMounted(() => {
  startCountdown()
  connectToAppHandler()
})

onUnmounted(() => {
  // 清理倒计时定时器
  if (countdownTimer) {
    clearInterval(countdownTimer)
    countdownTimer = null
  }
  if (monthlyCountdownTimer) {
    clearInterval(monthlyCountdownTimer)
    monthlyCountdownTimer = null
  }
})
</script>

<style lang="scss" scoped>
.timeBox {
  width: 50vw;
  display: flex;
  justify-content: center;
}

.timeText {
  color: #fff;
  font-weight: 590;
  font-size: 2em;
  margin-top: 1vw;

  background: linear-gradient(
    180deg,
    #ffdf6b 31.61%,
    #ffe562 36.73%,
    #fff 52.37%,
    #ffe562 58.67%,
    #ffa615 72.2%
  );
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.timeGap {
  width: 6px;
  align-self: stretch;

  display: flex;
  justify-content: center;
  align-items: center;
}

[dir='rtl'] .timeBox {
  flex-direction: row-reverse;
}

.helpBt {
  display: block;
  width: 8vw;
  object-fit: cover;
  position: absolute;
  z-index: 3;
  top: 2vw;
  right: 3vw;
}

[dir='rtl'] .helpBt {
  right: unset;
  left: 3vw;
}

.rankingBg {
  position: absolute;
  z-index: 3;
  top: 6vw;
  left: 3vw;
}

.rankingText {
  width: 100%;
  height: 100%;

  display: flex;
  justify-content: center;
  align-items: center;
}

[dir='rtl'] .rankingText {
  flex-direction: row-reverse;
}

[dir='rtl'] .rankingBg {
  left: unset;
  right: 3vw;
}
</style>
