<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'
import HomeLoader from '~/components/home/HomeLoader.vue'
import HomeIntro from '~/components/home/HomeIntro.vue'
import HomeHero from '~/components/home/HomeHero.vue'

gsap.registerPlugin(ScrollTrigger)

const { t } = useI18n()
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)),
  },
})

// 首页的 SEO 和 Meta 优化，支持国际化响应式
useSeoMeta({
  title: () => t('home.title'),
  description: () => t('home.welcome'),
  ogTitle: () => `${t('home.title')} - ${t('app.name')}`,
  ogDescription: () => t('home.welcome'),
  twitterTitle: () => `${t('home.title')} - ${t('app.name')}`,
  twitterDescription: () => t('home.welcome'),
})

const pageRef = ref<HTMLElement | null>(null)
const homeLoaderRef = ref<InstanceType<typeof HomeLoader> | null>(null)
const homeIntroRef = ref<InstanceType<typeof HomeIntro> | null>(null)
const homeHeroRef = ref<InstanceType<typeof HomeHero> | null>(null)

let heroAnimationContext: gsap.Context | null = null
let removeLoadListener: (() => void) | null = null
let restorePageScroll: (() => void) | null = null
let hasIntroStarted = false
let loaderTween: gsap.core.Tween | null = null
let introTimeline: gsap.core.Timeline | null = null
let introStartTimer: ReturnType<typeof window.setTimeout> | null = null

const setHomeIntroActive = (active: boolean) => {
  isIntroActive.value = active
  document.documentElement.classList.toggle('is-home-intro-active', active)
}

onMounted(() => {
  const pageElement = pageRef.value
  const loaderElement = homeLoaderRef.value?.loaderRef
  const loaderBarElement = homeLoaderRef.value?.loaderBarRef
  const introElement = homeIntroRef.value?.introRef
  const introTitleElement = homeIntroRef.value?.introTitleRef
  const heroElement = homeHeroRef.value?.heroRef

  if (
    !pageElement
    || !loaderElement
    || !loaderBarElement
    || !introElement
    || !introTitleElement
    || !heroElement
  ) {
    return
  }

  const introCharElements = gsap.utils.toArray('.hero-intro-char', introElement)
  const tmElement = introElement.querySelector('.hero-intro-tm')

  if (introCharElements.length === 0 || !tmElement) {
    return
  }

  const { $lenis } = useNuxtApp() as ReturnType<typeof useNuxtApp> & { $lenis?: Lenis }

  heroAnimationContext = gsap.context(() => {
    const playIntro = () => {
      if (hasIntroStarted) {
        return
      }

      hasIntroStarted = true
      removeLoadListener?.()
      removeLoadListener = null
      if (introStartTimer) {
        window.clearTimeout(introStartTimer)
        introStartTimer = null
      }
      loaderTween?.kill()
      loaderTween = null
      introTimeline?.kill()

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

      introTimeline
        .to(loaderBarElement, {
          scaleX: 1,
          duration: 0.25,
          ease: 'power2.out',
        })
        .to(loaderElement, {
          yPercent: -100,
          duration: 0.75,
          ease: 'power4.inOut',
        })
        .set(loaderElement, {
          display: 'none',
        })
        .set(introElement, {
          display: 'grid',
          yPercent: 0,
          autoAlpha: 1,
        })
        .set(introTitleElement, {
          y: 0,
          autoAlpha: 1,
        })
        .set(tmElement, {
          autoAlpha: 0,
        })
        .fromTo(introCharElements, {
          yPercent: 110,
          y: 0,
        }, {
          yPercent: 0,
          y: 0,
          duration: 0.75,
          stagger: 0.055,
        })
        .to(tmElement, {
          autoAlpha: 1,
          duration: 0.4,
          ease: 'power2.out',
        })
        .addLabel('introOut', '+=0.35')
        .to(introTitleElement, {
          autoAlpha: 0,
          duration: 1.05,
          ease: 'power4.inOut',
        }, 'introOut')
        .to(introElement, {
          yPercent: -100,
          duration: 1.05,
          ease: 'power4.inOut',
        }, 'introOut')
        .to(heroElement, {
          yPercent: 0,
          duration: 1.05,
          ease: 'power4.inOut',
          onUpdate: function() {
            // 当 Hero (白色背景) 的 yPercent 运动到 40% 的时候（即大部分背景已经上浮到了屏幕内，还没完全贴顶），触发导航栏出场
            const progress = this.progress()
            // 使用一个标记防止重复触发
            if (progress > 0.6 && !this._headerTriggered) {
              this._headerTriggered = true
              window.dispatchEvent(new Event('hero-intro-done'))
            }
          },
          onStart: function() {
            this._headerTriggered = false
          }
        }, 'introOut')
    }

    const releasePageScroll = () => {
      setHomeIntroActive(false)
      $lenis?.start()
    }

    // 首屏入场期间只通过 html class 锁滚动，避免 class 和 inline overflow 两套状态互相覆盖。
    setHomeIntroActive(true)
    $lenis?.scrollTo(0, { immediate: true })
    $lenis?.stop()
    restorePageScroll = releasePageScroll

    // Loading 层先接管首屏；真正的品牌入场等 window.load 完成后再开始。
    gsap.set(loaderElement, { display: 'grid', yPercent: 0, autoAlpha: 1 })
    gsap.set(loaderBarElement, { scaleX: 0.18, transformOrigin: 'left center' })
    gsap.set(introElement, { display: 'grid', yPercent: 0, autoAlpha: 0 })
    gsap.set(introTitleElement, { y: 0, autoAlpha: 1 })
    // 强制清除 CSS 中的 translateY 像素值，避免被 GSAP 解析为固定 y 像素导致一直不可见
    gsap.set(introCharElements, { y: 0, yPercent: 110 })
    gsap.set(tmElement, { autoAlpha: 0 })
    gsap.set(heroElement, { yPercent: 100 })

    loaderTween = gsap.to(loaderBarElement, {
      scaleX: 0.82,
      duration: 1.2,
      ease: 'power1.inOut',
      repeat: -1,
      yoyo: true,
    })

    const loaderStartedAt = window.performance.now()
    const minLoaderDuration = 1200
    const queueIntro = () => {
      const remainingTime = Math.max(0, minLoaderDuration - (window.performance.now() - loaderStartedAt))

      introStartTimer = window.setTimeout(() => {
        window.requestAnimationFrame(playIntro)
      }, remainingTime)
    }

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

    window.addEventListener('load', queueIntro, { once: true })
    removeLoadListener = () => window.removeEventListener('load', queueIntro)
  }, pageElement)
})

onBeforeUnmount(() => {
  setHomeIntroActive(false)
  hasIntroStarted = false
  if (introStartTimer) {
    window.clearTimeout(introStartTimer)
    introStartTimer = null
  }
  loaderTween?.kill()
  loaderTween = null
  introTimeline?.kill()
  introTimeline = 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"
  >
    <HomeLoader ref="homeLoaderRef" />
    <HomeIntro ref="homeIntroRef" />
    <HomeHero ref="homeHeroRef" />

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