<script setup lang="ts">
// Avatar dropdown shown in the topbar. Replaces the inert sidebar profile
// card that used to live in OpSidebar. Owns its own open/close state plus
// outside-click + Escape + route-change dismissal so the parent topbar stays
// dumb.

const { user } = useOidcAuth()
const { state: tweaks, setTheme } = useTweaks()
const route = useRoute()

const open = ref(false)

const displayName = computed<string>(() => {
  const name = (user.value?.userInfo as { name?: string } | undefined)?.name
  return name || (user.value?.userName as string | undefined) || 'operator'
})
const email = computed(() => (user.value?.userInfo as { email?: string } | undefined)?.email ?? '')

function toggle() {
  open.value = !open.value
}
function close() {
  open.value = false
}
function flipTheme() {
  setTheme(tweaks.value.theme === 'dark' ? 'light' : 'dark')
}

async function signOut() {
  close()
  // Use our custom endpoint instead of useOidcAuth().logout() — see
  // apps/operator/server/api/auth/sign-out.get.ts. It ends BOTH the local
  // session and the Authentik IdP session (required for shared-workstation
  // safety on an elevated-privilege portal) and lands on /signed-out.
  await navigateTo('/api/auth/sign-out', { external: true })
}

watch(() => route.path, close)

onMounted(() => {
  const onKey = (e: KeyboardEvent) => {
    if (e.key === 'Escape' && open.value) close()
  }
  document.addEventListener('keydown', onKey)
  onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
})
</script>

<template>
  <div class="usermenu">
    <button class="trigger" :class="{ on: open }" type="button" :title="displayName" @click="toggle">
      <Avatar :name="displayName" :size="26" />
    </button>

    <Teleport to="body">
      <div v-if="open" class="scrim" @click="close" />
    </Teleport>

    <Transition name="menu">
      <div v-if="open" class="menu" role="menu" aria-label="User menu">
        <div class="ident">
          <Avatar :name="displayName" :size="32" />
          <div class="ident-meta">
            <div class="ident-name">{{ displayName }}</div>
            <Mono dim>{{ email }}</Mono>
          </div>
        </div>

        <div class="divider" />

        <button class="item" type="button" role="menuitem" @click="flipTheme">
          <UiIcon :name="tweaks.theme === 'dark' ? 'shield' : 'shield'" :size="13" />
          <span class="label">Theme · {{ tweaks.theme === 'dark' ? 'dark' : 'light' }}</span>
          <Mono dim>{{ tweaks.theme === 'dark' ? 'switch to light' : 'switch to dark' }}</Mono>
        </button>

        <NuxtLink class="item" to="/settings" role="menuitem" @click="close">
          <UiIcon name="shield" :size="13" />
          <span class="label">Settings</span>
        </NuxtLink>

        <div class="divider" />

        <button class="item danger" type="button" role="menuitem" @click="signOut">
          <UiIcon name="logout" :size="13" />
          <span class="label">Sign out</span>
        </button>
      </div>
    </Transition>
  </div>
</template>

<style scoped>
.usermenu { position: relative; }

.trigger {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.trigger:hover { border-color: var(--border); }
.trigger.on { border-color: var(--border-hi); }

/* Transparent full-screen scrim that catches outside clicks. Sits below the
   menu since the menu is positioned in the same .usermenu container above. */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: transparent;
}

.menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 100;
  width: 240px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.32);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ident {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
}
.ident-meta { min-width: 0; flex: 1; }
.ident-name { font-size: 13px; font-weight: 500; }

.divider { height: 1px; background: var(--border); margin: 4px 0; }

.item {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.item:hover { background: var(--surface); }
.item .label { flex: 1; }
.item.danger { color: var(--bad); }
.item.danger:hover { background: rgba(240, 88, 88, 0.08); }

.menu-enter-active, .menu-leave-active { transition: opacity 0.12s, transform 0.12s; }
.menu-enter-from, .menu-leave-to { opacity: 0; transform: translateY(-4px); }
</style>
