@php
    use Illuminate\Support\Facades\Route;

    $user     = auth()->user();
    $role     = $user ? $user->roles->first() : null;
    $roleName = $role ? $role->name : 'User';

    // Role badge colour map
    $roleColors = [
        'Super Manager'  => 'bg-purple-500',
        'Manager'        => 'bg-blue-600',
        'Members'        => 'bg-green-500',
        'Trainers'       => 'bg-orange-500',
        'Trainees'       => 'bg-yellow-500',
        'Mentor'         => 'bg-teal-500',
        'Mentee'         => 'bg-cyan-500',
        'Partners'       => 'bg-indigo-500',
        'Contributor'    => 'bg-pink-500',
        'Health Marketor'=> 'bg-red-500',
    ];
    $roleBadgeClass = $roleColors[$roleName] ?? 'bg-gray-500';
@endphp

{{-- ============================================================
     APP HEADER COMPONENT
     x-data="appHeaderData()" — all reactive state lives in the
     appHeaderData() function defined at the bottom of this file.
     ============================================================ --}}
<header
    x-data="appHeaderData()"
    x-init="init()"
    @keydown.escape.window="closeSearch(); notificationsOpen = false; profileOpen = false;"
    class="sticky top-0 z-30 h-16 bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b border-gray-200/60 dark:border-gray-700/60 shadow-sm transition-all duration-300"
>
    <div class="h-full max-w-7xl mx-auto px-4 sm:px-6 flex items-center gap-3">

        {{-- ── LEFT: hamburger + logo + app name ─────────────────── --}}
        <div class="flex items-center gap-3 flex-shrink-0">
            {{-- Hamburger (mobile sidebar toggle) --}}
            <button
                @click="$root.toggleSidebar ? $root.toggleSidebar() : null"
                class="md:hidden p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                aria-label="Toggle Menu"
            >
                <i class="fa-solid fa-bars text-lg text-gray-700 dark:text-gray-300"></i>
            </button>

            {{-- Org logo / initials --}}
            @php $org = \App\Models\Organization::first(); @endphp
            <a href="{{ route('dashboard') }}" class="flex items-center gap-2 no-underline">
                <div class="w-8 h-8 rounded-lg bg-gradient-to-br from-blue-600 to-purple-600 flex items-center justify-center text-white font-bold text-sm flex-shrink-0">
                    {{ strtoupper(substr($org?->short_name ?? $org?->name ?? 'S', 0, 2)) }}
                </div>
                <span class="hidden lg:block text-sm font-semibold text-gray-800 dark:text-gray-100 truncate max-w-[140px]">
                    {{ $org?->short_name ?? $org?->name ?? 'SSHIA' }}
                </span>
            </a>
        </div>

        {{-- ── CENTER: desktop search bar ─────────────────────────── --}}
        <div class="flex-1 max-w-xl relative hidden md:block">
            <div class="relative">
                <i class="fa-solid fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm pointer-events-none"></i>
                <input
                    type="text"
                    x-model="searchQuery"
                    x-ref="searchInput"
                    @input="onSearchInput()"
                    @focus="if(searchQuery.length >= 2) searchOpen = true"
                    @keydown.arrow-down.prevent="navigateResults(1)"
                    @keydown.arrow-up.prevent="navigateResults(-1)"
                    @keydown.enter.prevent="selectFocused()"
                    @keydown.escape="closeSearch()"
                    placeholder="Search…"
                    autocomplete="off"
                    class="w-full pl-9 pr-9 py-2 text-sm rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
                />
                <button
                    x-show="searchQuery.length > 0"
                    @click="closeSearch(); searchQuery = ''; $refs.searchInput.focus()"
                    class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
                    aria-label="Clear search"
                >
                    <i class="fa-solid fa-times text-sm"></i>
                </button>
            </div>

            {{-- Search results modal --}}
            <div
                x-show="searchOpen"
                x-transition:enter="transition ease-out duration-150"
                x-transition:enter-start="opacity-0 -translate-y-1"
                x-transition:enter-end="opacity-100 translate-y-0"
                x-transition:leave="transition ease-in duration-100"
                x-transition:leave-start="opacity-100"
                x-transition:leave-end="opacity-0"
                @click.outside="closeSearch()"
                class="absolute top-full left-0 right-0 mt-2 w-full max-w-[calc(100vw-1rem)] z-[9999] bg-white dark:bg-gray-900 rounded-xl shadow-2xl border border-gray-200/60 dark:border-gray-700/60 overflow-hidden"
                style="display:none;"
            >
                {{-- Loading state --}}
                <div x-show="searchLoading" class="px-4 py-6 text-center">
                    <i class="fa-solid fa-spinner fa-spin text-blue-500 text-xl"></i>
                    <p class="text-sm text-gray-500 dark:text-gray-400 mt-2">Searching…</p>
                </div>

                {{-- Results --}}
                <div x-show="!searchLoading">
                    {{-- No results --}}
                    <div
                        x-show="Object.keys(searchResults).length === 0"
                        class="px-4 py-8 text-center"
                    >
                        <i class="fa-solid fa-search text-3xl text-gray-300 dark:text-gray-600 mb-2"></i>
                        <p class="text-sm text-gray-500 dark:text-gray-400">No results found</p>
                    </div>

                    {{-- Grouped results --}}
                    <template x-for="(items, group) in searchResults" :key="group">
                        <div>
                            <div class="px-4 py-2 bg-gray-50 dark:bg-gray-800/60 border-b border-gray-100 dark:border-gray-700">
                                <span class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider" x-text="group"></span>
                            </div>
                            <template x-for="(item, idx) in items" :key="item.id + '-' + group">
                                <a
                                    :href="item.url"
                                    :class="{'bg-blue-50 dark:bg-blue-900/30': focusedResultIndex === getFlatIndex(group, idx)}"
                                    class="flex items-center gap-3 px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors border-b border-gray-100 dark:border-gray-700/50 last:border-b-0 cursor-pointer"
                                    @mouseenter="focusedResultIndex = getFlatIndex(group, idx)"
                                >
                                    <div class="w-8 h-8 rounded-lg bg-blue-100 dark:bg-blue-900/40 flex items-center justify-center flex-shrink-0">
                                        <i class="fa-solid fa-file-alt text-blue-500 text-xs"></i>
                                    </div>
                                    <div class="flex-1 min-w-0">
                                        <p class="text-sm font-medium text-gray-900 dark:text-white truncate" x-text="item.title"></p>
                                        <p class="text-xs text-gray-500 dark:text-gray-400 truncate" x-text="item.subtitle ?? ''"></p>
                                    </div>
                                    <span class="text-xs text-gray-400 dark:text-gray-500 flex-shrink-0" x-text="item.type"></span>
                                </a>
                            </template>
                        </div>
                    </template>
                </div>
            </div>
        </div>

        {{-- ── RIGHT: mobile search, dark mode, notifications, avatar ─ --}}
        <div class="flex items-center gap-1 sm:gap-2 ml-auto">

            {{-- Mobile search toggle --}}
            <button
                @click="mobileSearchOpen = !mobileSearchOpen"
                class="md:hidden p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                aria-label="Search"
            >
                <i class="fa-solid fa-search text-gray-600 dark:text-gray-400"></i>
            </button>

            {{-- Dark mode toggle --}}
            <button
                @click="toggleDarkMode()"
                class="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                aria-label="Toggle Dark Mode"
            >
                <i
                    class="fa-solid text-lg transition-colors"
                    :class="darkMode ? 'fa-sun text-yellow-400' : 'fa-moon text-gray-600 dark:text-gray-400'"
                ></i>
            </button>

            {{-- ── Notification bell ──────────────────────────────── --}}
            <div class="relative">
                <button
                    @click="notificationsOpen = !notificationsOpen; profileOpen = false;"
                    class="relative p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                    aria-label="Notifications"
                >
                    <i class="fa-solid fa-bell text-lg text-gray-600 dark:text-gray-400"></i>
                    {{-- Unread badge --}}
                    <span
                        x-show="notificationCount > 0"
                        x-text="notificationCount > 99 ? '99+' : notificationCount"
                        class="absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 flex items-center justify-center text-[10px] font-bold text-white bg-red-500 rounded-full leading-none"
                        style="display:none;"
                    ></span>
                </button>

                {{-- Notification dropdown --}}
                <div
                    x-show="notificationsOpen"
                    x-transition:enter="transition ease-out duration-150"
                    x-transition:enter-start="opacity-0 scale-95"
                    x-transition:enter-end="opacity-100 scale-100"
                    x-transition:leave="transition ease-in duration-100"
                    x-transition:leave-start="opacity-100 scale-100"
                    x-transition:leave-end="opacity-0 scale-95"
                    @click.outside="notificationsOpen = false"
                    class="absolute right-0 mt-2 w-80 max-w-[calc(100vw-1rem)] z-[9999] bg-white dark:bg-gray-900 rounded-xl shadow-2xl border border-gray-200/60 dark:border-gray-700/60 overflow-hidden"
                    style="display:none;"
                >
                    {{-- Header --}}
                    <div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
                        <h3 class="text-sm font-semibold text-gray-900 dark:text-white">Notifications</h3>
                        <button
                            x-show="notificationCount > 0"
                            @click="markAllRead()"
                            class="text-xs text-blue-600 dark:text-blue-400 hover:underline"
                        >Mark all read</button>
                    </div>

                    {{-- Loading --}}
                    <div x-show="notificationsLoading" class="px-4 py-6 text-center">
                        <i class="fa-solid fa-spinner fa-spin text-blue-500"></i>
                    </div>

                    {{-- List --}}
                    <div x-show="!notificationsLoading" class="max-h-96 overflow-y-auto divide-y divide-gray-100 dark:divide-gray-700/50">
                        <template x-if="notifications.length === 0">
                            <div class="px-4 py-8 text-center">
                                <i class="fa-solid fa-bell-slash text-3xl text-gray-300 dark:text-gray-600 mb-2"></i>
                                <p class="text-sm text-gray-500 dark:text-gray-400">No notifications</p>
                            </div>
                        </template>
                        <template x-for="n in notifications" :key="n.id">
                            <a
                                :href="n.action_url ?? '#'"
                                @click.prevent="markRead(n.id); if(n.action_url) window.location.href = n.action_url"
                                class="flex items-start gap-3 px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors cursor-pointer"
                                :class="{'bg-blue-50/50 dark:bg-blue-900/10': !n.is_read}"
                            >
                                <div class="flex-shrink-0 w-8 h-8 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center mt-0.5">
                                    <i class="fa-solid text-sm" :class="n.icon ?? 'fa-bell text-blue-400'"></i>
                                </div>
                                <div class="flex-1 min-w-0">
                                    <p class="text-sm font-medium text-gray-900 dark:text-white truncate" x-text="n.title"></p>
                                    <p class="text-xs text-gray-500 dark:text-gray-400 mt-0.5 line-clamp-2" x-text="n.message"></p>
                                    <p class="text-xs text-gray-400 dark:text-gray-500 mt-1" x-text="n.time_ago"></p>
                                </div>
                                <span x-show="!n.is_read" class="flex-shrink-0 w-2 h-2 bg-blue-500 rounded-full mt-2"></span>
                            </a>
                        </template>
                    </div>
                </div>
            </div>

            {{-- ── Avatar + profile dropdown ──────────────────────── --}}
            <div class="relative">
                <button
                    @click="profileOpen = !profileOpen; notificationsOpen = false;"
                    class="flex items-center gap-2 p-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
                    aria-label="User Menu"
                >
                    {{-- Avatar image with initials fallback --}}
                    <div class="relative w-8 h-8 rounded-full overflow-hidden bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center flex-shrink-0">
                        <img
                            src="{{ $user->avatar_url }}"
                            alt="{{ $user->name }}"
                            class="w-full h-full object-cover"
                            onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
                        />
                        <span
                            class="absolute inset-0 items-center justify-center text-white font-semibold text-xs"
                            style="display:none;"
                        >{{ $user->initials }}</span>
                    </div>

                    {{-- Name + role (desktop) --}}
                    <div class="hidden sm:block text-left">
                        <p class="text-sm font-medium text-gray-900 dark:text-white leading-tight">{{ $user->name }}</p>
                        <p class="text-xs text-gray-500 dark:text-gray-400 leading-tight">{{ $roleName }}</p>
                    </div>
                    <i class="fa-solid fa-chevron-down text-xs text-gray-400 hidden sm:block"></i>
                </button>

                {{-- Profile dropdown --}}
                <div
                    x-show="profileOpen"
                    x-transition:enter="transition ease-out duration-150"
                    x-transition:enter-start="opacity-0 scale-95"
                    x-transition:enter-end="opacity-100 scale-100"
                    x-transition:leave="transition ease-in duration-100"
                    x-transition:leave-start="opacity-100 scale-100"
                    x-transition:leave-end="opacity-0 scale-95"
                    @click.outside="profileOpen = false"
                    class="absolute right-0 mt-2 w-64 max-w-[calc(100vw-1rem)] z-[9999] bg-white dark:bg-gray-900 rounded-xl shadow-2xl border border-gray-200/60 dark:border-gray-700/60 overflow-hidden"
                    style="display:none;"
                >
                    {{-- User info --}}
                    <div class="px-4 py-4 border-b border-gray-200 dark:border-gray-700">
                        <div class="flex items-center gap-3">
                            <div class="relative w-10 h-10 rounded-full overflow-hidden bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center flex-shrink-0">
                                <img
                                    src="{{ $user->avatar_url }}"
                                    alt="{{ $user->name }}"
                                    class="w-full h-full object-cover"
                                    onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"
                                />
                                <span
                                    class="absolute inset-0 items-center justify-center text-white font-semibold text-sm"
                                    style="display:none;"
                                >{{ $user->initials }}</span>
                            </div>
                            <div class="flex-1 min-w-0">
                                <p class="text-sm font-semibold text-gray-900 dark:text-white truncate">{{ $user->name }}</p>
                                <p class="text-xs text-gray-500 dark:text-gray-400 truncate">{{ $user->email }}</p>
                                <span class="inline-block mt-1 px-2 py-0.5 text-[10px] font-semibold text-white rounded-full {{ $roleBadgeClass }}">
                                    {{ $roleName }}
                                </span>
                            </div>
                        </div>
                    </div>

                    {{-- Menu items --}}
                    <div class="py-1">
                        <a
                            href="{{ route('profile.edit') }}"
                            class="flex items-center gap-3 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                            <i class="fa-solid fa-user w-4 text-gray-400"></i>
                            Edit Profile
                        </a>
                        <a
                            href="{{ $user->getDashboardUrl() }}"
                            class="flex items-center gap-3 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                            <i class="fa-solid fa-gauge w-4 text-gray-400"></i>
                            Dashboard
                        </a>
                        @if($user->hasSelfPacedPortalAccess())
                        <a
                            href="{{ route($user->getSelfPacedPortalRoute()) }}"
                            class="flex items-center gap-3 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                            <i class="fa-solid fa-graduation-cap w-4 text-indigo-500"></i>
                            {{ $user->hasRole('Trainees') ? 'My Courses' : 'Self-Paced Portal' }}
                        </a>
                        @endif
                        @role('Super Manager')
                        <a
                            href="{{ route('roles.index') }}"
                            class="flex items-center gap-3 px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                            <i class="fa-solid fa-user-shield w-4 text-gray-400"></i>
                            Role Management
                        </a>
                        @endrole
                    </div>

                    {{-- Logout --}}
                    <div class="border-t border-gray-200 dark:border-gray-700">
                        <form method="POST" action="{{ route('logout') }}">
                            @csrf
                            <button
                                type="submit"
                                class="flex items-center gap-3 w-full px-4 py-3 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors"
                            >
                                <i class="fa-solid fa-right-from-bracket w-4"></i>
                                Logout
                            </button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

    {{-- ── Mobile full-width search overlay ───────────────────────── --}}
    <div
        x-show="mobileSearchOpen"
        x-transition:enter="transition ease-out duration-200"
        x-transition:enter-start="opacity-0 -translate-y-2"
        x-transition:enter-end="opacity-100 translate-y-0"
        x-transition:leave="transition ease-in duration-150"
        x-transition:leave-start="opacity-100"
        x-transition:leave-end="opacity-0"
        class="md:hidden absolute top-16 left-0 right-0 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700 px-4 py-3 z-[9999]"
        style="display:none;"
    >
        <div class="relative">
            <i class="fa-solid fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm pointer-events-none"></i>
            <input
                type="text"
                x-model="searchQuery"
                @input="onSearchInput()"
                @keydown.escape="mobileSearchOpen = false; closeSearch()"
                placeholder="Search…"
                autocomplete="off"
                class="w-full pl-9 pr-9 py-2 text-sm rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-400 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            />
            <button
                @click="mobileSearchOpen = false; closeSearch(); searchQuery = ''"
                class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
                aria-label="Close search"
            >
                <i class="fa-solid fa-times text-sm"></i>
            </button>
        </div>

        {{-- Mobile search results --}}
        <div
            x-show="searchOpen"
            class="mt-2 w-full max-w-[calc(100vw-1rem)] bg-white dark:bg-gray-900 rounded-xl shadow-xl border border-gray-200/60 dark:border-gray-700/60 overflow-hidden"
            style="display:none;"
        >
            <div x-show="searchLoading" class="px-4 py-4 text-center">
                <i class="fa-solid fa-spinner fa-spin text-blue-500"></i>
            </div>
            <div x-show="!searchLoading" class="max-h-64 overflow-y-auto">
                <template x-if="Object.keys(searchResults).length === 0">
                    <div class="px-4 py-6 text-center">
                        <p class="text-sm text-gray-500 dark:text-gray-400">No results found</p>
                    </div>
                </template>
                <template x-for="(items, group) in searchResults" :key="group">
                    <div>
                        <div class="px-4 py-1.5 bg-gray-50 dark:bg-gray-800/60">
                            <span class="text-xs font-semibold text-gray-500 uppercase tracking-wider" x-text="group"></span>
                        </div>
                        <template x-for="item in items" :key="item.id">
                            <a
                                :href="item.url"
                                class="flex items-center gap-3 px-4 py-2.5 hover:bg-gray-50 dark:hover:bg-gray-800 border-b border-gray-100 dark:border-gray-700/50 last:border-b-0"
                            >
                                <p class="text-sm font-medium text-gray-900 dark:text-white truncate" x-text="item.title"></p>
                            </a>
                        </template>
                    </div>
                </template>
            </div>
        </div>
    </div>
</header>

<script>
/**
 * appHeaderData()
 * Alpine.js component function for the app header.
 * Manages search, notifications, profile dropdown, dark mode.
 */
function appHeaderData() {
    return {
        // ── Search state ──────────────────────────────────────────
        searchQuery:        '',
        searchOpen:         false,
        searchResults:      {},
        searchLoading:      false,
        searchDebounceTimer: null,
        focusedResultIndex: -1,
        _flatResults:       [],   // flattened for keyboard nav

        // ── Mobile search overlay ─────────────────────────────────
        mobileSearchOpen: false,

        // ── Notification state ────────────────────────────────────
        notificationsOpen:    false,
        notificationCount:    0,
        notifications:        [],
        notificationsLoading: false,
        pollingTimer:         null,

        // ── Profile dropdown ──────────────────────────────────────
        profileOpen: false,

        // ── Dark mode ─────────────────────────────────────────────
        darkMode: localStorage.getItem('darkMode') === 'true',

        // ─────────────────────────────────────────────────────────
        // Lifecycle
        // ─────────────────────────────────────────────────────────
        init() {
            // Apply persisted dark mode
            if (this.darkMode) {
                document.documentElement.classList.add('dark');
            }
            this.fetchNotifications();
            this.startPolling();
        },

        destroy() {
            this.stopPolling();
        },

        // ─────────────────────────────────────────────────────────
        // Search
        // ─────────────────────────────────────────────────────────
        onSearchInput() {
            clearTimeout(this.searchDebounceTimer);
            if (this.searchQuery.length < 2) {
                this.closeSearch();
                return;
            }
            this.searchDebounceTimer = setTimeout(() => this.fetchSearch(), 300);
        },

        fetchSearch() {
            if (this.searchQuery.length < 2) return;
            this.searchLoading = true;
            this.searchOpen    = true;

            const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
            const url       = `{{ route('api.header.search') }}?q=${encodeURIComponent(this.searchQuery)}`;

            fetch(url, {
                headers: {
                    'Accept':       'application/json',
                    'X-CSRF-TOKEN': csrfToken,
                },
                credentials: 'same-origin',
            })
            .then(res => {
                if (!res.ok) throw new Error('Search failed: ' + res.status);
                return res.json();
            })
            .then(data => {
                this.searchResults    = data.results ?? {};
                this._flatResults     = this._buildFlatResults(data.results ?? {});
                this.focusedResultIndex = -1;
                this.searchOpen       = true;
            })
            .catch(err => {
                console.error('[Header] Search error:', err);
                this.searchResults = {};
                this.searchOpen    = false;
            })
            .finally(() => {
                this.searchLoading = false;
            });
        },

        closeSearch() {
            this.searchOpen         = false;
            this.searchResults      = {};
            this._flatResults       = [];
            this.focusedResultIndex = -1;
            clearTimeout(this.searchDebounceTimer);
        },

        /** Build a flat array of {url} from grouped results for keyboard nav */
        _buildFlatResults(grouped) {
            const flat = [];
            for (const group of Object.values(grouped)) {
                for (const item of group) {
                    flat.push(item);
                }
            }
            return flat;
        },

        /** Return a flat index for a given group + within-group index */
        getFlatIndex(group, idx) {
            let offset = 0;
            for (const [g, items] of Object.entries(this.searchResults)) {
                if (g === group) return offset + idx;
                offset += items.length;
            }
            return -1;
        },

        navigateResults(direction) {
            if (!this.searchOpen || this._flatResults.length === 0) return;
            const max = this._flatResults.length - 1;
            this.focusedResultIndex = Math.max(0, Math.min(max, this.focusedResultIndex + direction));
        },

        selectFocused() {
            if (this.focusedResultIndex >= 0 && this._flatResults[this.focusedResultIndex]) {
                window.location.href = this._flatResults[this.focusedResultIndex].url;
            }
        },

        // ─────────────────────────────────────────────────────────
        // Notifications
        // ─────────────────────────────────────────────────────────
        fetchNotifications() {
            this.notificationsLoading = true;
            const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content ?? '';

            fetch('{{ route('api.header.notifications') }}', {
                headers: {
                    'Accept':       'application/json',
                    'X-CSRF-TOKEN': csrfToken,
                },
                credentials: 'same-origin',
            })
            .then(res => {
                if (!res.ok) throw new Error('Notifications failed: ' + res.status);
                return res.json();
            })
            .then(data => {
                this.notificationCount = data.unread_count  ?? 0;
                this.notifications     = data.notifications ?? [];
            })
            .catch(err => {
                // Requirement 3.9: retain last known state on failure
                console.error('[Header] Notifications error:', err);
            })
            .finally(() => {
                this.notificationsLoading = false;
            });
        },

        startPolling() {
            // Poll every 30 seconds (Requirement 3.2)
            this.pollingTimer = setInterval(() => this.fetchNotifications(), 30000);
        },

        stopPolling() {
            if (this.pollingTimer) {
                clearInterval(this.pollingTimer);
                this.pollingTimer = null;
            }
        },

        markRead(id) {
            // Optimistic update (Requirement 3.5)
            const n = this.notifications.find(n => n.id === id);
            if (n && !n.is_read) {
                n.is_read = true;
                this.notificationCount = Math.max(0, this.notificationCount - 1);
            }

            const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
            fetch(`/api/header/notifications/${id}/read`, {
                method:  'POST',
                headers: {
                    'Accept':       'application/json',
                    'X-CSRF-TOKEN': csrfToken,
                },
                credentials: 'same-origin',
            })
            .then(res => {
                if (!res.ok) {
                    // Roll back optimistic update on failure
                    if (n) {
                        n.is_read = false;
                        this.notificationCount++;
                    }
                }
            })
            .catch(() => {
                if (n) {
                    n.is_read = false;
                    this.notificationCount++;
                }
            });
        },

        markAllRead() {
            // Optimistic update (Requirement 3.6)
            this.notifications.forEach(n => { n.is_read = true; });
            this.notificationCount = 0;

            const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
            fetch('/api/header/notifications/read-all', {
                method:  'POST',
                headers: {
                    'Accept':       'application/json',
                    'X-CSRF-TOKEN': csrfToken,
                },
                credentials: 'same-origin',
            })
            .catch(err => {
                console.error('[Header] Mark-all-read error:', err);
                // Re-fetch to restore accurate state
                this.fetchNotifications();
            });
        },

        // ─────────────────────────────────────────────────────────
        // Dark mode
        // ─────────────────────────────────────────────────────────
        toggleDarkMode() {
            this.darkMode = !this.darkMode;
            localStorage.setItem('darkMode', this.darkMode);
            document.documentElement.classList.toggle('dark', this.darkMode);
        },
    };
}
</script>
