<script setup>
import { computed, ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLayout } from '@/layout/composables/layout'

import AppMenuItem from './AppMenuItem.vue'
import AppMenuFooterPanel from './AppMenuFooterPanel.vue'
import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue'


import { useMenuStore } from '@/stores/menuStore'

const route = useRoute()
const router = useRouter()
const { layoutState } = useLayout()

const menuStore = useMenuStore()

// ======================================================
// ✅ Blindagem anti-“menu some”
// - se o menuStore.model piscar como [], mantém o último menu válido
// - evita sumiço ao entrar em /admin/clinic/features (reset momentâneo)
// ======================================================

// raw (pode piscar vazio)
const rawModel = computed(() => menuStore.model || [])

// último menu válido
const lastGoodModel = ref([])

// debounce curto para aceitar "vazio real" (ex.: logout) sem travar UI
let acceptEmptyT = null

function setLastGoodIfValid (m) {
  if (Array.isArray(m) && m.length) {
    lastGoodModel.value = m
  }
}

watch(
  rawModel,
  (m) => {
    // se veio com itens, atualiza na hora
    if (Array.isArray(m) && m.length) {
      if (acceptEmptyT) clearTimeout(acceptEmptyT)
      setLastGoodIfValid(m)
      return
    }

    // se veio vazio, NÃO derruba o menu imediatamente.
    // Só aceita vazio se continuar vazio por um tempinho.
    if (acceptEmptyT) clearTimeout(acceptEmptyT)
    acceptEmptyT = setTimeout(() => {
      // se ainda estiver vazio, e você quiser realmente limpar, faça aqui.
      // Por padrão, manteremos o último menu válido para evitar UX quebrada.
      // Se quiser limpar em logout, o logout deve limpar lastGoodModel explicitamente.
    }, 250)
  },
  { immediate: true, deep: false }
)

// model final exibido (com fallback)
const model = computed(() => {
  const m = rawModel.value
  if (Array.isArray(m) && m.length) return m
  if (Array.isArray(lastGoodModel.value) && lastGoodModel.value.length) return lastGoodModel.value
  return []
})

// ✅ rota -> activePath (NÃO fecha menu)
watch(
  () => route.path,
  (p) => { layoutState.activePath = p },
  { immediate: true }
)

// ======================================================
// 🔎 Busca no menu (mantive igual)
// ======================================================
const query = ref('')
const showResults = ref(false)
const activeIndex = ref(-1)
const forcedOpen = ref(false)

const searchEl = ref(null)
const searchWrapEl = ref(null)

const RECENT_KEY = 'menu_search_recent'
const recent = ref([])

function loadRecent () {
  try { recent.value = JSON.parse(localStorage.getItem(RECENT_KEY) || '[]') } catch { recent.value = [] }
}
function saveRecent (q) {
  const v = String(q || '').trim()
  if (!v) return
  const list = [v, ...recent.value.filter(x => x !== v)].slice(0, 8)
  recent.value = list
  localStorage.setItem(RECENT_KEY, JSON.stringify(list))
}
function clearRecent () {
  recent.value = []
  try { localStorage.removeItem(RECENT_KEY) } catch {}
}
loadRecent()

watch(query, (v) => {
  const hasText = !!v?.trim()
  if (hasText) {
    forcedOpen.value = false
    showResults.value = true
    return
  }
  showResults.value = forcedOpen.value
})

function clearSearch () {
  query.value = ''
  activeIndex.value = -1
  showResults.value = false
  forcedOpen.value = false
}

function norm (s) {
  return String(s || '')
    .toLowerCase()
    .normalize('NFD')
    .replace(/\p{Diacritic}/gu, '')
    .trim()
}

function isVisibleItem (it) {
  const v = it?.visible
  if (typeof v === 'function') return !!v()
  if (v === undefined || v === null) return true
  return v !== false
}

function flattenMenu (items, trail = []) {
  const out = []
  for (const it of (items || [])) {
    if (!isVisibleItem(it)) continue

    const nextTrail = [...trail, it?.label].filter(Boolean)

    if (it?.to && !it?.items?.length) {
      out.push({
        label: it.label || it.to,
        to: it.to,
        icon: it.icon,
        trail: nextTrail,

        // ✅ usa cálculo dinâmico vindo do navigation (quando existir)
        proBadge: !!(it.__showProBadge ?? it.proBadge),

        feature: it.feature || null
      })
    }

    if (it?.items?.length) {
      out.push(...flattenMenu(it.items, nextTrail))
    }
  }
  return out
}

const allLinks = computed(() => flattenMenu(model.value))

const results = computed(() => {
  const q = norm(query.value)
  if (!q) return []

  const wantPro = q === 'pro' || q.startsWith('pro ') || q.includes(' pro')

  return allLinks.value
    .filter(r => {
      const hay = `${norm(r.label)} ${norm(r.trail.join(' > '))} ${norm(r.to)}`
      if (hay.includes(q)) return true
      if (wantPro && (r.proBadge || r.feature)) return true
      return false
    })
    .slice(0, 12)
})

watch(results, (list) => {
  activeIndex.value = list.length ? 0 : -1
})

function escapeHtml (s) {
  return String(s || '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
}

function highlight (text, q) {
  const queryNorm = norm(q)
  const raw = String(text || '')
  if (!queryNorm) return escapeHtml(raw)

  const rawNorm = norm(raw)
  const idx = rawNorm.indexOf(queryNorm)
  if (idx < 0) return escapeHtml(raw)

  const before = escapeHtml(raw.slice(0, idx))
  const mid = escapeHtml(raw.slice(idx, idx + queryNorm.length))
  const after = escapeHtml(raw.slice(idx + queryNorm.length))
  return `${before}<mark class="px-1 rounded bg-yellow-200/40">${mid}</mark>${after}`
}

function onSearchKeydown (e) {
  if (e.key === 'Escape') {
    showResults.value = false
    forcedOpen.value = false
    return
  }

  if (e.key === 'ArrowDown') {
    e.preventDefault()
    if (!results.value.length) return
    showResults.value = true
    activeIndex.value = (activeIndex.value + 1) % results.value.length
    return
  }

  if (e.key === 'ArrowUp') {
    e.preventDefault()
    if (!results.value.length) return
    showResults.value = true
    activeIndex.value = (activeIndex.value - 1 + results.value.length) % results.value.length
    return
  }

  if (e.key === 'Enter') {
    if (showResults.value && results.value.length && activeIndex.value >= 0) {
      e.preventDefault()
      goTo(results.value[activeIndex.value])
    }
  }
}

function isTypingTarget (el) {
  if (!el) return false
  const tag = (el.tagName || '').toLowerCase()
  return tag === 'input' || tag === 'textarea' || el.isContentEditable
}

function focusSearch () {
  forcedOpen.value = true
  showResults.value = true

  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      const inst = searchEl.value
      const input =
        inst?.$el?.tagName === 'INPUT'
          ? inst.$el
          : inst?.$el?.querySelector?.('input')

      input?.focus?.()
    })
  })
}

function onGlobalKeydown (e) {
  if (isTypingTarget(document.activeElement)) return

  const isK = e.key?.toLowerCase() === 'k'
  const withCmdOrCtrl = e.ctrlKey || e.metaKey

  if (withCmdOrCtrl && isK) {
    e.preventDefault()
    e.stopPropagation()
    focusSearch()
  }
}

function applyRecent (q) {
  query.value = q
  forcedOpen.value = true
  showResults.value = true
  activeIndex.value = 0
  nextTick(() => focusSearch())
}

function onDocMouseDown (e) {
  if (!showResults.value) return
  const root = searchWrapEl.value
  if (!root) return
  if (!root.contains(e.target)) {
    showResults.value = false
    forcedOpen.value = false
  }
}

onMounted(() => {
  window.addEventListener('keydown', onGlobalKeydown, true)
  document.addEventListener('mousedown', onDocMouseDown)
})
onBeforeUnmount(() => {
  if (acceptEmptyT) clearTimeout(acceptEmptyT)
  window.removeEventListener('keydown', onGlobalKeydown, true)
  document.removeEventListener('mousedown', onDocMouseDown)
})

async function goTo (r) {
  saveRecent(query.value)

  query.value = ''
  showResults.value = false
  activeIndex.value = -1
  forcedOpen.value = false

  await router.push(r.to)
}

// ==============================
// Quick create
// ==============================
const quickDialog = ref(false)
function onQuickCreate () { quickDialog.value = true }
function onQuickCreated () { quickDialog.value = false }

function onSearchFocus () {
  if (!query.value?.trim()) {
    forcedOpen.value = true
    showResults.value = true
  }
}
</script>

<template>
  <div class="flex flex-col h-full">
    <!-- 🔎 TOPO FIXO -->
    <div ref="searchWrapEl" class="px-3 pt-3 pb-2 border-b border-[var(--surface-border)] bg-[var(--surface-card)]">
      <div class="relative">
        <div
          aria-hidden="true"
          style="position:absolute; left:-9999px; top:-9999px; width:1px; height:1px; overflow:hidden;"
        >
          <input type="email" name="email" autocomplete="username" tabindex="-1" disabled />
          <input type="password" name="password" autocomplete="current-password" tabindex="-1" disabled />
        </div>

        <FloatLabel variant="on" class="w-full">
          <IconField class="w-full">
            <InputIcon class="pi pi-search" />
            <InputText
              ref="searchEl"
              id="menu_search"
              name="menu_search"
              type="search"
              inputmode="search"
              autocomplete="off"
              autocapitalize="off"
              autocorrect="off"
              spellcheck="false"
              data-lpignore="true"
              data-1p-ignore="true"
              v-model="query"
              class="w-full pr-10"
              variant="filled"
              @focus="onSearchFocus"
              @keydown="onSearchKeydown"
            />
          </IconField>
          <label for="menu_search">Encontrar menu...</label>
        </FloatLabel>

        <button
          v-if="query.trim()"
          type="button"
          class="absolute right-2 top-1/2 -translate-y-1/2 opacity-70 hover:opacity-100"
          @mousedown.prevent="clearSearch"
          aria-label="Limpar busca"
        >
          <i class="pi pi-times" />
        </button>
      </div>

      <div
        v-if="showResults && !query.trim() && recent.length"
        class="mt-2 border border-[var(--surface-border)] rounded-xl bg-[var(--surface-card)] shadow-sm overflow-hidden"
      >
        <div class="px-3 py-2 text-xs opacity-70 flex items-center justify-content-between">
          <span>Recentes</span>
          <button
            type="button"
            class="opacity-70 hover:opacity-100"
            @mousedown.prevent="clearRecent"
            aria-label="Limpar recentes"
          >
            <i class="pi pi-trash" />
          </button>
        </div>

        <button
          v-for="q in recent"
          :key="q"
          class="w-full text-left px-3 py-2 hover:bg-[var(--surface-hover)] flex items-center gap-2"
          type="button"
          @click.stop.prevent="applyRecent(q)"
        >
          <i class="pi pi-history opacity-70" />
          <div class="flex-1">{{ q }}</div>
        </button>
      </div>

      <div
        v-else-if="showResults && results.length"
        class="mt-2 border border-[var(--surface-border)] rounded-xl bg-[var(--surface-card)] shadow-sm overflow-hidden"
      >
        <button
          v-for="(r, i) in results"
          :key="String(r.to)"
          type="button"
          @mousedown.prevent="goTo(r)"
          :class="[
            'w-full text-left px-3 py-2 flex items-center gap-2',
            i === activeIndex ? 'bg-[var(--surface-hover)]' : 'hover:bg-[var(--surface-hover)]'
          ]"
        >
          <i v-if="r.icon" :class="r.icon" class="opacity-80" />
          <div class="flex flex-col flex-1">
            <div class="font-medium leading-tight" v-html="highlight(r.label, query)" />
            <small class="opacity-70">{{ r.trail.join(' > ') }}</small>
          </div>

          <span
            v-if="r.proBadge"
            class="text-xs px-2 py-0.5 rounded border border-[var(--surface-border)] opacity-80"
          >
            PRO
          </span>
        </button>
      </div>

      <div v-else-if="showResults && query && !results.length" class="mt-2 px-3 py-2 text-sm opacity-70">
        Nenhum item encontrado.
      </div>
    </div>

    <div class="flex-1 overflow-y-auto">
      <ul class="layout-menu pb-20">
        <template v-for="(item, i) in model" :key="i">
          <AppMenuItem :item="item" :index="i" :root="true" @quick-create="onQuickCreate" />
        </template>
      </ul>
    </div>

    <AppMenuFooterPanel />

    <ComponentCadastroRapido
      v-model="quickDialog"
      title="Cadastro Rápido"
      table-name="patients"
      name-field="nome_completo"
      email-field="email_principal"
      phone-field="telefone"
      :extra-payload="{ status: 'Ativo' }"
      @created="onQuickCreated"
    />
  </div>
</template>