<template>
  <div class="auto-scroll-container" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" ref="container">
    <div class="auto-scroll-content" ref="content" :style="{ transform: scrollEnabled ? `translate3d(0, ${Math.round(scrollY)}px, 0)` : 'none' }">
      <div class="auto-scroll-item" :class="safety ? 'safety' : ''" v-for="(item, index) in displayList" :key="index">
        <slot :item="item" :index="index">{{ item }}</slot>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
interface Props {
  items: any[];
  speed?: number;
  height?: number;
  minItems?: number;
  autoScroll?: boolean;
  safety?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  speed: 0.4,
  minItems: 2,
  autoScroll: true
});

const container = ref<HTMLElement | null>(null);
const content = ref<HTMLElement | null>(null);

let scrollY = 0;
let animationFrameId: number | null = null;
let manualPaused = false;
let manualControl = false;

// 是否满足滚动条件
const scrollEnabled = computed(() => props.items.length >= props.minItems);

// 展示数据列表（数据足够时复制一份）
const displayList = computed(() => (scrollEnabled.value ? [...props.items, ...props.items] : props.items));

// 修正 scrollY 范围
function normalizeScrollY(contentHeight: number) {
  scrollY = (((scrollY % contentHeight) + contentHeight) % contentHeight) - contentHeight;
}

// 滚动逻辑
function step() {
  if (!content.value) return;
  const contentHeight = content.value.offsetHeight / 2;
  scrollY -= props.speed;
  normalizeScrollY(contentHeight);
  content.value.style.transform = `translate3d(0, ${Math.round(scrollY)}px, 0)`;
  animationFrameId = requestAnimationFrame(step);
}

function startScroll() {
  if (!animationFrameId) {
    animationFrameId = requestAnimationFrame(step);
  }
}

function pauseScroll() {
  if (animationFrameId) {
    cancelAnimationFrame(animationFrameId);
    animationFrameId = null;
  }
}

function onMouseEnter() {
  if (!manualControl) pauseScroll();
}

function onMouseLeave() {
  if (!manualControl && props.autoScroll) startScroll();
}

function onWheel(e: WheelEvent) {
  if (!content.value || !container.value) return;

  const contentHeight = content.value.offsetHeight / (scrollEnabled.value ? 2 : 1);
  const containerHeight = container.value.offsetHeight;

  if (contentHeight <= containerHeight) {
    e.preventDefault();
    return;
  }

  manualPaused = true;
  pauseScroll();
  scrollY -= e.deltaY;
  normalizeScrollY(contentHeight);
  content.value.style.transform = `translate3d(0, ${Math.round(scrollY)}px, 0)`;
}

// 生命周期
onMounted(() => {
  if (scrollEnabled.value && props.autoScroll) {
    startScroll();
  }
  container.value?.addEventListener('wheel', onWheel, { passive: false });
});

onUnmounted(() => {
  pauseScroll();
  container.value?.removeEventListener('wheel', onWheel);
});

// 监听数据是否滚动条件满足
watch(scrollEnabled, (newVal) => {
  if (!newVal) {
    pauseScroll();
    scrollY = 0;
    if (content.value) content.value.style.transform = 'none';
  } else if (props.autoScroll && !manualPaused && !manualControl) {
    startScroll();
  }
});

// 暴露控制方法
defineExpose({
  pause: (): void => {
    manualControl = true;
    pauseScroll();
  },
  resume: (): void => {
    manualControl = false;
    if (scrollEnabled.value) startScroll();
  },
  reset: (): void => {
    scrollY = 0;
    if (content.value) {
      content.value.style.transform = 'translate3d(0, 0, 0)';
    }
  }
});
</script>

<style scoped>
.auto-scroll-container {
  overflow: hidden;
  position: relative;
}
.auto-scroll-content {
  display: flex;
  flex-direction: column;
  will-change: transform;
}
.safety:nth-child(odd) {
  background-color: rgba(67, 226, 203, 0.2);
}
</style>
