<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'
import { useUserStore } from '~/stores/user'

gsap.registerPlugin(ScrollTrigger)

const { t } = useI18n()
const introTitle = 'ArcticNewOne'
const introLetters = introTitle.split('')
const heroPinDistance = 1200
const isIntroActive = ref(true)
const userStore = useUserStore()
const demoUserName = computed(() => userStore.displayName)
const demoUserRole = computed(() => userStore.role)

if (!userStore.isLoggedIn) {
  userStore.loadDemoUser()
}

// 让首屏入场的锁滚动在 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 heroStageRef = ref<HTMLElement | null>(null)
const heroRef = ref<HTMLElement | null>(null)
const heroPanelRef = ref<HTMLElement | null>(null)
let heroAnimationContext: gsap.Context | null = null
let removeLoadListener: (() => void) | null = null
let restorePageScroll: (() => void) | null = null
let cleanupHeroScroll: (() => void) | null = null

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

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

  heroAnimationContext = gsap.context(() => {
    const pinEndScale = 0.65
    const finalScale = 0.18
    const getExitDistance = () => window.innerHeight

    const setupHeroScroll = () => {
      cleanupHeroScroll?.()

      gsap.set(heroPanelRef.value, {
        scale: 1,
        force3D: true,
        transformOrigin: 'center center',
      })

      const setHeroPanelScale = (scale: number) => {
        if (!heroPanelRef.value) {
          return
        }

        heroPanelRef.value.style.transform = `scale(${scale})`
      }

      const updateHeroPanelScale = () => {
        if (!heroStageRef.value) {
          return
        }

        const exitDistance = getExitDistance()
        const totalDistance = heroPinDistance + exitDistance
        const currentScroll = Math.max(window.scrollY, $lenis?.scroll ?? 0)
        const currentDistance = gsap.utils.clamp(0, totalDistance, currentScroll - heroStageRef.value.offsetTop)

        if (currentDistance <= heroPinDistance) {
          setHeroPanelScale(gsap.utils.interpolate(1, pinEndScale, currentDistance / heroPinDistance))
          return
        }

        setHeroPanelScale(
          gsap.utils.interpolate(
            pinEndScale,
            finalScale,
            (currentDistance - heroPinDistance) / exitDistance,
          ),
        )
      }

      // CSS sticky 负责固定；ticker 每帧读取当前滚动距离，避免依赖 scroll/ScrollTrigger 事件链。
      updateHeroPanelScale()
      gsap.ticker.add(updateHeroPanelScale)

      cleanupHeroScroll = () => {
        gsap.ticker.remove(updateHeroPanelScale)
      }
    }

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

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

      introTimeline
        .to('.hero-intro-char', {
          yPercent: 0,
          duration: 0.75,
          stagger: 0.055,
        })
        .addLabel('introOut', '+=0.35')
        .to('.hero-intro-title', {
          autoAlpha: 0,
          duration: 1.05,
          ease: 'power4.inOut',
        }, '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

    const releasePageScroll = () => {
      isIntroActive.value = false
      document.documentElement.classList.remove('is-home-intro-active')
      document.documentElement.style.overflow = previousHtmlOverflow
      document.body.style.overflow = previousBodyOverflow
      $lenis?.start()
    }

    document.documentElement.classList.add('is-home-intro-active')
    document.documentElement.style.overflow = 'hidden'
    document.body.style.overflow = 'hidden'
    $lenis?.scrollTo(0, { immediate: true })
    $lenis?.stop()
    restorePageScroll = releasePageScroll

    // 每次播放前都重置首屏状态，避免热更新或页面返回时残留上一次的 inline style。
    gsap.set(introRef.value, { display: 'grid', yPercent: 0, autoAlpha: 1 })
    gsap.set('.hero-intro-title', { y: 0, autoAlpha: 1 })
    gsap.set('.hero-intro-char', { yPercent: 110 })
    gsap.set(heroRef.value, { yPercent: 100 })
    if (topHeader) {
      gsap.set(topHeader, { yPercent: -140, autoAlpha: 0 })
    }
    setupHeroScroll()

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

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

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

</script>

<template>
  <main
    ref="pageRef"
    id="top"
    :data-demo-user="demoUserName"
    :data-demo-user-role="demoUserRole"
  >
    <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="heroStageRef"
      class="hero-stage"
      :style="{ '--hero-pin-distance': `${heroPinDistance}px` }"
    >
      <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>
    <section 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-stage {
  position: relative;
  height: calc(100svh + var(--hero-pin-distance));
  background: #000;
}

.hero-section {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  background: #111;
}

.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>
