<script setup>
import { ref, computed, watch, onBeforeUnmount } from 'vue'
import { useRoute, useRouter, RouterLink } from 'vue-router'
import Logo from './Logo.vue'
import Icon from './Icon.vue'
import IconButton from './IconButton.vue'
import LanguageSwitcher from './LanguageSwitcher.vue'
import Search from './Search.vue'
import { products as defaultProducts } from '@/api/index.js'
import { useI18n } from '@/i18n/index.js'

const props = defineProps({
  variant: {
    type: String,
    default: 'paper',
    validator: (v) => ['brand', 'cream', 'paper'].includes(v),
  },
  /**
   * Layout:
   *  - 'standard': edge-to-edge bar with bottom border (static at top of page)
   *  - 'floating': sticky rounded card that detaches from page edges with a shadow
   */
  layout: {
    type: String,
    default: 'standard',
    validator: (v) => ['standard', 'floating'].includes(v),
  },
  /**
   * Primary nav items — render in the left cluster, next to the logo.
   * On the shop/home these are the top-level shop destinations
   * (Shop, Cook, Clean, Care).
   */
  items: {
    type: Array,
    default: () => [
      { key: 'nav.shop', href: '#' },
      { key: 'nav.applications', href: '#' },
      { key: 'nav.about', href: '#' },
      { key: 'nav.contact', href: '#' },
    ],
  },
  /**
   * Secondary nav items — render in the right cluster, immediately to
   * the LEFT of the search trigger. Intended for supporting pages
   * (Bundles, Revitalisation, About) that sit above the purchasing
   * flow but below the category browse in importance. Empty by
   * default so callers that don't use the split leave the right
   * cluster unchanged.
   */
  secondaryItems: {
    type: Array,
    default: () => [],
  },
  cartCount: { type: Number, default: 0 },
  floatOnMobile: { type: Boolean, default: true },
  /**
   * Catalogue the search overlay queries. Defaults to the frontend fixture
   * so the navbar is usable on its own; callers pass in their own list once
   * the product data is backend-driven.
   */
  products: { type: Array, default: () => defaultProducts },
})

defineEmits(['cart', 'nav', 'search', 'select'])

const { t } = useI18n()
const menuOpen = ref(false)
const searchOpen = ref(false)

const tones = {
  brand: {
    bar: 'bg-brand text-cream border-cream-line',
    link: 'text-cream hover:text-accent',
    logo: 'text-cream',
    searchTrigger: 'border border-cream-line bg-cream-wash text-cream/80 hover:text-accent',
  },
  cream: {
    bar: 'bg-cream text-brand border-line',
    link: 'text-brand hover:text-brand-hover',
    logo: 'text-brand',
    searchTrigger: 'border border-line-strong bg-paper text-muted hover:text-brand',
  },
  paper: {
    bar: 'bg-paper text-ink border-line',
    link: 'text-ink hover:text-brand',
    logo: 'text-brand',
    searchTrigger: 'border border-line bg-paper text-muted hover:text-brand',
  },
}

const tone = computed(() => tones[props.variant])

// Both layouts stay pinned at the top of the scroll container while the user
// scrolls. `sticky` keeps it in normal document flow until it hits the top edge,
// which avoids the layout-shift that `position: fixed` would introduce.
const layoutClasses = computed(() =>
  props.layout === 'floating'
    ? 'sticky top-4 md:top-6 z-30 mx-4 md:mx-6 rounded-lg border shadow-md'
    : 'sticky top-0 z-30 border-b',
)

// Edge-to-edge: the bar's contents span the full bar width. Logo sits at the
// far left, language + cart cluster at the far right. No centered max-width
// container — matches the live kaiser-natron.at layout.
const innerPadding = computed(() =>
  props.layout === 'floating'
    ? 'px-6 md:pl-4 md:pr-8 py-3 md:py-3.5'
    : 'px-6 md:px-8 lg:px-10 py-5',
)

const logoClasses = computed(() =>
  props.layout === 'floating'
    ? 'w-9 md:w-16 h-auto'
    : 'w-12 md:w-24 h-auto',
)

function itemLabel(item) {
  return item.key ? t(item.key) : item.label
}

// Mobile menu list — primary items + secondary supporting pages
// concatenated. The desktop top-bar shows the same items in two
// clusters (left of logo + right of search) when `secondaryItems`
// is populated; on mobile they read as one stack so neither group
// is hidden from a single-column overlay.
const menuItems = computed(() => [...props.items, ...props.secondaryItems])

// Active-link detection. Two-step compare so we recognise both
// in-page anchors (`/#bundles` from a different page lands on `/`,
// and the visible "active" link should be Shop, not Bundles) and
// hash-only links inside the same page (`#cook` on Shop). The
// route hash is compared explicitly because Vue Router's path
// excludes the hash.
const route = useRoute()
const router = useRouter()

function goToLogin() {
  router.push('/login')
}
function isActive(href) {
  if (!href || href === '#') return false
  const here = route.path
  const hereHash = `${route.path}${route.hash || ''}`
  // Strip leading `/` to compare hash-only forms (`#cook`) against
  // the current route's hash directly.
  if (href.startsWith('#')) return route.hash === href
  // Exact path match (`/shop`, `/`).
  if (href === here) return true
  // Path + hash match (`/shop#care`, `/#bundles`). The user is
  // "on" that destination only when both the path and the hash
  // line up — otherwise plain `/shop` would also flag `/shop#care`
  // as active.
  return href === hereHash
}

// RouterLink doesn't fire a navigation when the destination resolves
// to the current URL, so Vue Router's scrollBehavior never runs for
// "logo while on /" or "/#bundles while on /#bundles". We handle the
// scroll manually here so those clicks always animate.
function onNavClick(item, event) {
  if (!item || !item.href) return
  const [path, hash] = item.href.split('#')
  const targetPath = path || '/'
  const onSameRoute = targetPath === route.path
  if (!onSameRoute) return
  if (hash) {
    const el = document.getElementById(hash)
    if (el) {
      event?.preventDefault?.()
      el.scrollIntoView({ behavior: 'smooth', block: 'start' })
      try {
        history.replaceState(history.state, '', `#${hash}`)
      } catch {}
    }
    return
  }
  // Same path, no hash (logo click on home) → smooth-scroll to top.
  event?.preventDefault?.()
  window.scrollTo({ top: 0, behavior: 'smooth' })
}

function onLogoClick(event) {
  if (route.path === '/') {
    event?.preventDefault?.()
    window.scrollTo({ top: 0, behavior: 'smooth' })
  }
}

watch(menuOpen, (open) => {
  if (typeof document === 'undefined') return
  document.documentElement.style.overflow = open ? 'hidden' : ''
})

onBeforeUnmount(() => {
  if (typeof document !== 'undefined') document.documentElement.style.overflow = ''
})
</script>

<template>
  <header :class="['font-sans', layoutClasses, tone.bar]">
    <div :class="[innerPadding, 'flex items-center justify-between gap-6']">
      <!-- Left: logo + desktop nav -->
      <div class="flex items-center gap-10 min-w-0">
        <RouterLink
          to="/"
          :class="['block shrink-0 py-1', tone.logo]"
          aria-label="Kaiser Natron home"
          @click="onLogoClick"
        >
          <Logo :class="logoClasses" />
        </RouterLink>
        <nav class="hidden min-[1100px]:flex items-center gap-7">
          <RouterLink
            v-for="item in items"
            :key="item.key || item.label"
            :to="item.href || '/'"
            :class="[
              isActive(item.href) ? 'text-accent' : tone.link,
              'text-[14px] font-medium tracking-label transition-colors duration-base',
            ]"
            @click="onNavClick(item, $event); $emit('nav', item)"
          >{{ itemLabel(item) }}</RouterLink>
        </nav>
      </div>

      <!-- Right: secondary nav + search + language + cart (desktop only) -->
      <div class="hidden min-[1100px]:flex items-center gap-4">
        <!-- Secondary nav — supporting pages tucked to the left of
             search so the primary category nav on the left stays the
             focal point. Shares the same visual treatment as the
             primary items for consistency. -->
        <nav
          v-if="secondaryItems.length"
          class="flex items-center gap-6 mr-2"
        >
          <RouterLink
            v-for="item in secondaryItems"
            :key="item.key || item.label"
            :to="item.href || '/'"
            :class="[
              isActive(item.href) ? 'text-accent' : tone.link,
              'text-[14px] font-medium tracking-label transition-colors duration-base',
            ]"
            @click="onNavClick(item, $event); $emit('nav', item)"
          >{{ itemLabel(item) }}</RouterLink>
        </nav>
        <button
          type="button"
          :class="[
            'inline-flex items-center gap-2 pl-3 pr-4 h-10 rounded-pill text-[13px] font-medium tracking-label transition-colors duration-base',
            tone.searchTrigger,
          ]"
          :aria-label="t('search.open')"
          @click="searchOpen = true"
        >
          <Icon name="search" :size="16" />
          <span>{{ t('search.placeholder') }}</span>
        </button>
        <LanguageSwitcher :tone="variant" />
        <IconButton
          icon="user"
          variant="float"
          shadow="none"
          size="md"
          :aria-label="t('auth.login.cta')"
          @click="goToLogin"
        />
        <IconButton
          icon="cart"
          variant="accent"
          size="md"
          :count="cartCount"
          :aria-label="t('cart.open')"
          @click="$emit('cart')"
        />
      </div>

      <!-- Mobile-only: account icon on the top right of the bar. The
           cart still lives in the bottom-right floating cluster; this
           keeps account discovery one tap away without crowding the
           thumb-zone cluster. -->
      <div class="min-[1100px]:hidden flex items-center">
        <IconButton
          icon="user"
          variant="float"
          shadow="none"
          size="md"
          :aria-label="t('auth.login.cta')"
          @click="goToLogin"
        />
      </div>
    </div>

    <!-- Mobile floating search (bottom-left). Matches the bottom-right
         cluster's safe-area handling so it clears the home indicator. -->
    <div
      v-if="floatOnMobile"
      class="min-[1100px]:hidden fixed bottom-5 left-5 z-40"
      style="padding-bottom: env(safe-area-inset-bottom);"
    >
      <IconButton
        icon="search"
        variant="float"
        size="lg"
        :icon-stroke-width="2"
        :aria-label="t('search.open')"
        @click="searchOpen = true"
      />
    </div>

    <!-- Mobile floating cluster (bottom-right) -->
    <div
      v-if="floatOnMobile"
      class="min-[1100px]:hidden fixed bottom-5 right-5 z-40 flex items-center gap-3"
      style="padding-bottom: env(safe-area-inset-bottom);"
    >
      <IconButton
        icon="cart"
        variant="accent"
        size="lg"
        shadow="md"
        :count="cartCount"
        :aria-label="t('cart.open')"
        @click="$emit('cart')"
      />
      <IconButton
        icon="menu"
        variant="float"
        size="lg"
        :icon-size="24"
        :icon-stroke-width="2"
        :aria-label="t('menu.open')"
        @click="menuOpen = true"
      />
    </div>

    <!-- Mobile overlay menu -->
    <Teleport to="body">
      <Transition
        enter-active-class="transition duration-slow ease-out"
        enter-from-class="opacity-0 translate-y-2"
        enter-to-class="opacity-100 translate-y-0"
        leave-active-class="transition duration-base ease-out"
        leave-from-class="opacity-100 translate-y-0"
        leave-to-class="opacity-0 translate-y-2"
      >
        <div
          v-if="menuOpen"
          class="fixed inset-0 z-50 bg-brand text-cream flex flex-col font-sans"
        >
          <div
            class="flex items-center px-6 pt-6 pb-4"
            style="padding-top: calc(env(safe-area-inset-top) + 1.5rem);"
          >
            <Logo class="w-12 h-auto text-cream" />
          </div>

          <!-- Mobile menu — Shop + supporting pages (Bundles /
               Revitalisation / About). The category shortcuts
               (Cook / Clean / Care) are reachable from the home
               hero pills and the desktop top-bar; on mobile the
               menu stays focused on the four top-level
               destinations. -->
          <nav class="flex-1 flex flex-col-reverse justify-center px-8 gap-3 overflow-y-auto">
            <RouterLink
              v-for="item in menuItems"
              :key="item.key || item.label"
              :to="item.href || '/'"
              :class="[
                'font-serif font-normal text-[clamp(2.25rem,9vw,3.5rem)] tracking-tight leading-[1.05] transition-colors duration-base',
                isActive(item.href)
                  ? 'text-accent'
                  : 'text-cream hover:text-accent',
              ]"
              @click="onNavClick(item, $event); menuOpen = false; $emit('nav', item)"
            >{{ itemLabel(item) }}</RouterLink>
          </nav>

          <!-- Language selector. Extra bottom padding clears the
               floating cart+close row (pill ~56px + safe-area +
               `bottom-5` inset) so it never sits behind that
               row when the overlay content is short. -->
          <div
            class="px-6 flex justify-center"
            style="padding-bottom: calc(env(safe-area-inset-bottom) + 6.5rem);"
          >
            <LanguageSwitcher tone="brand" />
          </div>

          <!-- Floating action row — cart pill on the left, close X
               on the right at `bottom-5 right-5` (same edges as the
               page's menu-open IconButton). Both live in one
               horizontal band so cart + close read as a cluster and
               the X lands exactly over the position the user just
               tapped to open the menu. The row is a single `fixed`
               wrapper so only one layout element owns the bottom
               anchoring. -->
          <div
            class="fixed bottom-5 left-5 right-5 z-[60] flex items-center gap-3"
            style="padding-bottom: env(safe-area-inset-bottom);"
          >
            <button
              type="button"
              class="flex-1 min-w-0 inline-flex items-center justify-between px-6 py-4 rounded-pill bg-accent text-brand font-semibold tracking-label hover:bg-accent-soft transition-colors shadow-md"
              @click="menuOpen = false; $emit('cart')"
            >
              <span class="inline-flex items-center gap-3">
                <Icon name="cart" :size="20" />
                {{ t('cart.label') }}
              </span>
              <span
                v-if="cartCount > 0"
                class="min-w-[22px] h-[22px] px-2 rounded-full bg-brand text-accent text-[12px] font-bold flex items-center justify-center"
              >{{ cartCount }}</span>
            </button>
            <!-- Close wrapped in a div so the fixed row's flex
                 layout drives width; IconButton's own root is
                 `relative` (count badge anchor) and would fight a
                 `fixed` applied directly. -->
            <div class="shrink-0">
              <IconButton
                icon="close"
                variant="float"
                size="lg"
                :icon-size="24"
                :icon-stroke-width="2"
                :aria-label="t('menu.close')"
                @click="menuOpen = false"
              />
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>

    <Search
      v-model="searchOpen"
      :products="products"
      :tone="variant"
      @select="(p) => $emit('search', p)"
    />
  </header>
</template>
