<template>
  <aside class="fc-tag-panel" aria-label="Tags for this image">
    <h3 class="fc-tag-panel__title">Tags</h3>
    <div class="fc-tag-panel__chips">
      <TagChip
        v-for="tag in modal.current?.tags || []"
        :key="tag.id" :tag="tag"
        @remove="onRemove" @rename="openRename" @set-fandom="openSetFandom"
      />
      <span v-if="!modal.current?.tags?.length" class="text-caption">No tags yet.</span>
    </div>

    <v-divider class="my-3" />

    <TagAutocomplete
      ref="tagInputRef"
      @pick-existing="onPickExisting" @pick-new="onPickNew"
      @accept-suggestion="onAcceptSuggestion"
    />

    <v-alert v-if="errorMsg" type="error" variant="tonal" class="mt-2" closable>
      {{ errorMsg }}
    </v-alert>

    <SuggestionsPanel
      v-if="modal.currentImageId != null"
      :image-id="modal.currentImageId"
      @accepted="focusTagInput"
    />

    <v-dialog v-model="renameDialog" max-width="420">
      <TagRenameDialog
        v-if="renameTarget"
        :tag="renameTarget"
        @renamed="onRenamed" @cancel="renameDialog = false"
      />
    </v-dialog>

    <v-dialog
      v-model="fandomDialog" max-width="460"
      @after-enter="fandomSetRef?.focusSearch?.()"
    >
      <FandomSetDialog
        ref="fandomSetRef"
        v-if="fandomTarget" :tag="fandomTarget"
        @updated="onFandomUpdated" @cancel="fandomDialog = false"
      />
    </v-dialog>
  </aside>
</template>

<script setup>
import { ref } from 'vue'
import { useModalStore } from '../../stores/modal.js'
import { useSuggestionsStore } from '../../stores/suggestions.js'
import TagChip from './TagChip.vue'
import TagAutocomplete from './TagAutocomplete.vue'
import SuggestionsPanel from './SuggestionsPanel.vue'
import TagRenameDialog from './TagRenameDialog.vue'
import FandomSetDialog from './FandomSetDialog.vue'

const modal = useModalStore()
const suggestions = useSuggestionsStore()
const errorMsg = ref(null)
const tagInputRef = ref(null)

// Return focus to the tag input after a suggestion is accepted (from the
// Suggestions panel or the autocomplete dropdown) so the operator can keep
// typing the next tag without re-clicking the field (operator-asked 2026-06-08).
function focusTagInput() { tagInputRef.value?.focus?.() }

async function onRemove(tagId) {
  errorMsg.value = null
  try { await modal.removeTag(tagId) }
  catch (e) { errorMsg.value = e.message }
}
async function onPickExisting(hit) {
  errorMsg.value = null
  try { await modal.addExistingTag(hit.id) }
  catch (e) { errorMsg.value = e.message }
}
async function onPickNew(payload) {
  errorMsg.value = null
  try { await modal.createAndAdd(payload) }
  catch (e) { errorMsg.value = e.message }
}
// A suggestion picked from the autocomplete dropdown runs the SAME path as the
// Suggestions panel's Accept: the store creates the tag if it's raw, records the
// acceptance, and drops it from the panel; then we refresh the chip rail.
async function onAcceptSuggestion(s) {
  errorMsg.value = null
  try {
    await suggestions.accept(s)
    await modal.reloadTags()
    focusTagInput()
  } catch (e) { errorMsg.value = e.message }
}

const renameDialog = ref(false)
const renameTarget = ref(null)

function openRename(tag) {
  renameTarget.value = tag
  renameDialog.value = true
}
async function onRenamed() {
  renameDialog.value = false
  // Reflect the new name in the modal's current tag list without a full reload.
  await modal.reloadTags()
}

const fandomDialog = ref(false)
const fandomTarget = ref(null)
const fandomSetRef = ref(null)
function openSetFandom(tag) {
  fandomTarget.value = tag
  fandomDialog.value = true
}
async function onFandomUpdated() {
  fandomDialog.value = false
  // A fandom change can merge the tag away; reload to reflect the new state.
  await modal.reloadTags()
}
</script>

<style scoped>
.fc-tag-panel {
  padding: 16px;
}
.fc-tag-panel__title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 18px;
  font-weight: 500;
  color: rgb(var(--v-theme-on-surface));
  margin-bottom: 12px;
}
.fc-tag-panel__chips { display: flex; flex-wrap: wrap; gap: 6px; }
</style>
