<template>
  <span class="fc-tag-chip" @mouseenter="onEnter" @mouseleave="onLeave">
    <v-chip
      size="small" closable
      :color="store.colorFor(tag.kind)" variant="tonal"
      class="fc-tag-chip__nav"
      role="link"
      :title="`Browse images tagged “${tag.name}”`"
      @click="$emit('navigate', tag)"
      @click:close="$emit('remove', tag.id)"
    >
      <v-icon start size="x-small">{{ iconFor(tag.kind) }}</v-icon>
      {{ tag.name }}<v-icon
        v-if="tag.is_system" end size="x-small" class="fc-tag-chip__system"
        title="System tag — tagged items are excluded from training other concepts"
      >mdi-shield-outline</v-icon><span
        v-if="tag.fandom_id" class="fc-tag-chip__fandom"
        :title="tag.fandom_name ? `Fandom: ${tag.fandom_name}` : 'Has a fandom'"
      >→<template v-if="fandomLabel">&nbsp;{{ fandomLabel }}</template></span>
    </v-chip>
    <!-- Modal-safe kebab is baked into KebabMenu (this chip lives in the
         teleported image modal — #711). System tags hide it entirely: rename
         is refused server-side (the hygiene machinery keys on the row) and
         set-fandom never applies to their general kind. Remove (✕) stays —
         un-tagging an image is normal use. -->
    <KebabMenu
      v-if="!tag.is_system"
      class="fc-tag-chip__kebab" :label="`More actions for ${tag.name}`"
    >
      <v-list-item @click="$emit('rename', tag)">
        <v-list-item-title>Rename…</v-list-item-title>
      </v-list-item>
      <v-list-item v-if="tag.kind === 'character'" @click="$emit('set-fandom', tag)">
        <v-list-item-title>Set fandom…</v-list-item-title>
      </v-list-item>
    </KebabMenu>
  </span>
</template>

<script setup>
import { computed, inject } from 'vue'
import { useTagStore } from '../../stores/tags.js'
import { useApi } from '../../composables/useApi.js'
import KebabMenu from '../common/KebabMenu.vue'

const props = defineProps({
  tag: { type: Object, required: true },
  // When set (the tagging panels), hovering the chip asks the backend which crop
  // region best explains this applied tag and lights it up on the image — the
  // same overlay the suggestion rail uses (#1206 Step 4). Omitted elsewhere →
  // the hover is inert (no injected target, or no image to ground against).
  imageId: { type: Number, default: null },
})
defineEmits(['remove', 'rename', 'set-fandom', 'navigate'])

const store = useTagStore()
const api = useApi()

// #1206 Step 4: applied-tag grounding. `fcSuggestionHover` is provided by the
// image viewer / Explore host (a no-op elsewhere). Applied tags aren't scored
// live, so we fetch the winning region on demand and cache it per (image, tag).
const hover = inject('fcSuggestionHover', null)
const _groundingCache = new Map()
// Bumped on every enter/leave so a slow fetch that resolves after the pointer
// has moved on can't draw a stale overlay.
let hoverSeq = 0

async function onEnter () {
  if (!hover || props.imageId == null) return
  const seq = ++hoverSeq
  const key = `${props.imageId}:${props.tag.id}`
  let res = _groundingCache.get(key)
  if (res === undefined) {
    try {
      res = await api.get(
        `/api/images/${props.imageId}/tags/${props.tag.id}/grounding`
      )
      _groundingCache.set(key, res)
    } catch {
      return   // best-effort — leave the overlay untouched on error
    }
  }
  if (seq !== hoverSeq) return   // pointer already left / moved to another chip
  // No head → nothing to localize; don't draw an overlay at all. With a head,
  // null grounding still draws the whole-image frame ("the global vector won").
  if (res.has_head) hover.value = { g: res.grounding ?? null, tag: props.tag.name }
}
function onLeave () {
  hoverSeq++
  if (hover) hover.value = null
}

// Show a character's fandom inline (truncated). Falls back to a bare arrow when
// only fandom_id is known but the name wasn't resolved (older payloads).
const FANDOM_MAX = 15
const fandomLabel = computed(() => {
  const n = props.tag.fandom_name
  if (!n) return ''
  return n.length > FANDOM_MAX ? `${n.slice(0, FANDOM_MAX)}…` : n
})

const KIND_ICONS = {
  general: 'mdi-tag', character: 'mdi-account-circle',
  fandom: 'mdi-book-open-page-variant', series: 'mdi-bookshelf',
  meta: 'mdi-cog-outline', rating: 'mdi-shield-check-outline',
}
function iconFor (k) { return KIND_ICONS[k] || 'mdi-tag' }
</script>

<style scoped>
.fc-tag-chip { display: inline-flex; align-items: center; gap: 1px; }
/* The chip body navigates to the filtered gallery (#5); signal it's clickable.
   The close ✕ (remove) and the sibling kebab stay as the explicit controls. */
.fc-tag-chip__nav { cursor: pointer; }
.fc-tag-chip__nav:focus-visible {
  outline: 2px solid rgb(var(--v-theme-accent));
  outline-offset: 1px;
}
.fc-tag-chip__system { opacity: 0.6; margin-left: 2px; }
.fc-tag-chip__kebab { opacity: 0.7; }
.fc-tag-chip:hover .fc-tag-chip__kebab { opacity: 1; }
.fc-tag-chip__fandom { opacity: 0.7; font-size: 0.85em; }
</style>
