<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { topNavigation } from '~/data/navigation'
import { siteInfo } from '~/data/site'

type NavNode = (typeof topNavigation)[number]
type ChildNode = {
  label: string
  to?: string
  children?: Array<{ label: string; to: string }>
}

const route = useRoute()
const isMenuOpen = ref(false)
const isMobile = ref(false)
const isSticky = ref(false)
const isStickyVisible = ref(false)
const expandedItems = ref<Record<string, boolean>>({})
let lastScrollTop = 0

const stickyThreshold = 1000

const getItemKey = (segments: string[]) => segments.join('::')

const hasChildren = (item: NavNode | ChildNode) => 'children' in item && Boolean(item.children?.length)

const updateStickyState = () => {
  if (typeof window === 'undefined') {
    return
  }

  const currentScrollTop = Math.max(window.scrollY, window.pageYOffset, document.documentElement.scrollTop, 0)

  if (isMobile.value || currentScrollTop <= stickyThreshold) {
    isSticky.value = false
    isStickyVisible.value = false
    lastScrollTop = currentScrollTop
    return
  }

  isSticky.value = true
  isStickyVisible.value = currentScrollTop < lastScrollTop
  lastScrollTop = currentScrollTop
}

const updateViewport = () => {
  if (typeof window === 'undefined') {
    return
  }

  const mobile = window.innerWidth <= 991
  isMobile.value = mobile

  if (!mobile) {
    isMenuOpen.value = false
    expandedItems.value = {}
  }

  updateStickyState()
}

const setOverlay = (enabled: boolean) => {
  if (typeof document === 'undefined') {
    return
  }

  document.querySelector('.page-wrapper')?.classList.toggle('body-overlay', enabled)
}

const openMenu = () => {
  isMenuOpen.value = true
}

const closeMenu = () => {
  isMenuOpen.value = false
  expandedItems.value = {}
}

const toggleExpanded = (key: string) => {
  expandedItems.value[key] = !expandedItems.value[key]
}

const isExpanded = (key: string) => Boolean(expandedItems.value[key])

const matchesRoute = (to?: string) => {
  if (!to) {
    return false
  }

  if (to === '/') {
    return route.path === '/'
  }

  return route.path === to || route.path.startsWith(`${to}/`)
}

const isItemActive = (item: NavNode | ChildNode) => {
  if ('to' in item && matchesRoute(item.to)) {
    return true
  }

  if (hasChildren(item)) {
    return item.children.some((child) => isItemActive(child))
  }

  return false
}

const handleItemClick = (item: NavNode | ChildNode, key: string, event: MouseEvent) => {
  if (!isMobile.value) {
    if (!hasChildren(item)) {
      closeMenu()
    }
    return
  }

  if (!hasChildren(item)) {
    closeMenu()
    return
  }

  const itemHasRoute = 'to' in item && Boolean(item.to)
  const currentlyExpanded = isExpanded(key)

  if (!currentlyExpanded) {
    event.preventDefault()
    toggleExpanded(key)
    return
  }

  if (!itemHasRoute) {
    event.preventDefault()
    toggleExpanded(key)
  }
}

watch(isMenuOpen, setOverlay)
watch(
  () => route.fullPath,
  () => {
    closeMenu()
    updateStickyState()
  }
)

onMounted(() => {
  updateViewport()
  updateStickyState()
  window.addEventListener('resize', updateViewport)
  window.addEventListener('scroll', updateStickyState, { passive: true })
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', updateViewport)
  window.removeEventListener('scroll', updateStickyState)
  setOverlay(false)
})
</script>

<template>
  <header
    id="header"
    :class="['site-header', 'header-style-1', { 'site-header--stuck': isSticky, 'site-header--visible': isStickyVisible }]"
  >
    <nav class="navigation navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="open-btn" @click="openMenu">
            <span class="sr-only">打开菜单</span>
            <span class="icon-bar" />
            <span class="icon-bar" />
            <span class="icon-bar" />
          </button>
          <NuxtLink class="navbar-brand" to="/" @click="closeMenu">
            <img :src="siteInfo.headerLogo" :alt="siteInfo.companyName">
          </NuxtLink>
        </div>

        <div
          id="navbar"
          :class="['navbar-collapse', 'collapse', 'navbar-right', 'navigation-holder', { slideInn: isMenuOpen }]"
        >
          <button class="close-navbar" @click="closeMenu">
            <i class="ti-close" />
          </button>

          <ul :class="['nav', 'navbar-nav', { 'small-nav': isMobile }]">
            <li
              v-for="item in topNavigation"
              :key="item.label"
              :class="[
                {
                  current: isItemActive(item),
                  'menu-item-has-children': hasChildren(item),
                  'product-menu': item.label === '产品中心',
                  'solution-menu': item.label === '解决方案'
                }
              ]"
            >
              <NuxtLink
                v-if="'to' in item && item.to"
                :to="item.to"
                @click="handleItemClick(item, getItemKey([item.label]), $event)"
              >
                {{ item.label }}
              </NuxtLink>
              <a
                v-else
                href="#"
                @click.prevent="handleItemClick(item, getItemKey([item.label]), $event)"
              >
                {{ item.label }}
              </a>

              <ul
                v-if="hasChildren(item)"
                v-show="!isMobile || isExpanded(getItemKey([item.label]))"
                class="sub-menu"
              >
                <li
                  v-for="child in item.children"
                  :key="child.label"
                  :class="[{ current: isItemActive(child), 'menu-item-has-children': hasChildren(child) }]"
                >
                  <NuxtLink
                    v-if="'to' in child && child.to"
                    :to="child.to"
                    @click="handleItemClick(child, getItemKey([item.label, child.label]), $event)"
                  >
                    {{ child.label }}
                  </NuxtLink>
                  <a
                    v-else
                    href="#"
                    @click.prevent="handleItemClick(child, getItemKey([item.label, child.label]), $event)"
                  >
                    {{ child.label }}
                  </a>

                  <ul
                    v-if="hasChildren(child)"
                    v-show="!isMobile || isExpanded(getItemKey([item.label, child.label]))"
                    class="sub-menu"
                  >
                    <li v-for="leaf in child.children" :key="leaf.label" :class="{ current: matchesRoute(leaf.to) }">
                      <NuxtLink :to="leaf.to" @click="closeMenu">{{ leaf.label }}</NuxtLink>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </div>

        <div class="search-contact">
          <div class="contact">
            <a :href="`tel:${siteInfo.phone}`" class="theme-btn">{{ siteInfo.phone }}</a>
          </div>
        </div>
        <div class="separator" />
      </div>
    </nav>
  </header>
</template>
