<template>
  <!-- System-tag auto-applies (chrome hides / process WIP tags) that ALSO looked
       like real content — surfaced PROACTIVELY atop the gallery whenever there's
       something to review (NOT gated on the Show-hidden toggle, so misfires can't
       go unnoticed), most-concerning first, with keep / remove (#141, #1464).
       Renders nothing when there's nothing to review. -->
  <section v-if="items.length" class="fc-review" aria-label="Auto-tagged images to review">
    <div class="fc-review__head">
      <v-icon size="18" color="warning">mdi-alert-outline</v-icon>
      <span class="fc-review__title">
        {{ items.length }} auto-tagged {{ items.length === 1 ? 'image' : 'images' }}
        may be real content — review
      </span>
    </div>
    <div class="fc-review__cards">
      <div
        v-for="it in items" :key="keyOf(it)" class="fc-review-card"
      >
        <img
          :src="it.thumbnail_url" :alt="it.tag_name"
          class="fc-review-card__thumb" loading="lazy"
        >
        <div class="fc-review-card__body">
          <div
            class="fc-review-card__conflict"
            :title="`Scored ${Math.round(it.conflict_score * 100)}% on “${it.conflict_name || 'a content tag'}”`"
          >
            also looks like <strong>{{ it.conflict_name || 'content' }}</strong>
          </div>
          <div class="fc-review-card__tag">{{ tagLine(it) }}</div>
          <div class="fc-review-card__acts">
            <button
              type="button" class="fc-review-btn fc-review-btn--keep"
              :disabled="busy.includes(keyOf(it))" @click="resolve(it, 'keep')"
            >{{ keepLabel(it) }}</button>
            <button
              type="button" class="fc-review-btn fc-review-btn--unhide"
              :disabled="busy.includes(keyOf(it))" @click="resolve(it, 'unhide')"
            >{{ removeLabel(it) }}</button>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import { useApi } from '../../composables/useApi.js'
import { toast } from '../../utils/toast.js'

const api = useApi()

const items = ref([])
const busy = ref([])

function keyOf(it) { return `${it.image_id}:${it.tag_id}` }
// Chrome flags hide the image (keep-hidden / un-hide); process flags leave it
// visible and just tagged (keep-tag / remove-tag). Same endpoints, different words.
function tagLine(it) { return (it.mode === 'process' ? 'auto-tagged ' : 'hidden as ') + it.tag_name }
function keepLabel(it) { return it.mode === 'process' ? 'Keep tag' : 'Keep hidden' }
function removeLabel(it) { return it.mode === 'process' ? 'Remove tag' : 'Un-hide' }

async function load() {
  // Fetched unconditionally on mount — the strip prompts for pending misfires
  // even when the operator is browsing normally (Show-hidden off).
  try {
    const body = await api.get('/api/gallery/hidden-review')
    items.value = body.items || []
  } catch { items.value = [] }
}

async function resolve(it, action) {
  const k = keyOf(it)
  busy.value = [...busy.value, k]
  try {
    await api.post(`/api/gallery/hidden-review/${it.image_id}/${it.tag_id}/${action}`)
    items.value = items.value.filter((x) => keyOf(x) !== k)
    if (action === 'unhide') {
      const verb = it.mode === 'process' ? 'Removed' : 'Un-hidden'
      toast({ text: `${verb} — “${it.tag_name}” removed; it'll train the head`, type: 'success' })
    }
  } catch (e) {
    toast({
      text: `Could not ${action === 'keep' ? 'keep hidden' : 'un-hide'}: ${e.message}`,
      type: 'error',
    })
  } finally {
    busy.value = busy.value.filter((x) => x !== k)
  }
}

onMounted(load)
</script>

<style scoped>
.fc-review {
  margin-bottom: 14px;
  padding: 12px;
  border: 1px solid rgb(var(--v-theme-warning), 0.4);
  background: rgb(var(--v-theme-warning), 0.06);
  border-radius: 8px;
}
.fc-review__head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
}
.fc-review__title {
  font-size: 14px; font-weight: 600;
  color: rgb(var(--v-theme-on-surface));
}
.fc-review__cards {
  display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px;
}
.fc-review-card {
  flex: 0 0 auto; width: 150px;
  display: flex; flex-direction: column;
  border: 1px solid rgb(var(--v-theme-surface-light));
  border-radius: 6px; overflow: hidden;
  background: rgb(var(--v-theme-surface));
}
.fc-review-card__thumb {
  width: 100%; height: 96px; object-fit: cover; display: block;
  background: rgb(var(--v-theme-surface-light));
}
.fc-review-card__body { padding: 6px 8px; }
.fc-review-card__conflict {
  font-size: 11px; color: rgb(var(--v-theme-on-surface));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fc-review-card__conflict strong { color: rgb(var(--v-theme-warning)); }
.fc-review-card__tag {
  font-size: 10px; color: rgb(var(--v-theme-on-surface-variant));
  margin: 1px 0 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fc-review-card__acts { display: flex; gap: 4px; }
.fc-review-btn {
  flex: 1; font-size: 11px; padding: 3px 4px; border-radius: 4px;
  cursor: pointer; border: 1px solid transparent;
}
.fc-review-btn:disabled { opacity: 0.5; cursor: default; }
.fc-review-btn--keep {
  background: transparent;
  color: rgb(var(--v-theme-on-surface-variant));
  border-color: rgb(var(--v-theme-on-surface-variant), 0.4);
}
.fc-review-btn--keep:hover:not(:disabled) {
  background: rgb(var(--v-theme-on-surface-variant), 0.1);
}
.fc-review-btn--unhide {
  background: rgb(var(--v-theme-accent)); color: #fff;
}
.fc-review-btn--unhide:hover:not(:disabled) { opacity: 0.9; }
.fc-review-btn:focus-visible {
  outline: 2px solid rgb(var(--v-theme-accent)); outline-offset: 1px;
}
</style>
