<script setup lang="ts">
/**
 * AppTopbar — production port of crewli-starter AppTopbar.vue.
 *
 * Wiring:
 *  - Hamburger → shell.setMobileOpen(true) (mobile only, lg:hidden)
 *  - Brand: static mark + wordmark (Tailwind from .topbar-brand/.mark/.wordmark)
 *  - Breadcrumb: PrimeVue <Breadcrumb> fed from useBreadcrumb(), route-driven
 *  - Mobile workspace button: org gradient via computeOrgGradient() + initials
 *  - Search: static InputText with ⌘K hint (no backend, chrome only)
 *  - Density toggle: shell.setDensity() with flipped value
 *  - Theme toggle: shell.setTheme() with flipped value
 *  - Notifications: stubbed with count=0 — useNotificationStore is a toast/snackbar
 *    queue (visible/message/type) not a notification feed; real feed is not
 *    foundation scope.
 *    TODO TECH-WS-GUI-REDESIGN: real notification feed — not foundation scope
 *  - User menu: PrimeVue Menu with #start slot for user header; Sign out → authStore.logout()
 *  - All click-outside: PrimeVue Popover/Menu built-in dismissal (no document.addEventListener)
 *
 * Notifications decision (A7): useNotificationStore exposes only
 *   { visible, message, type, timeout, show, hide } — a toast/snackbar queue,
 *   not a persistent notification feed with unread counts or list items.
 *   Decision: STUB at count=0, empty list, with TODO comment above.
 *
 * Icon convention: import Icon from '@/components/Icon.vue', <Icon name="tabler-x" :size="N" />
 *
 * Styling: crewli-starter CSS translated to Tailwind inline.
 * <style scoped> used only for:
 *   1. topbar-mark-shadow — inset box-shadow (no Tailwind utility at this granularity, RFC §7.4)
 *   2. ws-mobile-btn-shadow — same inset shadow justification
 */

import Avatar from 'primevue/avatar'
import Breadcrumb from 'primevue/breadcrumb'
import InputText from 'primevue/inputtext'
import Menu from 'primevue/menu'
import OverlayBadge from 'primevue/overlaybadge'
import Popover from 'primevue/popover'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import type { MenuItem } from 'primevue/menuitem'
import Icon from '@/components/Icon.vue'
import { useBreadcrumb } from '@/composables/useBreadcrumb'
import { useAuthStore } from '@/stores/useAuthStore'
import { useShellUiStore } from '@/stores/useShellUiStore'
import { computeOrgGradient } from '@/utils/v2/gradient'

// ---------------------------------------------------------------------------
// Stores / router
// ---------------------------------------------------------------------------

const shell = useShellUiStore()
const authStore = useAuthStore()
const router = useRouter()

// ---------------------------------------------------------------------------
// Breadcrumb — route-driven via useBreadcrumb()
// ---------------------------------------------------------------------------

const { items: breadcrumbItems } = useBreadcrumb()

/**
 * Map BreadcrumbItem[] → PrimeVue MenuItem[].
 *
 * The installed PrimeVue Breadcrumb (BreadcrumbItem.vue) renders
 * `<a :href="item.url || '#'">` and calls `item.command` on click.
 * It does NOT honour a `route` key — router-link is never invoked.
 *
 * Fix: non-last items navigate via `command: () => router.push(item.to)` (client-side,
 * no full reload, no href="#"). Last/current item has no `to` from useBreadcrumb()
 * → no command → non-interactive.
 */
const breadcrumbModel = computed<MenuItem[]>(() =>
  breadcrumbItems.value.map(item => {
    const base: MenuItem = { label: item.label }

    if (item.to !== undefined) {
      base.command = () => {
        router.push(item.to!)
      }
    }

    return base
  }),
)

// ---------------------------------------------------------------------------
// User initials derived from full_name
// ---------------------------------------------------------------------------

const userInitials = computed<string>(() => {
  const name = authStore.user?.full_name?.trim() ?? ''

  if (!name)
    return '?'

  const words = name.split(/\s+/)

  return words.length >= 2
    ? (words[0][0] + words[words.length - 1][0]).toUpperCase()
    : name.slice(0, 2).toUpperCase()
})

// ---------------------------------------------------------------------------
// Mobile workspace button
// ---------------------------------------------------------------------------

const mobileOrgGradient = computed<[string, string]>(() => {
  const id = authStore.currentOrganisation?.id ?? ''

  return computeOrgGradient(id)
})

const mobileOrgInitials = computed<string>(() => {
  const name = authStore.currentOrganisation?.name?.trim() ?? ''

  if (!name)
    return '?'

  const words = name.split(/\s+/)

  return words.length >= 2
    ? (words[0][0] + words[1][0]).toUpperCase()
    : name.slice(0, 2).toUpperCase()
})

// ---------------------------------------------------------------------------
// Density toggle
// ---------------------------------------------------------------------------

function toggleDensity(): void {
  shell.setDensity(shell.density === 'comfortable' ? 'compact' : 'comfortable')
}

const densityAriaLabel = computed<string>(() =>
  shell.density === 'comfortable' ? 'Switch to compact' : 'Switch to comfortable',
)

const densityIcon = computed<string>(() =>
  shell.density === 'comfortable'
    ? 'tabler-layout-distribute-vertical'
    : 'tabler-layout-distribute-horizontal',
)

// ---------------------------------------------------------------------------
// Theme toggle
// ---------------------------------------------------------------------------

function toggleTheme(): void {
  shell.setTheme(shell.theme === 'dark' ? 'light' : 'dark')
}

const themeAriaLabel = computed<string>(() =>
  shell.theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode',
)

const themeIcon = computed<string>(() =>
  shell.theme === 'dark' ? 'tabler-sun' : 'tabler-moon',
)

// ---------------------------------------------------------------------------
// Notifications — STUBBED (see file header for A7 decision)
// TODO TECH-WS-GUI-REDESIGN: real notification feed — not foundation scope
// ---------------------------------------------------------------------------

const notifCount = 0
const notifPopoverRef = ref<InstanceType<typeof Popover> | null>(null)

function toggleNotifPopover(event: MouseEvent): void {
  notifPopoverRef.value?.toggle(event)
}

// ---------------------------------------------------------------------------
// User menu — PrimeVue Menu (replaces crewli-starter manual mousedown listener)
// ---------------------------------------------------------------------------

const userMenuRef = ref<InstanceType<typeof Menu> | null>(null)

function toggleUserMenu(event: MouseEvent): void {
  userMenuRef.value?.toggle(event)
}

const userMenuItems = computed<MenuItem[]>(() => [
  {
    items: [
      {
        label: 'Profile',
        icon: 'tabler-user',
        command: () => {
          // TODO TECH-WS-GUI-REDESIGN: routes not yet defined
        },
      },
      {
        label: 'Account settings',
        icon: 'tabler-settings',
        command: () => {
          // TODO TECH-WS-GUI-REDESIGN: routes not yet defined
        },
      },
      {
        label: 'Workspace settings',
        icon: 'tabler-adjustments',
        command: () => {
          // TODO TECH-WS-GUI-REDESIGN: routes not yet defined
        },
      },
    ],
  },
  {
    items: [
      {
        label: 'Keyboard shortcuts',
        icon: 'tabler-keyboard',
        command: () => {
          // TODO TECH-WS-GUI-REDESIGN: routes not yet defined
        },
      },
      {
        label: 'Help & support',
        icon: 'tabler-help',
        command: () => {
          // TODO TECH-WS-GUI-REDESIGN: routes not yet defined
        },
      },
    ],
  },
  {
    items: [
      {
        label: 'Sign out',
        icon: 'tabler-logout',
        command: () => {
          authStore.logout()
        },
      },
    ],
  },
])
</script>

<template>
  <!--
    .topbar: sticky top-0, h-[var(--topbar-h)], flex items-center, gap-3,
    bg-[var(--surface)], border-b border-[var(--border)], z-30, px-5
  -->
  <header class="sticky top-0 z-30 flex h-[var(--topbar-h,56px)] items-center gap-3 border-b border-[var(--p-content-border-color)] bg-[var(--p-content-background)] px-5">
    <!-- Left group: hamburger + brand + breadcrumb -->
    <div class="flex items-center gap-[6px]">
      <!--
        Hamburger — mobile only (lg:hidden).
        .hamburger: display none at >=lg, display inline-flex at <768px
        .icon-btn: 38x38, rounded, transparent bg, fg-muted color, hover bg-hover
      -->
      <button
        type="button"
        class="lg:hidden inline-flex h-[38px] w-[38px] items-center justify-center rounded-[var(--p-border-radius)] border-0 bg-transparent text-[var(--p-text-muted-color)] transition-colors duration-150 hover:bg-[var(--p-content-hover-background)] hover:text-[var(--p-text-color)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--p-primary-color)] focus-visible:outline-offset-1"
        aria-label="Open menu"
        @click="shell.setMobileOpen(true)"
      >
        <Icon
          name="tabler-menu-2"
          :size="20"
        />
      </button>

      <!--
        Brand — hidden on mobile, shown >=lg.
        .topbar-brand: display none default, display inline-flex >=lg
        .mark: 28x28, rounded-lg, gradient bg, white text, font-bold 13px
        .wordmark: font-bold 16px, tracking-tight
      -->
      <div class="hidden lg:inline-flex items-center gap-2">
        <!--
          Topbar mark — dynamic gradient cannot be a static Tailwind class.
          Inline style justified (RFC §7.4). Box-shadow via scoped CSS
          (inset-shadow has no Tailwind utility at this granularity).
        -->
        <div
          class="topbar-mark-shadow inline-flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg text-[13px] font-bold text-white"
          style="background: linear-gradient(135deg, var(--p-primary-500, #0d9488), var(--p-primary-700, #0f766e))"
          aria-hidden="true"
        >
          C
        </div>
        <span class="text-[16px] font-bold tracking-[-0.01em] text-[var(--p-text-color)]">
          Crewli
        </span>
      </div>

      <!--
        Breadcrumb — PrimeVue Breadcrumb, route-driven.
        .breadcrumb: flex, items-center, gap-[6px], text-[13px], color fg-muted, flex-wrap nowrap, overflow-hidden
        Hidden on mobile per crewli-starter (<768px: display:none!important)
      -->
      <nav
        class="hidden lg:flex items-center"
        aria-label="Breadcrumb"
      >
        <Breadcrumb
          :model="breadcrumbModel"
          class="border-0 bg-transparent p-0 text-[13px]"
        />
      </nav>
    </div>

    <!-- Right group: ws-mobile-btn, search, density, theme, notifications, user -->
    <div class="ms-auto flex items-center gap-[6px]">
      <!--
        Mobile workspace button — visible only <lg.
        .ws-mobile-btn: display none (>= 1024px). On mobile: display flex.
        38x38, rounded, color #fff, font-bold 12px, gradient bg via inline :style
        (dynamic hex pair — RFC §7.4). Box-shadow via scoped CSS.
      -->
      <button
        v-if="authStore.currentOrganisation"
        type="button"
        class="ws-mobile-btn-shadow lg:hidden inline-flex h-[38px] w-[38px] flex-shrink-0 items-center justify-center rounded-[var(--p-border-radius)] border-0 text-[12px] font-bold text-white"
        :style="{
          background: `linear-gradient(135deg, ${mobileOrgGradient[0]}, ${mobileOrgGradient[1]})`,
        }"
        :aria-label="`Workspace: ${authStore.currentOrganisation.name}`"
      >
        {{ mobileOrgInitials }}
      </button>

      <!--
        Search — static chrome, no backend.
        .search: position relative, w-[320px], max-w-full
        .search input: h-[38px], px-[12px] ps-[36px], bg-surface-alt, border rounded
        .search .kbd: absolute right-2, text-[11px], px-[6px] py-[2px], border rounded
        Hidden on smallest viewports per crewli-starter (<768px: width 0 / display:none)
      -->
      <div class="relative hidden sm:block w-[240px] lg:w-[320px] max-w-full">
        <Icon
          name="tabler-search"
          :size="16"
          class="pointer-events-none absolute left-[11px] top-1/2 -translate-y-1/2 text-[var(--p-text-muted-color)]"
        />
        <InputText
          class="h-[38px] w-full rounded-[var(--p-border-radius)] border border-transparent bg-[var(--p-content-hover-background)] ps-[36px] pe-[52px] text-[var(--p-text-color)] placeholder:text-[var(--p-text-muted-color)] focus:border-[var(--p-primary-color)] focus:bg-[var(--p-content-background)] focus:shadow-[0_0_0_3px_var(--p-primary-50)] focus:outline-none transition-[border-color,background,box-shadow] duration-150"
          placeholder="Search artists, crew, events..."
          :pt="{ root: { 'data-search-input': '' } }"
        />
        <span class="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 rounded-[var(--p-border-radius-sm,4px)] border border-[var(--p-content-border-color)] bg-[var(--p-content-background)] px-[6px] py-[2px] font-mono text-[11px] text-[var(--p-text-muted-color)]">
          ⌘K
        </span>
      </div>

      <!--
        Density toggle.
        .icon-btn: 38x38, inline-flex, centered, rounded, transparent, fg-muted, hover bg-hover
      -->
      <button
        type="button"
        class="inline-flex h-[38px] w-[38px] items-center justify-center rounded-[var(--p-border-radius)] border-0 bg-transparent text-[var(--p-text-muted-color)] transition-colors duration-150 hover:bg-[var(--p-content-hover-background)] hover:text-[var(--p-text-color)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--p-primary-color)] focus-visible:outline-offset-1"
        :aria-label="densityAriaLabel"
        @click="toggleDensity"
      >
        <Icon
          :name="densityIcon"
          :size="18"
        />
      </button>

      <!-- Theme toggle. -->
      <button
        type="button"
        class="inline-flex h-[38px] w-[38px] items-center justify-center rounded-[var(--p-border-radius)] border-0 bg-transparent text-[var(--p-text-muted-color)] transition-colors duration-150 hover:bg-[var(--p-content-hover-background)] hover:text-[var(--p-text-color)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--p-primary-color)] focus-visible:outline-offset-1"
        :aria-label="themeAriaLabel"
        @click="toggleTheme"
      >
        <Icon
          :name="themeIcon"
          :size="18"
        />
      </button>

      <!--
        Notifications — stubbed bell with OverlayBadge.
        PrimeVue Popover replaces crewli-starter's manual document.addEventListener('mousedown', …)
        TODO TECH-WS-GUI-REDESIGN: real notification feed — not foundation scope
      -->
      <OverlayBadge
        :value="notifCount > 0 ? String(notifCount) : undefined"
        severity="danger"
      >
        <button
          type="button"
          class="inline-flex h-[38px] w-[38px] items-center justify-center rounded-[var(--p-border-radius)] border-0 bg-transparent text-[var(--p-text-muted-color)] transition-colors duration-150 hover:bg-[var(--p-content-hover-background)] hover:text-[var(--p-text-color)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--p-primary-color)] focus-visible:outline-offset-1"
          aria-label="Notifications"
          @click="toggleNotifPopover"
        >
          <Icon
            name="tabler-bell"
            :size="18"
          />
        </button>
      </OverlayBadge>

      <Popover ref="notifPopoverRef">
        <div class="min-w-[320px] p-4 text-[13px] text-[var(--p-text-muted-color)]">
          No notifications
        </div>
      </Popover>

      <!--
        User menu — PrimeVue Avatar + Menu.
        Avatar: 32x32, rounded-full, initials, gradient bg.
        Menu: PrimeVue Menu replaces crewli-starter's manual click-outside listener.
        #start slot used for user info header.
      -->
      <Avatar
        :label="userInitials"
        shape="circle"
        class="cursor-pointer"
        :pt="{ root: { style: 'background: linear-gradient(135deg, #f472b6, var(--p-primary-500, #0d9488)); color: #fff;' } }"
        aria-label="User menu"
        @click="toggleUserMenu"
      />

      <Menu
        ref="userMenuRef"
        :model="userMenuItems"
        popup
      >
        <template #start>
          <div class="flex items-center gap-3 px-4 py-3 border-b border-[var(--p-content-border-color)]">
            <Avatar
              :label="userInitials"
              shape="circle"
              :pt="{ root: { style: 'background: linear-gradient(135deg, #f472b6, var(--p-primary-500, #0d9488)); color: #fff; width:40px; height:40px; font-size:14px;' } }"
            />
            <div class="min-w-0">
              <div class="truncate text-[13.5px] font-semibold text-[var(--p-text-color)]">
                {{ authStore.user?.full_name ?? '' }}
              </div>
              <div class="truncate text-[12px] text-[var(--p-text-muted-color)]">
                {{ authStore.user?.email ?? '' }}
              </div>
            </div>
          </div>
        </template>
      </Menu>
    </div>
  </header>
</template>

<style scoped>
/**
 * FIX 1: topbar-mark-shadow — inset directional box-shadow.
 * Tailwind has no inset-shadow utility at this depth/direction granularity → RFC §7.4.
 */
.topbar-mark-shadow {
  box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
}

/**
 * FIX 2: ws-mobile-btn-shadow — same inset shadow justification as above.
 * Background gradient is set via inline :style (dynamic hex pair from computeOrgGradient).
 */
.ws-mobile-btn-shadow {
  box-shadow: inset 0 -2px 0 rgb(0 0 0 / 10%);
}
</style>
