<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import type Lenis from 'lenis'
import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'

gsap.registerPlugin(ScrollTrigger)

const { t } = useI18n()
const introTitle = 'ArcticNewOne'
const introLetters = introTitle.split('')
const isIntroActive = ref(true)

// 让首屏入场的锁滚动在 SSR/首帧就生效，避免等 onMounted 才隐藏滚动条。
useHead({
  htmlAttrs: {
    class: computed(() => (isIntroActive.value ? 'is-home-intro-active' : undefined)),
  },
})

// 背景图是装饰层，左右两列共用同一套模板，只通过 side 区分位置和速度。
const heroGalleryColumns = [
  {
    side: 'left',
    images: [
      'https://picsum.photos/id/1018/900/1200',
      'https://picsum.photos/id/1015/900/1200',
      'https://picsum.photos/id/1024/900/1200',
      'https://picsum.photos/id/1039/900/1200',
    ],
  },
  {
    side: 'right',
    images: [
      'https://picsum.photos/id/1043/900/1200',
      'https://picsum.photos/id/1050/900/1200',
      'https://picsum.photos/id/1067/900/1200',
      'https://picsum.photos/id/1074/900/1200',
    ],
  },
] as const
const pageRef = ref<HTMLElement | null>(null)
const introRef = ref<HTMLElement | null>(null)
const heroRef = ref<HTMLElement | null>(null)
const heroPanelRef = ref<HTMLElement | null>(null)
const nextSectionRef = ref<HTMLElement | null>(null)
let heroAnimationContext: gsap.Context | null = null
let removeLoadListener: (() => void) | null = null
let restorePageScroll: (() => void) | null = null

onMounted(() => {
  if (!pageRef.value || !introRef.value || !heroRef.value || !nextSectionRef.value) {
    return
  }

  const { $lenis } = useNuxtApp() as ReturnType<typeof useNuxtApp> & { $lenis?: Lenis }
  const topHeader = document.querySelector<HTMLElement>('.site-header-top')

  heroAnimationContext = gsap.context(() => {
    // pinDistance 控制 Hero 固定阶段的滚动长度；scrollScrub 控制滚动追随的柔和程度。
    const pinDistance = 1200
    const scrollScrub = 0.65

    const setupHeroScroll = () => {
      gsap.set(heroPanelRef.value, {
        scale: 1,
        transformOrigin: 'center center',
      })

      // 第一段：Hero 停在屏幕中，前景白色面板先缩小，露出背后的图片列。
      gsap.timeline({
        scrollTrigger: {
          trigger: heroRef.value,
          start: 'top top',
          end: `+=${pinDistance}`,
          scrub: scrollScrub,
          pin: true,
          anticipatePin: 1,
        },
      })
        .to(heroPanelRef.value, {
          scale: 0.65,
          ease: 'none',
        })

      // 第二段：取消 pin 后，下一个板块开始进入，白色面板继续缩小。
      gsap.fromTo(heroPanelRef.value, {
        scale: 0.65,
      }, {
        scale: 0.18,
        ease: 'none',
        immediateRender: false,
        scrollTrigger: {
          trigger: nextSectionRef.value,
          start: 'top bottom',
          end: 'top top',
          scrub: scrollScrub,
        },
      })
    }

    const playIntro = () => {
      removeLoadListener?.()
      removeLoadListener = null

      const introTimeline = gsap.timeline({
        defaults: { ease: 'power3.out' },
        onComplete: () => {
          gsap.set(heroRef.value, { clearProps: 'transform' })
          gsap.set(introRef.value, { display: 'none' })
          setupHeroScroll()
          ScrollTrigger.refresh()
          isIntroActive.value = false
          restorePageScroll?.()
          restorePageScroll = null
        },
      })

      introTimeline
        .to('.hero-intro-char', {
          yPercent: 0,
          duration: 0.75,
          stagger: 0.055,
        })
        .to('.hero-intro-title', {
          y: -28,
          autoAlpha: 0,
          duration: 0.45,
          ease: 'power2.in',
        }, '+=0.35')
        .addLabel('introOut')
        .to(introRef.value, {
          yPercent: -100,
          duration: 1.05,
          ease: 'power4.inOut',
        }, 'introOut')
        .to(heroRef.value, {
          yPercent: 0,
          duration: 1.05,
          ease: 'power4.inOut',
        }, 'introOut')
      if (topHeader) {
        introTimeline.to(topHeader, {
          yPercent: 0,
          autoAlpha: 1,
          duration: 0.55,
          ease: 'power3.out',
        }, 'introOut+=0.45')
      }
    }

    // 首屏入场期间锁住滚动，等 window load 后再开始字母动画，避免资源未就绪时露出 Hero。
    const previousHtmlOverflow = document.documentElement.style.overflow
    const previousBodyOverflow = document.body.style.overflow

    $lenis?.scrollTo(0, { immediate: true })
    $lenis?.stop()
    document.documentElement.style.overflow = 'hidden'
    document.body.style.overflow = 'hidden'
    restorePageScroll = () => {
      document.documentElement.style.overflow = previousHtmlOverflow
      document.body.style.overflow = previousBodyOverflow
      $lenis?.start()
    }

    gsap.set(heroRef.value, { yPercent: 100 })
    gsap.set('.hero-intro-char', { yPercent: 110 })
    if (topHeader) {
      gsap.set(topHeader, { yPercent: -140, autoAlpha: 0 })
    }

    if (document.readyState === 'complete') {
      requestAnimationFrame(playIntro)
      return
    }

    window.addEventListener('load', playIntro, { once: true })
    removeLoadListener = () => window.removeEventListener('load', playIntro)
  }, pageRef.value)
})

onBeforeUnmount(() => {
  isIntroActive.value = false
  removeLoadListener?.()
  removeLoadListener = null
  restorePageScroll?.()
  restorePageScroll = null
  heroAnimationContext?.revert()
  heroAnimationContext = null
})

</script>

<template>
  <main ref="pageRef" id="top">
    <div ref="introRef" class="hero-intro" aria-hidden="true">
      <h1 class="hero-intro-title" :aria-label="introTitle">
        <span
          v-for="(letter, index) in introLetters"
          :key="`${letter}-${index}`"
          class="hero-intro-char-wrap"
        >
          <span class="hero-intro-char">{{ letter }}</span>
          <span v-if="index === introLetters.length - 1" class="hero-intro-tm">TM</span>
        </span>
      </h1>
    </div>

    <section ref="heroRef" class="hero-section">
      <div class="hero-backdrop" aria-hidden="true">
        <div
          v-for="column in heroGalleryColumns"
          :key="column.side"
          class="hero-gallery"
          :class="`hero-gallery-${column.side}`"
        >
          <!-- 复制两份图片组，配合 translateY(-50%) 做无缝循环。 -->
          <div
            class="hero-gallery-track"
            :class="{ 'hero-gallery-track-slow': column.side === 'right' }"
          >
            <div v-for="copy in 2" :key="`${column.side}-copy-${copy}`" class="hero-gallery-group">
              <img
                v-for="image in column.images"
                :key="`${column.side}-${copy}-${image}`"
                class="hero-gallery-image"
                :src="image"
                alt=""
                decoding="async"
                loading="eager"
              />
            </div>
          </div>
        </div>
      </div>
      <div ref="heroPanelRef" class="hero-panel">
        <p>Hero Section</p>
      </div>
    </section>
    <section ref="nextSectionRef" class="next-section">
      <h2>Next Section</h2>
    </section>
    <section id="work" class="work-section" data-cursor-label="Read more">
      <p>{{ t('home.welcome') }}</p>
    </section>
  </main>
</template>

<style scoped>
.hero-intro {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  overflow: hidden;
  color: #fff;
  background: #000;
  will-change: transform;
}

.hero-intro-title {
  display: flex;
  margin: 0;
  overflow: hidden;
  font-size: clamp(36px, 6.2vw, 104px);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.07em;
  white-space: nowrap;
}

.hero-intro-char-wrap,
.hero-intro-char {
  display: inline-block;
}

.hero-intro-char-wrap {
  position: relative;
  overflow: hidden;
}

.hero-intro-char {
  will-change: transform;
}

.hero-intro-tm {
  position: absolute;
  left: calc(100% + 0.12em);
  top: 0.08em;
  font-size: 0.13em;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}

.hero-section {
  position: relative;
  height: 100svh;
  overflow: hidden;
  background: #111;
  will-change: transform;
}

.hero-backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #000;
}

.hero-gallery {
  position: absolute;
  top: -40px;
  bottom: -40px;
  width: 49vw;
  overflow: hidden;
}

.hero-gallery-left {
  left: 0;
}

.hero-gallery-right {
  right: 0;
}

.hero-gallery-track {
  will-change: transform;
  animation: hero-gallery-scroll 28s linear infinite;
}

.hero-gallery-track-slow {
  animation-duration: 42s;
}

.hero-gallery-group {
  display: grid;
  gap: 36px;
  padding-bottom: 36px;
}

.hero-gallery-image {
  display: block;
  width: 100%;
  height: clamp(260px, 42vh, 430px);
  border-radius: 0;
  object-fit: cover;
}

@keyframes hero-gallery-scroll {
  to {
    transform: translateY(-50%);
  }
}

.hero-panel {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: #fff;
  font-size: 48px;
  will-change: transform;
}

.next-section,
.work-section {
  min-height: 100svh;
  display: grid;
  place-items: center;
}
</style>
