<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import gsap from 'gsap'
import { useAppStore } from '~/stores/app'
import { usePageScrollLock } from '~/composables/usePageScrollLock'

const loaderRef = ref<HTMLElement | null>(null)
const loaderBarRef = ref<HTMLElement | null>(null)
const appStore = useAppStore()

// Lock scroll while app is loading
usePageScrollLock(appStore.isAppLoading)

let loaderTween: gsap.core.Tween | null = null
let removeLoadListener: (() => void) | null = null
let introStartTimer: ReturnType<typeof window.setTimeout> | null = null

onMounted(() => {
  const loaderElement = loaderRef.value
  const loaderBarElement = loaderBarRef.value

  if (!loaderElement || !loaderBarElement) return

  // Initial GSAP setup
  gsap.set(loaderElement, { display: 'grid', yPercent: 0, autoAlpha: 1 })
  gsap.set(loaderBarElement, { scaleX: 0.18, transformOrigin: 'left center' })

  // Loader bar bouncing animation
  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 finishLoading = () => {
    removeLoadListener?.()
    removeLoadListener = null

    if (introStartTimer) {
      window.clearTimeout(introStartTimer)
      introStartTimer = null
    }

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

    introStartTimer = window.setTimeout(() => {
      // End the loader loop and slide out
      loaderTween?.kill()
      loaderTween = null

      const tl = gsap.timeline({
        onComplete: () => {
          gsap.set(loaderElement, { display: 'none' })
          appStore.setAppLoading(false)
        }
      })

      tl.to(loaderBarElement, {
        scaleX: 1,
        duration: 0.25,
        ease: 'power2.out',
      }).to(loaderElement, {
        yPercent: -100,
        duration: 0.75,
        ease: 'power4.inOut',
      })
    }, remainingTime)
  }

  if (document.readyState === 'complete') {
    finishLoading()
  } else {
    window.addEventListener('load', finishLoading, { once: true })
    removeLoadListener = () => window.removeEventListener('load', finishLoading)
  }
})

onBeforeUnmount(() => {
  loaderTween?.kill()
  if (introStartTimer) window.clearTimeout(introStartTimer)
  removeLoadListener?.()
})
</script>

<template>
  <div ref="loaderRef" class="page-loader" aria-hidden="true">
    <div class="page-loader-content">
      <p>Loading</p>
      <span class="page-loader-line">
        <span ref="loaderBarRef" class="page-loader-line-inner" />
      </span>
    </div>
  </div>
</template>

<style scoped>
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  color: #fff;
  background: #000;
  will-change: transform;
}

.page-loader-content {
  width: min(220px, calc(100vw - 48px));
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.page-loader-content p {
  margin: 0 0 14px;
}

.page-loader-line {
  display: block;
  width: 100%;
  height: 1px;
  overflow: hidden;
  background: rgb(255 255 255 / 20%);
}

.page-loader-line-inner {
  display: block;
  width: 100%;
  height: 100%;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left center;
}
</style>
