<template>
  <div class="lottery-3d-container">
    <div ref="threeContainer" class="three-container"></div>

    <!-- 分页指示器 -->
    <div v-if="totalPages > 1" class="page-indicator">
      第 {{ currentPage + 1 }} 页 / 共 {{ totalPages }} 页
    </div>

    <!-- 滚动提示 -->
    <!-- <div v-if="totalPages > 1 && currentPage === 0" class="scroll-hint">
      向下滚动查看更多
    </div>
    <div v-if="totalPages > 1 && currentPage === totalPages - 1" class="scroll-hint">
      向上滚动查看上一页
    </div> -->
  </div>
</template>

<script setup>
import {
  ref,
  onMounted,
  onBeforeUnmount,
  defineExpose,
  watch,
  computed,
} from "vue";
import * as THREE from "three";
import {
  CSS3DRenderer,
  CSS3DObject,
} from "three/examples/jsm/renderers/CSS3DRenderer.js";
// import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls.js'; // 移除拖拽控件
import TWEEN from "@tweenjs/tween.js";
import { NUMBER_MATRIX } from "../../../utils/config.js";
import CardItem from "./CardItem.vue";
import { createApp } from "vue";
import { getUserListApi } from "../../../api/API";
import { useLotteryStore } from "../../../store/lottery";
const lotteryStore = useLotteryStore();

const winners = computed({
  get: () => lotteryStore.winners,
  set: (val) => lotteryStore.setWinners(val),
});

const threeContainer = ref(null);
let renderer, scene, camera, animationId;
// let controls; // 移除controls

// 全局变量存储当前选中的卡片索引数组
let globalCardIndexes = [];

// 分页相关变量
const currentPage = ref(0);
const totalPages = ref(0);
const cardsPerPage = 10; // 每页显示的卡片数量
let isPageTransitioning = false; // 防止页面切换时的重复操作

// 3D卡片与目标
const threeDCards = [];
const targets = {
  table: [],
  sphere: [],
};
function swapCardContents() {
  // 确保有足够卡片且不在抽奖状态
  if (threeDCards.length < 2 || globalCardIndexes.length > 0) return;

  // 随机选择两张不同的卡片
  let indexA = Math.floor(Math.random() * threeDCards.length);
  let indexB = Math.floor(Math.random() * threeDCards.length);
  while (indexA === indexB) {
    indexB = Math.floor(Math.random() * threeDCards.length);
  }

  const cardA = threeDCards[indexA].element;
  const cardB = threeDCards[indexB].element;

  // 保存原始内容(如果尚未保存)
  if (!cardA.dataset.originalContent) {
    cardA.dataset.originalContent = cardA.innerHTML;
  }
  if (!cardB.dataset.originalContent) {
    cardB.dataset.originalContent = cardB.innerHTML;
  }

  // 交换内容并添加动画效果
  [cardA.innerHTML, cardB.innerHTML] = [cardB.innerHTML, cardA.innerHTML];
  cardA.classList.add('swap-animation');
  cardB.classList.add('swap-animation');

  // 动画结束后移除动画类
  setTimeout(() => {
    cardA.classList.remove('swap-animation');
    cardB.classList.remove('swap-animation');
  }, 500);
}
function createElement(css = "", text = "") {
  const dom = document.createElement("div");
  dom.className = css;
  dom.innerHTML = text;
  return dom;
}

function createCard(user, isBold, id, showTable, company) {
  // 使用 CardItem 组件动态渲染为 DOM 节点
  const container = document.createElement("div");
  const app = createApp(CardItem, {
    id,
    user,
    isBold,
    showTable,
    company,
    // highlight, prize 可后续补充
  });
  app.mount(container);
  return container.firstElementChild;
}

function createCards(member, length, showTable, position, config) {
  let index = 0;
  for (let i = 0; i < config.ROW_COUNT; i++) {
    for (let j = 0; j < config.COLUMN_COUNT; j++) {
      // 4. 判断是否高亮
      const isBold = (config.HIGHLIGHT_CELL || []).includes(j + "-" + i);
      const element = createCard(
        member[index % length],
        isBold,
        index,
        showTable,
        config.COMPANY
      );
      const object = new CSS3DObject(element);
      object.position.x = Math.random() * 4000 - 2000;
      object.position.y = Math.random() * 4000 - 2000;
      object.position.z = Math.random() * 4000 - 2000;
      scene.add(object);
      threeDCards.push(object);
      const targetObject = new THREE.Object3D();
      targetObject.position.x = j * 140 - position.x;
      targetObject.position.y = -(i * 180) + position.y;
      targets.table.push(targetObject);
      index++;
    }
  }
}

function createSphereTargets() {
  const vector = new THREE.Vector3();
  for (let i = 0, l = threeDCards.length; i < l; i++) {
    const phi = Math.acos(-1 + (2 * i) / l);
    const theta = Math.sqrt(l * Math.PI) * phi;
    const object = new THREE.Object3D();
    object.position.setFromSphericalCoords(600, phi, theta);
    object.position.y -= 200; // 向下偏移200px
    
    // 修正朝向计算：让卡牌朝向球体中心点
    vector.set(0, -200, 0); // 球体中心点，Y轴偏移与上面保持一致
    object.lookAt(vector);
    targets.sphere.push(object);
  }
}

// 动画与切换相关方法
function switchScreen(type) {
  if (highlightTimeout) {
    clearTimeout(highlightTimeout);
    highlightTimeout = null;
  }
  // 示例：enter/table/sphere 切换
  if (type === "enter") {
    transform(targets.table, 2000, () => {
      addHighlight();
      highlightTimeout = null;
    }); // 动画结束后加高亮
  } else {
    transform(targets.sphere, 2000, () => removeHighlight()); // 动画结束后移除高亮
  }
}

function transform(targetsArr, duration, onComplete) {
  for (let i = 0; i < threeDCards.length; i++) {
    const object = threeDCards[i];
    const target = targetsArr[i];
    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
  }
  new TWEEN.Tween({})
    .to({}, duration * 2)
    .onUpdate(() => render())
    .onComplete(() => {
      if (onComplete) onComplete();
    })
    .start();
}

function selectCard(selectedCardIndex, currentLuckys, duration = 600) {
  if (highlightTimeout) {
    clearTimeout(highlightTimeout);
    highlightTimeout = null;
  }
  removeHighlight(); // 开始抽奖前移除高亮
  console.log("selectCard called:", {
    selectedCardIndex,
    currentLuckys,
    duration,
  });
  return new Promise((resolve) => {
    const width = 140;

    // 计算总页数
    totalPages.value = Math.ceil(currentLuckys.length / cardsPerPage);
    currentPage.value = 0;

    // 为每页计算位置信息
    const pageLocates = [];

    for (let page = 0; page < totalPages.value; page++) {
      const startIndex = page * cardsPerPage;
      const endIndex = Math.min(
        (page + 1) * cardsPerPage,
        currentLuckys.length
      );
      const pageCount = endIndex - startIndex;

      const pageLocate = [];

      // 根据当前页的人数决定排列方式
      if (pageCount > 5) {
        // 大于5个分两排显示（与抽10人时的排列相同）
        const yPosition = [-87, 87];
        const mid = Math.ceil(pageCount / 2);
        let tag = -(mid - 1) / 2;

        for (let i = 0; i < mid; i++) {
          pageLocate.push({
            x: tag * width,
            y: yPosition[0],
          });
          tag++;
        }

        tag = -(pageCount - mid - 1) / 2;
        for (let i = mid; i < pageCount; i++) {
          pageLocate.push({
            x: tag * width,
            y: yPosition[1],
          });
          tag++;
        }
      } else {
        // 小于等于5个一排显示（与抽不足10人时的排列相同）
        let tag = -(pageCount - 1) / 2;
        for (let i = 0; i < pageCount; i++) {
          pageLocate.push({
            x: tag * width,
            y: 0,
          });
          tag++;
        }
      }

      pageLocates.push(pageLocate);
    }

    console.log("pageLocates calculated:", pageLocates);

    // 初始化所有卡片位置（隐藏超出第一页的卡片）
    selectedCardIndex.forEach((cardIndex, index) => {
      changeCard(cardIndex, currentLuckys[index]);
      const object = threeDCards[cardIndex];

      // 计算卡片应该在第几页
      const cardPage = Math.floor(index / cardsPerPage);
      const isVisible = cardPage === 0;

      // 计算在当前页中的索引
      const pageIndex = index % cardsPerPage;
      const pageLocate = pageLocates[cardPage][pageIndex];

      // 设置初始位置：第一页的卡片正常显示，其他页的卡片从下方隐藏
      let initialY;
      if (isVisible) {
        initialY = pageLocate.y;
      } else {
        // 非第一页的卡片从下方隐藏（为后续向上飞出做准备）
        initialY = pageLocate.y - 1000;
      }

      new TWEEN.Tween(object.position)
        .to(
          {
            x: pageLocate.x,
            y: initialY,
            z: 2200,
          },
          Math.random() * duration + duration
        )
        .easing(TWEEN.Easing.Exponential.InOut)
        .start();

      new TWEEN.Tween(object.rotation)
        .to(
          {
            x: 0,
            y: 0,
            z: 0,
          },
          Math.random() * duration + duration
        )
        .easing(TWEEN.Easing.Exponential.InOut)
        .start();

      object.element.classList.add("prize");
    });

    // 保存页面位置信息到全局变量，供switchPage使用
    window.pageLocates = pageLocates;

    new TWEEN.Tween({})
      .to({}, duration * 2)
      .onUpdate(() => render())
      .start()
      .onComplete(() => {
        console.log("selectCard animation completed");
        // 如果有多页，添加鼠标滚轮事件监听
        if (totalPages.value > 1) {
          addWheelListener();
        }
        resolve();
      });
  });
}

// 分页切换函数
function switchPage(direction) {
  if (isPageTransitioning || totalPages.value <= 1) return;

  const newPage =
    direction === "next" ? currentPage.value + 1 : currentPage.value - 1;
  if (newPage < 0 || newPage >= totalPages.value) return;

  isPageTransitioning = true;
  const duration = 800;

  // 使用保存的页面位置信息
  const pageLocates = window.pageLocates;
  if (!pageLocates) {
    console.error("页面位置信息未找到");
    isPageTransitioning = false;
    return;
  }
  console.log("globalCardIndexes", globalCardIndexes);
  // 动画切换卡片位置
  globalCardIndexes.forEach((cardIndex, index) => {
    const object = threeDCards[cardIndex];
    const cardPage = Math.floor(index / cardsPerPage);
    const isVisible = cardPage === newPage;
    const wasVisible = cardPage === currentPage.value;

    // 计算在当前页中的索引
    const pageIndex = index % cardsPerPage;
    const pageLocate = pageLocates[cardPage][pageIndex];

    // 根据切换方向决定动画效果
    let targetY;
    if (isVisible) {
      // 当前页要显示的卡片
      if (direction === "next") {
        // 索引增大：从下方飞出
        targetY = pageLocate.y;
      } else {
        // 索引减少：从上方飞出
        targetY = pageLocate.y;
      }
    } else {
      // 当前页要隐藏的卡片
      if (direction === "next") {
        // 索引增大：向上飞走
        targetY = pageLocate.y + 1000;
      } else {
        // 索引减少：向下飞走
        targetY = pageLocate.y - 1000;
      }
    }

    // 设置起始位置
    let startY;
    if (wasVisible) {
      // 当前页的卡片从当前位置开始
      startY = object.position.y;
    } else {
      // 非当前页的卡片从隐藏位置开始
      if (direction === "next") {
        // 索引增大：从下方开始
        startY = pageLocate.y - 1000;
      } else {
        // 索引减少：从上方开始
        startY = pageLocate.y + 1000;
      }
    }

    // 先设置起始位置
    object.position.y = startY;

    new TWEEN.Tween(object.position)
      .to(
        {
          x: pageLocate.x,
          y: targetY,
          z: 2200,
        },
        duration
      )
      .easing(TWEEN.Easing.Cubic.InOut)
      .start();
  });

  new TWEEN.Tween({})
    .to({}, duration)
    .onUpdate(() => render())
    .onComplete(() => {
      currentPage.value = newPage;
      isPageTransitioning = false;
      console.log(
        `切换到第 ${currentPage.value + 1} 页，共 ${totalPages.value} 页`
      );
    })
    .start();
}

// 鼠标滚轮事件处理
function handleWheel(event) {
  if (isPageTransitioning || totalPages.value <= 1) return;

  event.preventDefault();

  if (event.deltaY > 0) {
    // 向下滚动，显示下一页
    switchPage("next");
  } else if (event.deltaY < 0) {
    // 向上滚动，显示上一页
    switchPage("prev");
  }
}

// 添加鼠标滚轮事件监听器
function addWheelListener() {
  if (threeContainer.value) {
    threeContainer.value.addEventListener("wheel", handleWheel, {
      passive: false,
    });
  }
}

// 移除鼠标滚轮事件监听器
function removeWheelListener() {
  if (threeContainer.value) {
    threeContainer.value.removeEventListener("wheel", handleWheel);
  }
}

function resetCard(selectedCardIndex, duration = 500) {
  if (!selectedCardIndex || selectedCardIndex.length === 0) {
    return Promise.resolve();
  }

  // 移除鼠标滚轮事件监听器
  removeWheelListener();

  // 重置分页状态
  currentPage.value = 0;
  totalPages.value = 0;
  isPageTransitioning = false;

  // 清理保存的页面位置信息
  if (window.pageLocates) {
    delete window.pageLocates;
  }

  // 清空全局卡片索引数组
  globalCardIndexes = [];

  selectedCardIndex.forEach((index) => {
    const object = threeDCards[index];
    const target = targets.sphere[index];

    new TWEEN.Tween(object.position)
      .to(
        {
          x: target.position.x,
          y: target.position.y,
          z: target.position.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();

    new TWEEN.Tween(object.rotation)
      .to(
        {
          x: target.rotation.x,
          y: target.rotation.y,
          z: target.rotation.z,
        },
        Math.random() * duration + duration
      )
      .easing(TWEEN.Easing.Exponential.InOut)
      .start();
  });

  return new Promise((resolve) => {
    new TWEEN.Tween({})
      .to({}, duration * 2)
      .onUpdate(() => render())
      .start()
      .onComplete(() => {
        selectedCardIndex.forEach((index) => {
          const object = threeDCards[index];
          // 恢复原始内容
          if (object.element.dataset.originalContent) {
            object.element.innerHTML = object.element.dataset.originalContent;
            delete object.element.dataset.originalContent;
          }
          object.element.classList.remove("prize");
        });
        resolve();
      });
  });
}

function changeCard(cardIndex, user) {
  // 保存到全局变量数组
  if (!globalCardIndexes.includes(cardIndex)) {
    globalCardIndexes.push(cardIndex);
  }

  const card = threeDCards[cardIndex].element;

  // 保存原始内容，以便后续恢复
  if (!card.dataset.originalContent) {
    card.dataset.originalContent = card.innerHTML;
  }

  // 设置中奖内容 - 适配后端返回的数据格式
  // 后端返回的数据格式: { jwcode: "5412", username: "猪八戒22" }
  const jwcode = user.jwcode || user[0] || "";
  const username = user.username || user[1] || "";
  const company = user.company || user[2] || "PSST";
  
  card.innerHTML = `<div style="font-size: 30px; font-weight: bold; color: #ffffff; text-align: center; display: flex; justify-content: center; align-items: center; width: 100%; height: 100%;">${jwcode}</div>`;

  // 添加中奖样式类
  card.classList.add("prize");
}

function changeCard1() {
  console.log("执行取消高光，当前卡片索引:", globalCardIndexes);

  // 移除鼠标滚轮事件监听器
  removeWheelListener();

  // 重置分页状态
  currentPage.value = 0;
  totalPages.value = 0;
  isPageTransitioning = false;

  // 清理保存的页面位置信息
  if (window.pageLocates) {
    delete window.pageLocates;
  }

  globalCardIndexes.forEach((cardIndex) => {
    const card = threeDCards[cardIndex].element;
    // console.log('取消卡片', cardIndex, '的高光');

    // 恢复原始内容
    if (card.dataset.originalContent) {
      card.innerHTML = card.dataset.originalContent;
      delete card.dataset.originalContent;
    }

    // 移除prize类，让CardItem组件的样式重新生效
    card.classList.remove("prize");
  });
  // 清空数组
  globalCardIndexes = [];
}

function shine(cardIndex, color) {
  const card = threeDCards[cardIndex].element;
  card.style.backgroundColor =
    color || `rgba(0,127,127,${Math.random() * 0.7 + 0.25})`;
}

// 响应式高亮索引
const highlightedIndexes = ref([]);

// 替换 addHighlight 和 removeHighlight 为响应式写法
function addHighlight(indexes = null) {
  if (indexes) {
    highlightedIndexes.value = [...indexes];
  } else {
    // 默认高亮所有 .lightitem
    highlightedIndexes.value = threeDCards
      // .map((obj, idx) =>
      //   obj.element.classList.contains("lightitem") ? idx : null
      // )
      .filter((idx) => idx !== null);
  }
}

function removeHighlight(indexes = null) {
  if (indexes) {
    highlightedIndexes.value = highlightedIndexes.value.filter(
      (i) => !indexes.includes(i)
    );
  } else {
    highlightedIndexes.value = [];
  }
}

// 监听高亮索引变化并同步到DOM
watch(highlightedIndexes, (newVal) => {
  threeDCards.forEach((cardObj, idx) => {
    if (newVal.includes(idx)) {
      cardObj.element.classList.add("highlight");
    } else {
      cardObj.element.classList.remove("highlight");
    }
  });
});

let rotateObj = null;
let highlightTimeout = null;

function rotateBallStart() {
  return new Promise((resolve) => {
    if (!scene) return resolve();
    scene.rotation.y = 0;
    rotateObj = new TWEEN.Tween(scene.rotation)
      .to({ y: Math.PI * 6 * 1000 }, 3000 * 1000)
      .onUpdate(() => render())
      .onComplete(() => resolve())
      .start();
  });
}

function rotateBallStop() {
  return new Promise((resolve) => {
    if (!scene || !rotateObj) return resolve();
    rotateObj.stop();
    // 完全还原原生补偿动画逻辑
    const currentY = scene.rotation.y;
    const targetY = Math.ceil(currentY / (2 * Math.PI)) * 2 * Math.PI;
    const deltaY = Math.abs(targetY - currentY);
    const duration = 500 + 1000 * (deltaY / Math.PI);
    new TWEEN.Tween(scene.rotation)
      .to({ y: targetY }, duration)
      .easing(TWEEN.Easing.Cubic.Out)
      .onUpdate(() => render())
      .onComplete(() => {
        scene.rotation.y = 0;
        render();
        resolve();
      })
      .start();
  });
}

function getTotalCards() {
  return threeDCards.length;
}

onMounted(async () => {
  // 初始化 3D 场景
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    1,
    10000
  );
  camera.position.z = 3000;
  // camera.position.y = 250; // 整体上移10px
  // 或
  // scene.position.y = 10; // 整体上移10px
  renderer = new CSS3DRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  if (threeContainer.value) {
    threeContainer.value.appendChild(renderer.domElement);
  }

  // 2. 生成高亮坐标（以数字8为例）
  let text = "0123";
  let step = 5;
  let xoffset = 1;
  let yoffset = 1;
  let highlight = [];
  text.split("").forEach((n) => {
    highlight = highlight.concat(
      NUMBER_MATRIX[n].map((item) => {
        return `${item[0] + xoffset}-${item[1] + yoffset}`;
      })
    );
    xoffset += step;
  });
  // const highlightCells = NUMBER_MATRIX["0"].map(([x, y]) => `${x}-${y}`);
  const config = {
    ROW_COUNT: 7, // 数字矩阵是5行
    COLUMN_COUNT: 21, // 数字矩阵是4列
    HIGHLIGHT_CELL: highlight,
    COMPANY: "演示公司",
  };

  const userList = await getUserListApi();
  console.log("3D调用一次接口", userList);
  // lotteryStore.setWinners(userList);
  // console.log("userList", userList);
  // 将用户数据转换为兼容格式，用于3D卡片显示
  const member = userList.data.map((item) => [
    item.jwcode,
    item.username,
    "PSST",
  ]);

  // 将用户列表存储到store中，用于卡牌文字切换
  const userNames = userList.data.map(
    (item) => item.jwcode || item.username || ""
  );
  lotteryStore.setAllUsers(userNames);

  const length = member.length;
  const showTable = true;
  const position = {
    x: (100 * config.COLUMN_COUNT - 20) / 2,
    y: (120 * config.ROW_COUNT - 20) / 2,
  };
  createCards(member, length, showTable, position, config); // 3. 传递高亮配置
  createSphereTargets();

  // 先渲染散落状态
  render();
  animate();

  // 延迟后自动聚集到界面中间
  setTimeout(() => {
    switchScreen("enter");
  }, 500);

  window.addEventListener("resize", onWindowResize);
//  swapInterval.value = setInterval(swapCardContents, swapIntervalTime.value);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", onWindowResize);
  removeWheelListener(); // 移除鼠标滚轮事件监听器
  if (animationId) cancelAnimationFrame(animationId);
  if (highlightTimeout) {
    clearTimeout(highlightTimeout);
    highlightTimeout = null;
  }
  // if (swapInterval.value) {
  //   clearInterval(swapInterval.value);
  //   swapInterval.value = null;
  // }
});

function render() {
  renderer.render(scene, camera);
}

function animate() {
  animationId = requestAnimationFrame(animate);
  TWEEN.update();
  // controls.update(); // 移除controls
  render();
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  render();
}

defineExpose({
  resetCard,
  addHighlight,
  switchScreen,
  rotateBallStart,
  rotateBallStop,
  selectCard,
  getTotalCards,
  changeCard1,
});
</script>

<style scoped>
.lottery-3d-container {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  position: relative;
}
.three-container {
  width: 100%;
  height: 100%;
}

/* 分页指示器样式 */
.page-indicator {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 14px;
  pointer-events: none;
}

/* 滚动提示样式 */
.scroll-hint {
  position: absolute;
  bottom: 60px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 8px 16px;
  border-radius: 20px;
  font-size: 12px;
  pointer-events: none;
  animation: fadeInOut 2s ease-in-out infinite;
}

.price-font {
  font-size: 16px;
  font-weight: bold;
  color: #ffffff;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

@keyframes fadeInOut {
  0%,
  100% {
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
}
</style> 