<script setup>
import { ref, computed, watch, onUnmounted } from "vue";
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { luckyDrawProps, luckyDrawEmits } from "./lucky-draw";
defineOptions({ name: "YhLuckyDraw" });
const props = defineProps(luckyDrawProps);
const emit = defineEmits(luckyDrawEmits);
const ns = useNamespace("lucky-draw");
const { t } = useLocale();
const { themeStyle } = useComponentTheme(
  "lucky-draw",
  computed(() => props.themeOverrides)
);
const isRotating = ref(false);
const wheelRotate = ref(0);
const gridActiveIndex = ref(-1);
let animationFrameId = null;
let wheelTimer = null;
const finalActionText = computed(() => {
  if (isRotating.value || props.loading) return t("luckydraw.drawing");
  return props.actionText || t("luckydraw.start");
});
const containerStyle = computed(() => ({
  ...themeStyle.value,
  width: typeof props.size === "number" ? `${props.size}px` : props.size,
  height: typeof props.size === "number" ? `${props.size}px` : props.size
}));
const isPureText = computed(() => props.prizes.length > 0 && props.prizes.every((p) => !p.image));
const defaultColors = ["#FFF4EB", "#FFFFFF"];
const wheelInnerStyle = computed(() => {
  const prizeCount = props.prizes.length;
  if (prizeCount === 0) return {};
  const degreesPerPrize = 360 / prizeCount;
  const gradientParts = [];
  props.prizes.forEach((prize, index) => {
    const start = index * degreesPerPrize;
    const end = (index + 1) * degreesPerPrize;
    const color = prize.color || defaultColors[index % defaultColors.length];
    gradientParts.push(`${color} ${start}deg ${end}deg`);
  });
  return {
    background: `conic-gradient(${gradientParts.join(", ")})`
  };
});
const handleStart = (e) => {
  if (isRotating.value || props.loading) return;
  emit("click", e);
  emit("start");
};
const startWheel = (id) => {
  const index = props.prizes.findIndex((p) => p.id === id);
  if (index === -1) return;
  isRotating.value = true;
  const prizeCount = props.prizes.length;
  const degreesPerPrize = 360 / prizeCount;
  const destAngle = -(index * degreesPerPrize + degreesPerPrize / 2);
  const baseRotation = (props.rounds || 8) * 360;
  const currentRotation = wheelRotate.value;
  let extra = (destAngle - currentRotation % 360) % 360;
  if (extra > 0) extra -= 360;
  wheelRotate.value = currentRotation + baseRotation + extra;
  if (wheelTimer) clearTimeout(wheelTimer);
  wheelTimer = setTimeout(() => {
    isRotating.value = false;
    emit("finish", props.prizes[index]);
    wheelTimer = null;
  }, props.duration || 4e3);
};
const startGrid = (id) => {
  const index = props.prizes.findIndex((p) => p.id === id);
  if (index === -1) return;
  isRotating.value = true;
  const prizeCount = Math.min(props.prizes.length, 8);
  const totalSteps = prizeCount * (props.rounds || 8) + index;
  const startTime = Date.now();
  const tick = () => {
    const elapsed = Date.now() - startTime;
    const progress = Math.min(elapsed / props.duration, 1);
    const easedProgress = progress === 1 ? 1 : 1 - Math.pow(2, -10 * progress);
    const currentStep = Math.round(totalSteps * easedProgress);
    gridActiveIndex.value = currentStep % prizeCount;
    if (progress < 1) {
      animationFrameId = requestAnimationFrame(tick);
    } else {
      gridActiveIndex.value = index;
      isRotating.value = false;
      emit("finish", props.prizes[index]);
    }
  };
  animationFrameId = requestAnimationFrame(tick);
};
watch(
  () => props.targetId,
  (newId) => {
    if (newId !== "" && newId !== void 0 && newId !== null) {
      if (props.type === "wheel") startWheel(newId);
      else startGrid(newId);
    }
  }
);
onUnmounted(() => {
  if (animationFrameId) cancelAnimationFrame(animationFrameId);
  if (wheelTimer) {
    clearTimeout(wheelTimer);
    wheelTimer = null;
  }
});
const gridAreas = ["1/1", "1/2", "1/3", "2/3", "3/3", "3/2", "3/1", "2/1"];
</script>

<template>
  <div :class="[ns.b(), ns.m(type)]" :style="containerStyle">
    <template v-if="type === 'wheel'">
      <!-- Dynamic class injection for styling decoupling based on exact content -->
      <div :class="[ns.e('wheel-container'), ns.is('pure-text', isPureText)]">
        <div
          :class="ns.e('wheel-inner')"
          :style="[wheelInnerStyle, {
  transform: `rotate(${wheelRotate}deg)`,
  transition: isRotating ? `transform ${duration}ms cubic-bezier(0.15, 0, 0, 1.0)` : 'none'
}]"
        >
          <div
            v-for="(prize, index) in prizes"
            :key="prize.id"
            :class="ns.e('prize-item')"
            :style="{
  transform: `rotate(${360 / prizes.length * index + 360 / prizes.length / 2}deg)`
}"
          >
            <slot name="prize" :prize="prize">
              <div :class="ns.e('prize-content')">
                <div :class="ns.e('prize-name')" :style="{
  color: prize.textColor
}">
                  {{ prize.name }}
                </div>
                <div v-if="prize.image" :class="ns.e('prize-icon')">{{ prize.image }}</div>
              </div>
            </slot>
          </div>
        </div>
        <div v-if="!hideBtn" :class="ns.e('pointer')" @click="handleStart">
          <slot name="action">
            <div :class="ns.e('pointer-btn')">
              <span>{{ finalActionText }}</span>
            </div>
          </slot>
        </div>
      </div>
    </template>

    <template v-else-if="type === 'grid'">
      <div :class="ns.e('grid-container')">
        <div
          v-for="idx in 8"
          :key="idx"
          :class="[ns.e('grid-item'), ns.is('active', gridActiveIndex === idx - 1)]"
          :style="{
  'grid-area': gridAreas[idx - 1]
}"
        >
          <slot v-if="prizes[idx - 1]" name="prize" :prize="prizes[idx - 1]">
            <div v-if="prizes[idx - 1].image" :class="ns.e('prize-icon')">
              {{ prizes[idx - 1].image }}
            </div>
            <div :class="ns.e('prize-name')" :style="{
  color: prizes[idx - 1].textColor
}">
              {{ prizes[idx - 1].name }}
            </div>
          </slot>
        </div>
        <div
          v-if="!hideBtn"
          :class="ns.e('grid-btn')"
          @click="handleStart"
          style="grid-area: 2 / 2"
        >
          <slot name="action">{{ finalActionText }}</slot>
        </div>
      </div>
    </template>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-lucky-draw {
  --yh-lucky-primary: #ff4757;
  --yh-lucky-border-bg: linear-gradient(180deg, #ff8a65 0%, #ff5252 100%);
  --yh-lucky-shadow: 0 10px 25px rgba(255, 82, 82, 0.3);
  position: relative;
  display: inline-block;
  user-select: none;
  font-family: var(--yh-font-family);
}
.yh-lucky-draw--wheel {
  padding: 14px;
  border-radius: var(--yh-radius-circle);
  background: var(--yh-lucky-border-bg);
  box-shadow: var(--yh-lucky-shadow);
  border: 6px solid #ff7b63;
}
.yh-lucky-draw--wheel::before {
  content: "";
  position: absolute;
  top: 6px;
  left: 6px;
  right: 6px;
  bottom: 6px;
  border-radius: var(--yh-radius-circle);
  border: 4px dotted rgba(255, 255, 255, 0.9);
  pointer-events: none;
  z-index: 1;
}
.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--yh-radius-circle);
  background: var(--yh-color-white);
  overflow: hidden;
  box-shadow: 0 0 0 4px #ff3b3b;
}
.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container .yh-lucky-draw__prize-content {
  position: absolute;
  top: 8%;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 96px;
}

.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container .yh-lucky-draw__prize-name {
  font-size: var(--yh-font-size-sm);
  font-weight: var(--yh-font-weight-bold);
  color: #e5533e;
  line-height: var(--yh-line-height-tight);
  text-align: center;
  margin-bottom: 4px;
  white-space: nowrap;
  width: 100%;
}

.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container .yh-lucky-draw__prize-icon {
  font-size: 26px;
  margin: 0;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container.is-pure-text .yh-lucky-draw__prize-content {
  top: 6%;
  height: 28%;
  width: auto;
  justify-content: center;
}

.yh-lucky-draw--wheel .yh-lucky-draw__wheel-container.is-pure-text .yh-lucky-draw__prize-name {
  writing-mode: vertical-rl;
  white-space: nowrap;
  color: #8c1e1e;
  font-size: var(--yh-font-size-base);
  letter-spacing: 2px;
  margin: 0 auto;
}

.yh-lucky-draw__wheel-inner {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: var(--yh-radius-circle);
  will-change: transform;
  border: 1px solid rgba(0, 0, 0, 0.05);
}

.yh-lucky-draw__prize-item {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform-origin: center center;
  box-sizing: border-box;
}

.yh-lucky-draw__pointer {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 68px;
  height: 68px;
  z-index: 100;
  cursor: pointer;
  filter: drop-shadow(0 6px 15px rgba(0, 0, 0, 0.3));
  transition: transform var(--yh-duration-fast);
}
.yh-lucky-draw__pointer:active {
  transform: translate(-50%, -50%) scale(0.92);
}
.yh-lucky-draw__pointer::before {
  content: "";
  position: absolute;
  top: -18px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 14px solid transparent;
  border-right: 14px solid transparent;
  border-bottom: 24px solid #da1f3b;
}

.yh-lucky-draw__pointer-btn {
  width: 100%;
  height: 100%;
  border-radius: var(--yh-radius-circle);
  background: radial-gradient(circle at center, #ff2346 0%, #d80b2a 100%);
  border: 3px solid #ffcc00;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-shadow: inset 0 2px 8px rgba(255, 255, 255, 0.3);
}
.yh-lucky-draw__pointer-btn span {
  font-size: var(--yh-font-size-sm);
  font-weight: 900;
  color: var(--yh-color-white);
  line-height: 1.1;
  width: 2.2em;
  display: inline-block;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.yh-lucky-draw--grid {
  background: #eef2ff;
  padding: 14px;
  border-radius: var(--yh-radius-round);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06), inset 0 0 0 1px rgba(0, 0, 0, 0.03);
}
.yh-lucky-draw--grid .yh-lucky-draw__grid-item {
  background: var(--yh-color-white);
  border-radius: var(--yh-radius-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 16px 8px 8px 8px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.04);
  border: 2px solid transparent;
  transition: all var(--yh-duration-base) var(--yh-timing-ease-in-out);
}
.yh-lucky-draw--grid .yh-lucky-draw__grid-item.is-active {
  background: linear-gradient(135deg, #ff6b81 0%, #ff4757 100%);
  transform: scale(1.06);
  box-shadow: 0 5px 15px rgba(255, 71, 87, 0.4);
  z-index: 2;
  border-color: transparent;
}
.yh-lucky-draw--grid .yh-lucky-draw__grid-item.is-active .yh-lucky-draw__prize-name {
  color: var(--yh-color-white);
}

.yh-lucky-draw--grid .yh-lucky-draw__grid-item.is-active .yh-lucky-draw__prize-icon {
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2)) brightness(1.1);
}

.yh-lucky-draw--grid .yh-lucky-draw__prize-icon {
  font-size: 32px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
}

.yh-lucky-draw--grid .yh-lucky-draw__prize-name {
  font-size: var(--yh-font-size-xs);
  font-weight: var(--yh-font-weight-semibold);
  color: #666;
  text-align: center;
  line-height: 1.35;
  margin-top: 0;
}

.yh-lucky-draw__grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  height: 100%;
}

.yh-lucky-draw__grid-btn {
  background: linear-gradient(180deg, #ff4757 0%, #e82c3c 100%);
  color: var(--yh-color-white);
  border-radius: var(--yh-radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--yh-font-size-md);
  font-weight: 800;
  cursor: pointer;
  box-shadow: 0 5px 0 #b71322, 0 8px 15px rgba(232, 44, 60, 0.4);
  transition: all 0.1s;
  letter-spacing: 1px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.yh-lucky-draw__grid-btn:active {
  transform: translateY(4px);
  box-shadow: 0 1px 0 #b71322, 0 3px 5px rgba(232, 44, 60, 0.4);
}
</style>
