<template>
  <div class="bg-000 w-full vh100">
    <div class="carousel-wrapper">
      <!-- 轮播容器 -->
      <div class="carousel-container" ref="carouselRef">
        <div
          class="carousel-track"
          :class="{ 'no-anim': noTransition }"
          :style="{
            transform: `translateX(${trackTranslateX}%)`,
            transition: noTransition ? 'none' : `transform ${transitionDuration}ms ${transitionTiming}`,
          }"
        >
          <div
            v-for="(slide, index) in extendedSlides"
            :key="index"
            class="carousel-slide"
            :class="slideClass(index)"
            :style="{ zIndex: slideZIndex(index) }"
          >
            <div class="slide-content relative" :style="{ background: 'slide.bg' }">
              <img src="../../static/image/meinv.png" class="w-full" style="height: auto" alt="" />
              <div class="shadow-overlay absolute"></div>
            </div>
          </div>
        </div>
      </div>

      <!-- 分页指示器 -->
      <div class="carousel-pagination">
        <button
          v-for="(_, index) in paginationDots"
          :key="index"
          class="pagination-dot"
          :class="{ active: index === currentDotIndex }"
          @click="goTo(index)"
        />
      </div>

      <!-- 导航按钮 -->
      <button class="carousel-btn prev" @click="prev">
        <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M15 18l-6-6 6-6" />
        </svg>
      </button>
      <button class="carousel-btn next" @click="next">
        <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M9 18l6-6-6-6" />
        </svg>
      </button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue';

// ===== Props =====
const props = defineProps({
  // 轮播数据
  slides: {
    type: Array as () => Array<{ sub: string; title: string; bg: string }>,
    required: true,
    default: () => [
      { sub: '新功能上线', title: '走！扫街去', bg: 'linear-gradient(135deg,#2980b9,#6dd5fa,#ffd86b)' },
      { sub: '全新发布', title: 'Seedream 5.0 Pro', bg: 'linear-gradient(135deg,#3a1c71,#d76d77,#ffaf7b)' },
      { sub: '热门玩法', title: '爆款短片复刻', bg: 'linear-gradient(135deg,#0f2027,#203a43,#2c5364)' },
      { sub: '电商专属', title: '皮克斯动画广告', bg: 'linear-gradient(135deg,#8e2de2,#4a00e0)' },
      { sub: '音乐创作', title: '一键生成 MV', bg: 'linear-gradient(135deg,#c31432,#240b36)' },
      { sub: '短剧专区', title: '一句话生成短剧', bg: 'linear-gradient(135deg,#159957,#155799)' },
      { sub: '产品展示', title: '商品展示片制作', bg: 'linear-gradient(135deg,#f7971e,#ffd200)' },
    ],
  },
  // 每页显示数量
  slidesPerView: {
    type: Number,
    default: 3,
  },
  // 自动播放间隔（毫秒），0 表示不自动播放
  autoplayDelay: {
    type: Number,
    default: 0,
  },
  // 过渡动画时长（毫秒）
  transitionDuration: {
    type: Number,
    default: 400,
  },
  // 过渡动画曲线
  transitionTiming: {
    type: String,
    default: 'ease',
  },
});

// ===== 布局常量 =====
// 中间幻灯片宽度（%）
const middleWidth = 34.72;
// 左右幻灯片宽度（%）—— 旋转角变小后投影缩水少，侧卡只需略宽
const sideWidth = 36.3;
// 左右与中间的重叠量（%）—— 2*36.3 + 34.72 - 2*3.66 = 100
const overlap = 3.66;
// 中间卡片左边缘目标位置（让其中心落在 50%）
const centerTargetLeft = (100 - middleWidth) / 2; // 32.64

// ===== 状态 =====
// 无限循环：在数据前后各补 slidesPerView 个克隆作为缓冲
const buffer = props.slidesPerView;
const realCount = props.slides.length;
const extendedSlides = computed(() => [
  ...props.slides.slice(-buffer), // 末尾 buffer 个克隆到前面
  ...props.slides,
  ...props.slides.slice(0, buffer), // 开头 buffer 个克隆到后面
]);
// 真实段在 extended 中的起始索引
const realStart = buffer;
// 真实段最后一个可作为左起视图的索引
const realLastStart = realStart + realCount - props.slidesPerView;

const currentIndex = ref(realStart); // 从真实段第一张开始
const noTransition = ref(false);
let resetTimer: number | null = null;

// 角色判断：d = index - (currentIndex+1)
const roleOf = (index: number): 'left' | 'center' | 'right' | 'far' => {
  const d = index - (currentIndex.value + 1);
  if (d === -1) return 'left';
  if (d === 0) return 'center';
  if (d === 1) return 'right';
  return 'far';
};

// class 标记当前页中间及其左右
const slideClass = (index: number): Record<string, boolean> => {
  const r = roleOf(index);
  return {
    'is-left': r === 'left',
    'is-center': r === 'center',
    'is-right': r === 'right',
  };
};

// 按角色返回宽度
const widthOf = (role: ReturnType<typeof roleOf>): number => (role === 'center' ? middleWidth : sideWidth);
// 左边用 margin-right（把中间往左拉），右边用 margin-left（把自己往左拉）
const marginLeftOf = (role: ReturnType<typeof roleOf>): number => (role === 'right' ? -overlap : 0);
const marginRightOf = (role: ReturnType<typeof roleOf>): number => (role === 'left' ? -overlap : role === 'far' ? -overlap : 0);

// 动态累计偏移：把当前中间卡片左边缘定位到 centerTargetLeft
const trackTranslateX = computed(() => {
  const center = currentIndex.value + 1;
  let pos = marginLeftOf(roleOf(0)); // pos(0)
  for (let i = 1; i <= center; i++) {
    const prev = roleOf(i - 1);
    const cur = roleOf(i);
    pos += widthOf(prev) + marginRightOf(prev) + marginLeftOf(cur);
  }
  return centerTargetLeft - pos;
});

// 当前视图中间幻灯片在最上层，左右在下层
const slideZIndex = (index: number): number => {
  const center = currentIndex.value + 1;
  const d = Math.abs(index - center);
  if (d === 0) return 10; // 中间：最上层
  if (d === 1) return 5; // 左右：下层
  return 1; // 其它：最下层
};

// 把 extended 索引映射回真实 slides 索引（用于显示编号）
const realIndexOf = (index: number): number => {
  return (((index - realStart) % realCount) + realCount) % realCount;
};
const carouselRef = ref<HTMLElement | null>(null);
let autoplayTimer: number | null = null;
let isTransitioning = false;

// ===== 计算属性 =====
// 总页数（每页显示 slidesPerView 个）
const totalPages = computed(() => {
  return Math.ceil(realCount / props.slidesPerView);
});

// 分页指示器数据
const paginationDots = computed(() => {
  return Array.from({ length: totalPages.value }, (_, i) => i);
});

// 当前分页索引（基于真实段位置）
const currentDotIndex = computed(() => {
  const realPos = currentIndex.value - realStart;
  const dot = Math.floor(realPos / props.slidesPerView);
  return Math.max(0, Math.min(dot, totalPages.value - 1));
});

// ===== 方法 =====
// 过渡结束后，若进入缓冲克隆区，静默跳回真实段对应位置
const scheduleSilentReset = () => {
  if (resetTimer) clearTimeout(resetTimer);
  resetTimer = window.setTimeout(() => {
    let target = currentIndex.value;
    if (currentIndex.value >= realStart + realCount) {
      // 进入尾部缓冲区 → 回退到真实段
      target = currentIndex.value - realCount;
    } else if (currentIndex.value < realStart) {
      // 进入头部缓冲区 → 前进到真实段
      target = currentIndex.value + realCount;
    }
    if (target !== currentIndex.value) {
      noTransition.value = true;
      currentIndex.value = target;
      // 下一帧恢复过渡
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          noTransition.value = false;
          isTransitioning = false;
        });
      });
    } else {
      isTransitioning = false;
    }
  }, props.transitionDuration + 20);
};

// 下一张
const next = () => {
  if (isTransitioning) return;
  const maxIndex = extendedSlides.value.length - props.slidesPerView;
  if (currentIndex.value >= maxIndex) return; // 边界保护
  isTransitioning = true;
  currentIndex.value += 1;
  scheduleSilentReset();
};

// 上一张
const prev = () => {
  if (isTransitioning) return;
  if (currentIndex.value <= 0) return; // 边界保护
  isTransitioning = true;
  currentIndex.value -= 1;
  scheduleSilentReset();
};

// 跳转到指定页
const goTo = (pageIndex: number) => {
  if (isTransitioning) return;
  const target = realStart + pageIndex * props.slidesPerView;
  if (target !== currentIndex.value) {
    currentIndex.value = target;
  }
};

// 启动自动播放
const startAutoplay = () => {
  if (props.autoplayDelay <= 0 || props.slides.length <= props.slidesPerView) return;

  stopAutoplay();
  autoplayTimer = window.setInterval(() => {
    next();
  }, props.autoplayDelay);
};

// 停止自动播放
const stopAutoplay = () => {
  if (autoplayTimer) {
    clearInterval(autoplayTimer);
    autoplayTimer = null;
  }
};

// 重置自动播放（用户交互后重置定时器）
const resetAutoplay = () => {
  if (props.autoplayDelay > 0) {
    startAutoplay();
  }
};

// ===== 生命周期 =====
onMounted(() => {
  // 初始化位置（真实段第一张）
  currentIndex.value = realStart;
  // 启动自动播放
  startAutoplay();
});

// 监听索引变化，重置自动播放
watch(currentIndex, () => {
  resetAutoplay();
});

onBeforeUnmount(() => {
  stopAutoplay();
  if (resetTimer) clearTimeout(resetTimer);
});

// ===== 暴露方法给父组件 =====
defineExpose({
  next,
  prev,
  goTo,
  startAutoplay,
  stopAutoplay,
  currentIndex,
  totalPages,
});
</script>

<style scoped lang="scss">
/* ===== 轮播容器 ===== */
.carousel-wrapper {
  position: relative;
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
  padding: 20px 0 40px;
  overflow: visible;
}

/* ===== 轮播可视区域 ===== */
.carousel-container {
  position: relative;
  width: 100%;
  overflow: hidden;
  border-radius: 16px;
}

/* ===== 轮播轨道 ===== */
.carousel-track {
  display: flex;
  width: 100%;
  will-change: transform;
}

/* 静默跳转时禁用所有子元素过渡，避免角色重分配引发抖动 */
.carousel-track.no-anim .carousel-slide,
.carousel-track.no-anim .slide-content {
  transition: none !important;
}

/* ===== 每个幻灯片（默认 far，宽度同左右）===== */
.carousel-slide {
  flex-shrink: 0;
  box-sizing: border-box;
  position: relative; /* 使 z-index 生效，实现中间在上、左右在下 */
  width: 36.3%; /* 默认（far/左右）宽度 */
  margin-right: -3.66%; /* far 默认推进步进 */
  transition:
    width 0.3s ease,
    margin-left 0.3s ease,
    margin-right 0.3s ease;
}

/* 当前页中间幻灯片：宽度 34.72%，无 margin */
.carousel-slide.is-center {
  width: 34.72%;
  margin-left: 0;
  margin-right: 0;
}

/* 中间左边的幻灯片：用 margin-right 把中间往左拉，形成重叠 */
.carousel-slide.is-left {
  margin-right: -3.66%;
  margin-left: 0;
}

/* 中间右边的幻灯片：用 margin-left 把自己往左拉，钻到中间下面 */
.carousel-slide.is-right {
  margin-left: -3.66%;
  margin-right: 0;
}

.slide-content {
  width: 100%;
  height: 280px;
  border-radius: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* padding: 24px 18px; */
  overflow: hidden;
  transition: transform 0.3s ease;
}

/* 3D 变换按角色施加 */
.carousel-slide.is-center .slide-content {
  transform: none;
}
.carousel-slide.is-left .slide-content {
  transform: perspective(600px) translate3d(0px, 0px, 0px) rotateY(12deg) scaleY(0.92);
  .shadow-overlay {
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(to left, #00000080, #00000000);
  }
}
.carousel-slide.is-right .slide-content {
  transform: perspective(600px) translate3d(0px, 0px, 0px) rotateY(-12deg) scaleY(0.92);
  .shadow-overlay {
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(to right, #00000080, #00000000);
  }
}

.slide-sub {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 8px;
  letter-spacing: 2px;
}

.slide-title {
  font-size: 28px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.3);
}

/* ===== 分页指示器 ===== */
.carousel-pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
}

.pagination-dot {
  width: 32px;
  height: 4px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.2);
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
  padding: 0;
}

.pagination-dot.active {
  width: 48px;
  background: rgba(255, 255, 255, 0.85);
}

.pagination-dot:hover {
  background: rgba(255, 255, 255, 0.5);
}

/* ===== 导航按钮 ===== */
.carousel-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 10;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: rgba(255, 255, 255, 0.8);
  cursor: pointer;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.carousel-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}

.carousel-btn:active {
  transform: translateY(-50%) scale(0.95);
}

.carousel-btn.prev {
  left: 10px;
}

.carousel-btn.next {
  right: 10px;
}

/* ===== 响应式 ===== */
@media (max-width: 768px) {
  .carousel-btn {
    width: 32px;
    height: 32px;
  }

  .carousel-btn.prev {
    left: 4px;
  }

  .carousel-btn.next {
    right: 4px;
  }

  .slide-content {
    height: 200px;
  }

  .slide-title {
    font-size: 20px;
  }

  .slide-sub {
    font-size: 12px;
  }

  .pagination-dot {
    width: 20px;
  }

  .pagination-dot.active {
    width: 32px;
  }
}
</style>
