<script setup lang="ts">
import { register } from 'swiper/element/bundle';
import { ref, computed, defineEmits, onMounted, defineModel, useSlots } from 'vue';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';

// 定义 Swiper 元素类型
interface SwiperEvent {
  detail: [any, any?];
}

interface SwiperElement extends HTMLElement {
  swiper: any;
}

// 注册 Swiper 元素
register();

// Swiper 实例引用
const swiperRef = ref<SwiperElement | null>(null);
const swiperInstance = ref<any>(null);

// 使用 defineModel 定义可双向绑定的属性
// 轮播图数据
const slides = defineModel<any[]>('slides', { default: () => [] });
// 每个幻灯片的渲染函数
const renderSlide = defineModel<Function | null>('renderSlide', { default: null });
// 每页显示的幻灯片数
const slidesPerView = defineModel<number | string>('slidesPerView', { default: 1 });
// 幻灯片之间的间距
const spaceBetween = defineModel<number | string>('spaceBetween', { default: 10 });
// 是否居中显示
const centeredSlides = defineModel<boolean>('centeredSlides', { default: false });
// 是否循环播放
const loop = defineModel<boolean>('loop', { default: false });
// 是否自动播放
const autoplay = defineModel<boolean | object>('autoplay', { default: false });
// 是否显示分页器
const pagination = defineModel<boolean | object>('pagination', { default: false });
// 是否显示导航按钮
const navigation = defineModel<boolean | object>('navigation', { default: false });
// 断点配置
const breakpoints = defineModel<object>('breakpoints', { default: () => ({}) });
// 初始幻灯片索引
const initialSlide = defineModel<number>('initialSlide', { default: 0 });
// 高度
const height = defineModel<string>('height', { default: '' });
// 宽度
const width = defineModel<string>('width', { default: '100%' });
// 是否允许触摸滑动（设置为 false 则禁用滑动）
const allowTouchMove = defineModel<boolean>('allowTouchMove', { default: true });

// 定义事件
const emit = defineEmits([
  'progress',
  'slideChange',
  'slideChangeTransitionStart',
  'slideChangeTransitionEnd',
  'update'
]);

// 计算属性：自动播放配置
const autoplayConfig = computed(() => {
  if (autoplay.value === true) {
    return { delay: 3000, disableOnInteraction: false };
  }
  return autoplay.value || false;
});

// 计算属性：分页器配置
const paginationConfig = computed(() => {
  // 始终返回 false，禁用原生分页指示器
  return false;
});

// 获取插槽
const slots = useSlots();

// 计算属性：是否有自定义导航按钮
const hasCustomNavButtons = computed(() => {
  return !!(slots.prevButton || slots.nextButton);
});

// 计算属性：导航按钮配置
const navigationConfig = computed(() => {
  // 如果有自定义导航按钮，则禁用原生导航按钮
  if (hasCustomNavButtons.value) {
    return false;
  }

  // 否则使用配置的导航按钮设置
  if (navigation.value === true) {
    return {};
  }
  return navigation.value || false;
});

// 事件处理函数
const onProgress = (e: SwiperEvent) => {
  const [swiper, progress] = e.detail;
  emit('progress', { swiper, progress });
};

const onSlideChange = (e: SwiperEvent) => {
  const [swiper] = e.detail;
  emit('slideChange', { swiper, activeIndex: swiper.activeIndex });
};

const onSlideChangeTransitionStart = (e: SwiperEvent) => {
  const [swiper] = e.detail;
  emit('slideChangeTransitionStart', { swiper });
};

const onSlideChangeTransitionEnd = (e: SwiperEvent) => {
  const [swiper] = e.detail;
  emit('slideChangeTransitionEnd', { swiper });
};

// 初始化 Swiper
onMounted(() => {
  // 使用 setTimeout 确保 DOM 已完全渲染
  setTimeout(() => {
    if (swiperRef.value && swiperRef.value.swiper) {
      swiperInstance.value = swiperRef.value.swiper;
      emit('update', swiperInstance.value);
    }
  }, 0);
});

// 提供方法：切换到下一张幻灯片
const slideNext = () => {
  if (swiperInstance.value && typeof swiperInstance.value.slideNext === 'function') {
    swiperInstance.value.slideNext();
  }
};

// 提供方法：切换到上一张幻灯片
const slidePrev = () => {
  if (swiperInstance.value && typeof swiperInstance.value.slidePrev === 'function') {
    swiperInstance.value.slidePrev();
  }
};

// 提供方法：切换到指定幻灯片
const slideTo = (index: number) => {
  if (swiperInstance.value && typeof swiperInstance.value.slideTo === 'function') {
    swiperInstance.value.slideTo(index);
  }
};

// 暴露方法给父组件
defineExpose({
  slideNext,
  slidePrev,
  slideTo,
  swiper: swiperInstance
});
</script>

<template>
  <div class="yl-swiper" :style="{ width, height }">
    <!-- 导航按钮（左） -->
    <div v-if="navigation" class="yl-swiper-button-prev" @click="slidePrev">
      <slot name="prevButton">
        <el-icon :size="24"><arrow-left /></el-icon>
      </slot>
    </div>

    <!-- :navigation="navigationConfig" -->
    <swiper-container
      ref="swiperRef"
      :autoHeight="true"
      :slides-per-view="slidesPerView"
      :space-between="spaceBetween"
      :centered-slides="centeredSlides"
      :initial-slide="initialSlide"
      :loop="loop"
      :autoplay="autoplayConfig"
      :pagination="paginationConfig"
      :breakpoints="breakpoints"
      :allow-touch-move="allowTouchMove"
      @swiperprogress="onProgress"
      @swiperslidechange="onSlideChange"
      @sliderslidetransitionstart="onSlideChangeTransitionStart"
      @sliderslidetransitionend="onSlideChangeTransitionEnd"
    >
      <!-- 使用传入的渲染函数渲染幻灯片 -->
      <template v-if="renderSlide && slides && slides.length">
        <swiper-slide v-for="(item, index) in slides" :key="index">
          <component :is="renderSlide(item, index)" />
        </swiper-slide>
      </template>

      <!-- 使用默认插槽 -->
      <template v-else>
        <slot></slot>
      </template>
    </swiper-container>

    <!-- 导航按钮（右） -->
    <div v-if="navigation" class="yl-swiper-button-next" @click="slideNext">
      <slot name="nextButton">
        <el-icon :size="24"><arrow-right /></el-icon>
      </slot>
    </div>

    <!-- 自定义分页指示器 -->
    <div v-if="pagination" class="yl-swiper-pagination">
      <slot name="pagination">
        <div
          v-for="(_, index) in slides && slides.length
            ? slides
            : swiperInstance?.value?.slides || []"
          :key="index"
          class="yl-swiper-pagination-bullet"
          :class="{ 'is-active': swiperInstance?.value?.activeIndex === index }"
          @click="slideTo(index)"
        ></div>
      </slot>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.yl-swiper {
  width: 100%;
  position: relative;
  overflow: hidden;

  .yl-swiper-button-prev,
  .yl-swiper-button-next {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .yl-swiper-button-prev {
    left: 10px;
  }

  .yl-swiper-button-next {
    right: 10px;
  }

  .yl-swiper-button-prev,
  .yl-swiper-button-next {
    width: 32px;
    height: 32px;
    background-color: rgba(255, 255, 255, 0.8);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
    color: #71b73c;
  }

  .yl-swiper-pagination {
    position: absolute;
    bottom: 10px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    z-index: 10;

    .yl-swiper-pagination-bullet {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background-color: rgba(0, 0, 0, 0.2);
      cursor: pointer;
      transition: all 0.3s;

      &.is-active {
        background-color: #71b73c;
        width: 16px;
        border-radius: 4px;
      }
    }
  }
}
</style>
