<script setup lang="ts">
import type { PageDataLnbMenu } from '#layers/types/api/pageData'

const { y: windowY, directions } = useWindowScroll({ behavior: 'smooth' })
const pageDataStore = usePageDataStore()
const breakpoints = useResponsiveBreakpoints()

const { pageData } = storeToRefs(pageDataStore)

// 상수 정의
const HEADER_HEIGHT = 64
const OBSERVER_OPTIONS = {
  root: null,
  rootMargin: '-20% 0px -60% 0px', // 상단 20%, 하단 60% 마진
  threshold: 0,
} as const

const isShowLnbWithScroll = ref(false)
const activeSection = ref<string>('')

const lnbList = computed<Record<string, PageDataLnbMenu>>(
  () => pageData.value?.lnb_menus || {}
)
const isShowLnb = computed(() => {
  return Boolean(
    pageData.value?.use_lnb &&
      breakpoints.value.isDesktop &&
      Object.keys(lnbList.value).length > 0
  )
})
const activeColor = computed(
  () => pageData.value?.lnb_text_color_code_active || 'var(--text-primary)'
)
const disableColor = computed(
  () => pageData.value?.lnb_text_color_code_deactive || 'var(--text-secondary)'
)

// 1depth가 활성화되었는지 확인 (자신 또는 자식 중 하나가 활성화된 경우)
const is1DepthActive = (lnbItem: PageDataLnbMenu): boolean => {
  // 자신이 활성화된 경우
  if (activeSection.value === lnbItem.page_ver_tmpl_name_en) {
    return true
  }

  // children 중 하나가 활성화된 경우
  const children = lnbItem.children
  if (children && Object.keys(children).length > 0) {
    return Object.values(children).some(
      child => activeSection.value === child.page_ver_tmpl_name_en
    )
  }

  return false
}

// IntersectionObserver 콜백: 교차하는 섹션들 중 가장 위에 있는 것을 활성화
const handleIntersection = (entries: IntersectionObserverEntry[]) => {
  if (import.meta.server) return

  const visibleEntries = entries
    .filter(entry => entry.isIntersecting)
    .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)

  if (visibleEntries.length > 0) {
    const topEntry = visibleEntries[0]
    activeSection.value = topEntry.target.id
  }
}

const observer = new IntersectionObserver(handleIntersection, OBSERVER_OPTIONS)

// 요소 관찰 헬퍼 함수
const observeElement = (elementId: string) => {
  const element = document.getElementById(elementId)
  if (element) {
    observer.observe(element)
  }
}

// 섹션들을 관찰 시작
const observeSections = () => {
  if (import.meta.server) return

  Object.values(lnbList.value).forEach(lnbItem => {
    // 1depth 관찰
    observeElement(lnbItem.page_ver_tmpl_name_en)

    // 2depth 관찰
    const children = lnbItem.children
    if (children && Object.keys(children).length > 0) {
      Object.values(children).forEach(childItem => {
        observeElement(childItem.page_ver_tmpl_name_en)
      })
    }
  })
}

// LNB 클릭 핸들러: 해당 섹션으로 스크롤
const handleLnbClick = (lnbItem: PageDataLnbMenu) => {
  if (import.meta.server) return

  const targetId =
    lnbItem.page_ver_tmpl_name_en === ''
      ? lnbItem?.children?.['1']?.page_ver_tmpl_name_en
      : lnbItem.page_ver_tmpl_name_en

  const targetElement = document.getElementById(targetId)
  if (!targetElement) return

  // 헤더 높이를 고려한 스크롤 위치 계산
  const elementTop = targetElement.getBoundingClientRect().top
  const currentScrollY = window.scrollY
  const targetScrollY = currentScrollY + elementTop - HEADER_HEIGHT

  windowY.value = targetScrollY
}

watch(directions, newVal => {
  // 스크롤 업일 때만 표시, 다운이거나 멈춘 상태에서는 숨김
  isShowLnbWithScroll.value = newVal.top === true
})

onMounted(() => {
  observeSections()
})

onUnmounted(() => {
  observer.disconnect()
})
</script>

<template>
  <template v-if="isShowLnb">
    <div
      :class="['lnb-wrap', { 'is-hidden': !isShowLnbWithScroll }]"
      :style="{
        '--lnb-active-color': activeColor,
        '--lnb-disable-color': disableColor,
      }"
    >
      <ul class="lnb-main">
        <li v-for="lnbItem in lnbList" :key="lnbItem.path_code">
          <button
            v-dompurify-html="lnbItem.menu_name"
            type="button"
            :class="['btn-1depth', { 'is-active': is1DepthActive(lnbItem) }]"
            @click="handleLnbClick(lnbItem)"
          ></button>
          <ul
            v-if="Object.keys(lnbItem.children || {}).length > 0"
            class="lnb-sub"
          >
            <li v-for="subItem in lnbItem.children" :key="subItem.path_code">
              <button
                v-dompurify-html="subItem.menu_name"
                type="button"
                :class="[
                  'btn-2depth',
                  {
                    'is-active':
                      activeSection === subItem.page_ver_tmpl_name_en,
                  },
                ]"
                @click="handleLnbClick(subItem)"
              ></button>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </template>
</template>

<style scoped>
.empty-game + main .lnb-wrap {
  @apply mt-[var(--scroll-position,48px)];
}
.lnb-wrap {
  @apply fixed top-0 right-0 mt-[calc(var(--scroll-position,48px)+64px)] py-8 pr-10 bg-[radial-gradient(100%_50%_at_100%_50%,rgba(0,0,0,0.4)_25%,rgba(0,0,0,0)_100%)] transition-transform duration-[400ms] ease-in-out z-50;
}
.lnb-wrap:before {
  content: '';
  position: absolute;
  top: 0;
  left: -5%;
  width: 105%;
  height: 100%;
  backdrop-filter: blur(5px);
  mask-image: radial-gradient(
    circle at right center,
    #000 0%,
    #000 40%,
    transparent 80%
  );
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
  z-index: -1;
}
.lnb-wrap.is-hidden {
  @apply translate-x-[110%] delay-[5s];
}
.lnb-main {
  @apply flex flex-col gap-4 items-end;
}
.lnb-main > li {
  @apply flex flex-col items-end;
}
.btn-1depth {
  @apply text-[15px] leading-[26px] tracking-[-0.54px];
}
.lnb-sub {
  @apply flex flex-col gap-2 items-end mt-4 mb-1 pr-[16px];
}
.btn-2depth {
  @apply text-[14px] leading-[20px] tracking-[-0.42px];
}

button {
  @apply flex items-center font-[500] text-[var(--lnb-disable-color)] drop-shadow-[0_2px_2px_rgba(0,0,0,0.6)] transition-all duration-300 ease-in-out;
}
button:hover,
button.is-active {
  @apply text-[var(--lnb-active-color)];
}
button::after {
  @apply content-[''] rounded-full ml-2 bg-[var(--lnb-disable-color)] transition-all duration-300 ease-in-out;
}
button.is-active::after {
  @apply bg-[var(--lnb-active-color)];
}
.btn-1depth::after {
  @apply -right-4 w-1.5 h-1.5;
}
.btn-2depth::after {
  @apply -right-3.5 w-1 h-1;
}

.main-promotion .lnb-wrap {
  @apply mt-[calc(var(--scroll-position,48px)+64px+72px)];
}
.empty-game + .main-promotion .lnb-wrap {
  @apply mt-[calc(var(--scroll-position,48px)+72px)];
}
</style>
