<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted } from "vue";
import DesignStage from "../../../components/DesignStage.vue";
import type Player from "@/commons/player.ts";
import { $format_str, $is_run_local } from "@/commons/utils.ts";
import { cssAssetUrl, assetUrl } from "@/commons/assets.ts";

const props = defineProps<{
  rankList: Player[];
}>();

const emit = defineEmits<{
  start: [];
  next: [];
}>();

const RANK_LIMIT = 10;
const designStage = ref<InstanceType<typeof DesignStage> | null>(null);
const rankEffects = ref<Record<string, "up" | "down" | "new">>({});
const gameStarted = ref(false);
const showResult = ref(false);

const imageUrls = {
  runway: cssAssetUrl("game5/paodao.webp"),
  bg: cssAssetUrl("game5/bg-backup.webp"),
  logo: cssAssetUrl("game1/logo.png"),
  title: cssAssetUrl("game5/title3.webp"),
  rankNo4: cssAssetUrl("game6/no4.png"),
  rankNo1: cssAssetUrl("game6/no1.png"),
  rankNo2: cssAssetUrl("game6/no2.png"),
  rankNo3: cssAssetUrl("game6/no3.png"),
  avatar: cssAssetUrl("avatar-yellow.png"),
  avatarAnimation: cssAssetUrl("avatar-yellow_animation.png"),
  rankContainer: cssAssetUrl("game6/rank-container.png"),
};

// ========== 马匹相关 ==========
const HORSE_TYPES = [1, 2, 3, 4] as const;
const HORSE_FRAME_COUNT = 21; // 每匹马 21 帧（00-20）
const HORSE_WIDTH = 200;
const HORSE_START_X = -100; // 左侧屏外起点，进一步右移让马更快进入屏幕
const HORSE_END_X = 1920 - HORSE_WIDTH; // 右边缘贴齐屏幕右侧（1720px）


// 预构建四种马的帧 URL（与 H5 PlayingView 一致，避免运行时拼路径）
const horseFrames: Record<number, string[]> = {};
for (let h = 1; h <= 4; h++) {
  horseFrames[h] = Array.from({ length: HORSE_FRAME_COUNT }, (_, i) =>
    assetUrl(`game5/horse${h}/no-circle/qcnf-ma${h}_${String(i).padStart(2, "0")}.png`),
  );
}

interface Horse {
  id: string;
  horseType: number; // 1-4 颜色
  lane: "top" | "bottom";
  frameIndex: number; // 当前帧 0-20
  frameTimer: number; // 帧切换计时器
  startTime: number; // 开始移动的时间戳（ms）
  durationMs: number; // 跑完全程时长（ms）
  x: number; // 当前 X 位置
}

const horses = ref<Horse[]>([]);
let horseIdCounter = 0;

const isGameRunning = ref(false);
const emptyPlayer = (index: number): Player => ({
  wechat_id: `empty-${index}`,
  nickname: "虚位以待",
  avatar: "",
  score: "-",
});

const list = ref<Player[]>(
  Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)),
);
const playerKey = (player: Player, index = 0) => {
  // 优先使用 userid/wechat_id，没有则用 avatar 作为唯一标识
  const id = player.userid || player.wechat_id;
  if (id && !String(id).startsWith('empty-')) return String(id);
  
  // 如果有头像且昵称有效，用 avatar 作为唯一标识
  if (player.avatar && player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
    return `avt:${player.avatar}`;
  }
  
  return `empty-${index}`;
};

// ========== 排名更新 ==========
const updateRankList = (rankList: Player[]) => {
  const oldRanks = new Map(
    list.value.map((player, index) => [playerKey(player, index), index]),
  );
  const next = Array.from(
    { length: RANK_LIMIT },
    (_, index) => rankList[index] ?? emptyPlayer(index),
  );
  const effects: Record<string, "up" | "down" | "new"> = {};

  next.forEach((player, index) => {
    const key = playerKey(player, index);
    if (!key || key.startsWith("empty-")) return;

    const oldIndex = oldRanks.get(key);
    if (oldIndex === undefined) effects[key] = "new";
    else if (oldIndex > index) effects[key] = "up";
    else if (oldIndex < index) effects[key] = "down";
  });

  list.value = next;
  rankEffects.value = {};
  requestAnimationFrame(() => {
    rankEffects.value = effects;
  });
};

watch(
  () => props.rankList,
  (rankList) => {
    console.log('[Game5 Rank1View] watch rankList 触发，rankList:', rankList?.length, JSON.stringify(rankList?.slice(0, 3)));
    if (rankList && rankList.length > 0) {
      console.log('[Game5 Rank1View] 排名列表更新 - 数据:', JSON.stringify(rankList.map(p => ({ nickname: p.nickname, score: p.score, userid: p.userid, wechat_id: p.wechat_id }))))
      updateRankList(rankList);

    }
  },
  { immediate: true, deep: true },
);

// ========== startIntro：倒计时 + 游戏流程 ==========
const startIntro = async () => {
  showResult.value = false;
  gameStarted.value = false;
  isGameRunning.value = false;
  horses.value = [];
  horseIdCounter = 0;
  preloadHorseFrames(); // 确保马匹帧图已预加载

  console.log('[Rank1View] 游戏流程启动 - 开始 3s 倒计时 + 60s 游戏')
  // 启动完整倒计时：3s 开场 + 60s 游戏
  const countdownPromise = designStage.value?.startCountdown(3, 60);

  // 等待 3-2-1 开场倒计时结束（~3.5s 后安全触发）
  await new Promise((r) => setTimeout(r, 3500));
  console.log('[Rank1View] 倒计时结束，马匹开始奔跑')

  // Phase 2: 倒计时结束 → 游戏正式开始，背景动画+马匹启动
  gameStarted.value = true;
  isGameRunning.value = true;
  generateRandomHorses();
  startHorseLoop();

  // 等待 60s 游戏倒计时完全结束
  await countdownPromise;
  stopGame();
};

const stopGame = () => {
  console.log('[Rank1View] 游戏结束 - 60s 倒计时到')
  isGameRunning.value = false;
  showResult.value = true;
  stopHorseLoop();
};

// ========== 马匹动画循环 (RAF 仅驱动脚步切帧，位移由 CSS animation 负责) ==========
let horseRafId: number | undefined;
let horseLastTs = 0;
const HORSE_FRAME_TICK_MS = 14; // 每帧间隔 ~40fps（频率提升一倍）


const startHorseLoop = () => {
  stopHorseLoop();
  horseLastTs = 0;

  const tick = (ts: number) => {
    if (!isGameRunning.value) {
      horseRafId = requestAnimationFrame(tick);
      return;
    }
    if (!horseLastTs) horseLastTs = ts;
    const dt = Math.min(ts - horseLastTs, 200);
    horseLastTs = ts;

    for (const horse of horses.value) {
      if (ts < horse.startTime) continue;

      const elapsed = ts - horse.startTime;
      const progress = Math.min(elapsed / horse.durationMs, 1);
      horse.x = HORSE_START_X + (HORSE_END_X - HORSE_START_X) * progress;

      horse.frameTimer += dt;
      while (horse.frameTimer >= HORSE_FRAME_TICK_MS) {
        horse.frameTimer -= HORSE_FRAME_TICK_MS;
        horse.frameIndex = (horse.frameIndex + 1) % HORSE_FRAME_COUNT;
      }
    }

    horseRafId = requestAnimationFrame(tick);
  };
  horseRafId = requestAnimationFrame(tick);
};

const stopHorseLoop = () => {
  if (horseRafId) {
    cancelAnimationFrame(horseRafId);
    horseRafId = undefined;
  }
};

// ========== 自动随机生成 8-10 匹马 ==========
let gameStartTime = 0;

const generateRandomHorses = () => {
  const count = 8 + Math.floor(Math.random() * 3); // 8-10
  const lanes: ("top" | "bottom")[] = ["top", "bottom"];
  const newHorses: Horse[] = [];
  const now = performance.now();

  for (let i = 0; i < count; i++) {
    const type = HORSE_TYPES[i % HORSE_TYPES.length]!;
    const lane = lanes[i % 2]!;
    const delayMs = i * 50 + Math.random() * 50; // 大幅减少起步延迟，第一匹马几乎立刻出现
    const durationMs = (60 + Math.random() * 40) * 1000; // 60-100秒，降低速度，让马跑得更慢
    newHorses.push({
      id: `horse-${++horseIdCounter}`,
      horseType: type,
      lane,
      frameIndex: Math.floor(Math.random() * HORSE_FRAME_COUNT),
      frameTimer: 0,
      startTime: now + delayMs,
      durationMs,
      x: HORSE_START_X,
    });
  }

  horses.value = newHorses;
};


// ========== 本地模拟数据（已关闭）==========
const mockAvatars = [
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Misty',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Pepper',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Oreo',
  'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger',
];

const mockPlayers: Player[] = [
  { userid: 'local-1',  nickname: '疾风骑士',   avatar: mockAvatars[0], score: 45 },
  { userid: 'local-2',  nickname: '闪电侠',     avatar: mockAvatars[1], score: 38 },
  { userid: 'local-3',  nickname: '追风者',     avatar: mockAvatars[2], score: 30 },
  { userid: 'local-4',  nickname: '千里马',     avatar: mockAvatars[3], score: 22 },
  { userid: 'local-5',  nickname: '飞毛腿',     avatar: mockAvatars[4], score: 15 },
  { userid: 'local-6',  nickname: '烈焰驹',     avatar: mockAvatars[5], score: 52 },
  { userid: 'local-7',  nickname: '暴风战士',   avatar: mockAvatars[6], score: 41 },
  { userid: 'local-8',  nickname: '神行者',     avatar: mockAvatars[7], score: 35 },
  { userid: 'local-9',  nickname: '银鞍客',     avatar: mockAvatars[8], score: 28 },
  { userid: 'local-10', nickname: '踏雪无痕',   avatar: mockAvatars[9], score: 18 },
];

// ========== 预加载所有马匹帧图片（防止切帧时闪烁/白屏）==========
const preloadHorseFrames = () => {
  for (const frames of Object.values(horseFrames)) {
    for (const url of frames) {
      const img = new Image();
      img.src = url;
    }
  }
};

onMounted(() => {
  preloadHorseFrames();
  // 本地模拟已关闭，如需开启请取消以下注释
  // if ($is_run_local()) {
  //   updateRankList(mockPlayers);
  //   gameStarted.value = true;
  //   isGameRunning.value = true;
  //   generateRandomHorses();
  //   startHorseLoop();
  // }
});

onUnmounted(() => {
  stopGame();
  stopHorseLoop();
});

defineExpose({
  startIntro,
});

// ========== 头像渲染 ==========
const renderAvatar = (item: any | null) => {
  if (item && item.avatar) {
    return `background: url("${String(item.avatar).replace(/"/g, '\\"')}") center / cover no-repeat;`
  }
  return `background: ${imageUrls.avatar} center / cover no-repeat;`
}

// ========== rank icon 样式 ==========
const rankIcon = (index: number) => {
  const icons = [
    imageUrls.rankNo1,
    imageUrls.rankNo2,
    imageUrls.rankNo3,
  ];
  let w = 42;
  let h = 47;
  let l = -20;
  let t = -20;
  if (index <= 2) {
    w = 65;
    h = 48;
    l = -30;
    t = -20;
  }
  return {
    background: `${icons[index] ?? imageUrls.rankNo4} center / cover no-repeat`,
    width: w + 'px',
    height: h + 'px',
    left: l + 'px',
    top: t + 'px',
    lineHeight: h + 'px',
    color: index <= 2 ? 'white' : '#CC7F36',
  };
};
</script>

<template>
  <DesignStage ref="designStage">
    <div class="screen-container" :class="{ paused: !gameStarted || showResult }">
      <!-- 背景层 -->
      <div class="bg">
        <div class="img-logo"></div>
        <div class="img-title"></div>

        <div class="rank-container">
          <div v-for="(item, index) in list" :key="playerKey(item, index)">
            <div>
              <div class="rank-icon" :style="rankIcon(index)">{{ index + 1 }}</div>
              <div class="rank-item">
                <div>
                  <div class="img-avatar-container">
                    <div class="img-avatar" :style="`${renderAvatar(item)}`"></div>
                  </div>
                  <div class="txt-nickname">{{ $format_str(item.nickname, 8) }}</div>
                  <div class="txt-score">{{ item.score }}</div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- 底部跑道背景（倒计时结束后滚动） -->
        <div class="runway-track">
          <div class="runway-inner"></div>
          <div class="runway-inner"></div>
        </div>

        <!-- 马匹（倒计时结束后出现） -->
        <template v-if="gameStarted">
          <div
            v-for="horse in horses"
            :key="horse.id"
            class="horse-wrapper"
            :class="`horse-lane-${horse.lane}`"
            :style="{ transform: `translateX(${horse.x}px)` }"
          >
            <div class="horse-sprite">
              <img
                v-for="(url, frameIdx) in horseFrames[horse.horseType]"
                :key="frameIdx"
                :src="url"
                class="horse-frame"
                :class="{ active: frameIdx === horse.frameIndex }"
                alt=""
              />
              <div class="horse-shadow"></div>
            </div>
          </div>
        </template>
      </div>
    </div>
  </DesignStage>
</template>

<style scoped>
.screen-container {
  width: 1920px;
  height: 1080px;
  position: relative;
  overflow: hidden;
}

.screen-container.paused .runway-track,
.screen-container.paused .horse-running {
  animation-play-state: paused;
}

.bg {
  width: 1920px;
  height: 1080px;
  background: v-bind("imageUrls.bg") center / cover no-repeat;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
}

.img-logo {
  background: v-bind("imageUrls.logo");
  background-size: cover;
  width: 428px;
  height: 77px;
  position: absolute;
  left: 37px;
  top: 82px;
  z-index: 20;
}

.img-title {
  background: v-bind("imageUrls.title") no-repeat;
  width: 675px;
  height: 209px;
  margin: 0 auto;
  margin-top: 37px;
  position: relative;
  z-index: 20;
}

/* ========== 排名容器 (game6 风格水平布局) ========== */
.rank-container {
  background: v-bind("imageUrls.rankContainer") center / cover no-repeat;
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  align-items: center;
  column-gap: 42px;
  box-sizing: border-box;
  padding: 30px;
  width: 1832px;
  height: 244px;
  position: absolute;
  left: 44px;
  top: 280px;
  z-index: 5;

  > div {
    box-sizing: border-box;
    text-align: center;
    width: 100%;
    height: 100%;

    > div {
      box-sizing: border-box;
      width: 100%;
      height: 100%;
      background: #A10A06;
      border-radius: 5px;
      position: relative;

      .rank-icon {
        position: absolute;
        color: #CC7F36;
        font-weight: bold;
      }
    }
  }

  .img-avatar-container {
    position: relative;
    margin: 0 auto;
    width: 90px;
    height: 90px;
    border-radius: 36px;
    top: 18px;
  }

  .img-avatar-container::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: v-bind("imageUrls.avatarAnimation");
    animation: avatar-rotate 10s linear infinite;
  }

  .img-avatar {
    width: 80px;
    height: 80px;
    border-radius: 40px;
    position: absolute;
    left: 6px;
    top: 5px;
  }

  .txt-nickname {
    position: absolute;
    bottom: 40px;
    text-align: center;
    width: 100%;
    color: #F9EBCB;
  }

  .txt-score {
    position: absolute;
    bottom: 5px;
    text-align: center;
    width: 100%;
    color: #F9EBCB;
  }
}

@keyframes avatar-rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* ========== 底部跑道背景 ========== */
.runway-track {
  width: 7680px;
  height: 543px;
  position: absolute;
  bottom: 0;
  left: 0;
  display: flex;
  animation: bg-scroll-left 20s linear infinite;
  z-index: 2;
}

.runway-inner {
  width: 3840px;
  height: 543px;
  background: v-bind("imageUrls.runway") 0 0 / 3840px 543px
    no-repeat;
  flex-shrink: 0;
}

@keyframes bg-scroll-left {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-3840px);
  }
}

/* ========== 马匹 ========== */
.horse-wrapper {
  position: absolute;
  left: 0;
  width: 200px;
  height: 190px;
  z-index: 15;
}

.horse-wrapper.horse-lane-top {
  bottom: 300px; /* 往下挪 50px */
}

.horse-wrapper.horse-lane-bottom {
  bottom: 110px; /* 往上挪 50px */
}


.horse-sprite {
  position: relative;
  width: 200px;
  height: 190px;
}

/* 叠层帧图：预加载后仅切换 opacity，避免 background-image 换 URL 闪烁 */
.horse-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

.horse-frame.active {
  opacity: 1;
}

.horse-shadow {
  position: absolute;
  bottom: -2px;
  left: 50%;
  transform: translateX(-50%);
  width: 120px;
  height: 18px;
  background: radial-gradient(ellipse, rgba(0, 0, 0, 0.45) 0%, transparent 70%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}

@keyframes rank-up-flash {
  0% {
    background-color: #ffffcc;
  }
  50% {
    background-color: #ffff99;
  }
  100% {
    background-color: transparent;
  }
}

@keyframes rank-down-flash {
  0% {
    background-color: #ffe0e0;
  }
  50% {
    background-color: #ffcccc;
  }
  100% {
    background-color: transparent;
  }
}
</style>
