<template>
  <div class="fc-browse">
    <!-- Sticky browse chrome: the tab strip + a per-tab search bar, both pinned
         directly under the 64px TopNav (AppShell). Operator-asked 2026-06-11:
         the tab nav scrolled away (they didn't know it existed), and there was
         no search on Posts. Tabs + search live in ONE sticky block so the axis
         switcher and the search stay reachable no matter how far you scroll.
         Background uses the theme surface token so content scrolls cleanly
         under it (matches SettingsView's sticky tabs). -->
    <div class="fc-browse__head fc-chrome-continues">
      <v-container fluid class="py-0">
        <!-- Tabs and search share one row: the axis switcher on the left, the
             search field + active-scope chips on the right (operator-asked
             2026-06-12). Wraps to two rows only on narrow viewports. -->
        <div class="fc-browse__bar">
          <v-tabs
            v-model="tab" density="compact" color="accent"
            class="fc-browse__tabs"
          >
            <v-tab value="posts">Posts</v-tab>
            <v-tab value="artists">Artists</v-tab>
            <v-tab value="tags">Tags</v-tab>
          </v-tabs>

          <div class="fc-browse__search">
            <v-text-field
              v-model="searchInput"
              density="compact" variant="outlined" hide-details clearable
              prepend-inner-icon="mdi-magnify"
              :placeholder="searchPlaceholder"
              :aria-label="searchPlaceholder"
              class="fc-browse__search-field"
            />
            <!-- Posts search stays scoped to the active artist/platform filter
                 (operator-asked: 'if an artist is currently filtered in view').
                 The chips surface that scope next to the search even after the
                 PostsFilterBar scrolls off, and clear it to broaden. -->
            <template v-if="tab === 'posts'">
              <v-chip
                v-if="artistId != null" closable size="small"
                variant="tonal" color="accent" prepend-icon="mdi-account"
                @click:close="clearFilter('artist_id')"
              >{{ artistChipLabel }}</v-chip>
              <v-chip
                v-if="platform" closable size="small"
                variant="tonal" color="accent" prepend-icon="mdi-web"
                @click:close="clearFilter('platform')"
              >{{ platform }}</v-chip>
            </template>
          </div>
        </div>
      </v-container>
    </div>

    <!-- Each tab's view is self-contained (its own container + state). Only the
         active one is mounted; switching tabs swaps it. The Posts tab still
         reads its deep-link (post_id/artist_id/platform) from route.query, so
         /browse?tab=posts&post_id=N works exactly like the old /posts deep link.
         All three tabs read the shared `q` search term from route.query.
         (FC nav consolidation, operator-asked 2026-06-09: Posts/Artists/Tags are
         the three "browse the library by an axis" surfaces.) -->
    <component :is="activeComponent" :key="tab" />
  </div>
</template>

<script setup>
import { computed, nextTick, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { usePostsStore } from '../stores/posts.js'
import ArtistsView from './ArtistsView.vue'
import PostsView from './PostsView.vue'
import TagsView from './TagsView.vue'

const TABS = { posts: PostsView, artists: ArtistsView, tags: TagsView }
const PLACEHOLDERS = {
  posts: 'Search posts (title, description)',
  artists: 'Search artists',
  tags: 'Search tags',
}

const route = useRoute()
const router = useRouter()
const postsStore = usePostsStore()

const tab = computed({
  get() {
    const t = route.query.tab
    return typeof t === 'string' && t in TABS ? t : 'posts'
  },
  set(value) {
    // Switching tabs starts a clean tab — a posts deep link (post_id, etc.)
    // and the search term belong only to the tab they were typed in and
    // shouldn't bleed into Artists/Tags.
    router.replace({ name: 'browse', query: { tab: value } })
  },
})

const activeComponent = computed(() => TABS[tab.value])
const searchPlaceholder = computed(() => PLACEHOLDERS[tab.value])

// --- search term <-> route.query.q (debounced; deep-linkable) ---------------
// One sticky field drives every tab. The term lives in the URL (q=) so it's
// shareable and survives reload; each tab view watches route.query.q and
// re-queries the server (so the search surfaces content not yet scrolled into
// view, not just a client-side filter of loaded rows).
const searchInput = ref(typeof route.query.q === 'string' ? route.query.q : '')
let debounceTimer = null
let syncingFromRoute = false

watch(searchInput, (v) => {
  if (syncingFromRoute) return
  if (debounceTimer) clearTimeout(debounceTimer)
  debounceTimer = setTimeout(() => {
    const next = (v || '').trim()
    const query = { ...route.query }
    if (next) query.q = next
    else delete query.q
    router.replace({ name: 'browse', query })
  }, 300)
})

// Keep the field in sync when q changes from elsewhere (tab switch clears it,
// browser back/forward, a deep link). Guarded so it doesn't re-trigger a route
// write.
watch(() => route.query.q, (q) => {
  const val = typeof q === 'string' ? q : ''
  if (val === searchInput.value) return
  syncingFromRoute = true
  searchInput.value = val
  nextTick(() => { syncingFromRoute = false })
})

// --- active-scope chips (Posts) ---------------------------------------------
const artistId = computed(() => {
  const raw = route.query.artist_id
  return raw == null ? null : Number(raw)
})
const platform = computed(() => route.query.platform || null)
// Resolve the artist's name from whatever the posts feed has loaded for this
// scope; fall back to a generic label when the search returns nothing.
const artistChipLabel = computed(() => {
  const hit = postsStore.items.find((p) => p.artist?.id === artistId.value)
  return hit?.artist?.name || 'Artist'
})

function clearFilter(key) {
  const query = { ...route.query }
  delete query[key]
  router.replace({ name: 'browse', query })
}
</script>

<style scoped>
.fc-browse__head {
  position: sticky;
  top: var(--fc-nav-h, 64px); /* pins at the nav's real measured bottom (#1481) */
  z-index: 4;
  /* Background is the shared .fc-chrome-continues fade — it continues the nav's
     gradient instead of a solid surface band (operator 2026-07-13). */
}
.fc-browse__bar {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding: 8px 0;
}
.fc-browse__tabs {
  flex: 0 0 auto;
  width: auto;
}
.fc-browse__search {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  flex: 1 1 320px;
}
.fc-browse__search-field {
  max-width: 360px;
  flex: 1 1 240px;
}
</style>
