<template>
  <v-alert
    v-if="store.lastError"
    type="warning" variant="tonal" density="compact" class="mb-3"
  >{{ store.lastError }}</v-alert>

  <MaintenanceTile
    icon="mdi-tag-remove"
    title="Unused tags"
    blurb="Delete tags with no image or series-page references."
    destructive
  >
    <p class="fc-muted text-body-2 mb-3">
      Remove tags with zero image associations and zero series-page
      references. Auto-created tag rows that never got applied get swept here.
    </p>

    <v-btn
      color="accent" variant="flat" rounded="pill"
      prepend-icon="mdi-magnify"
      :loading="loadingPreview"
      class="mb-3"
      @click="onPreview"
    >Preview unused tags</v-btn>

    <div v-if="preview">
      <p class="text-body-2 mb-2">
        <strong>{{ preview.count }}</strong> unused tag(s).
        <span v-if="preview.count > 50" class="fc-muted">Showing first 50 names.</span>
      </p>
      <SampleNameGrid
        v-if="preview.sample_names?.length"
        :names="preview.sample_names" class="mb-3"
      />
      <v-btn
        color="error" variant="flat" rounded="pill"
        prepend-icon="mdi-delete-sweep"
        :disabled="!preview.count"
        :loading="committing"
        @click="onCommit"
      >Delete {{ preview.count }} unused tag(s)</v-btn>
    </div>
  </MaintenanceTile>

  <MaintenanceTile
    icon="mdi-format-letter-case"
    title="Standardize tag casing"
    blurb="Title-case all tags & merge case/space-variant duplicates."
    destructive
  >
    <!-- #714: standardize existing tags to the canonical Title-Case form
         and merge case/whitespace-variant duplicates. -->
    <p class="text-body-2 mb-2">
      New tags are saved Title Case, but older tags keep whatever casing they
      were created with. This renames every existing tag to <code>Title Case</code>
      (collapsing extra spaces) and <strong>merges</strong> tags that differ only
      by case or spacing (e.g. <code>hatsune miku</code> +
      <code>Hatsune&nbsp;&nbsp;Miku</code>) into one — repointing their images,
      allowlist entries and series pages.
    </p>
    <v-alert type="warning" variant="tonal" density="compact" class="mb-3">
      The merges are irreversible — back up first
      (Settings → Maintenance → Backup). Safe to run more than once.
    </v-alert>

    <v-btn
      color="accent" variant="flat" rounded="pill"
      prepend-icon="mdi-magnify"
      :loading="loadingNormPreview"
      class="mb-3"
      @click="onNormPreview"
    >Preview tag standardization</v-btn>

    <div v-if="normPreview">
      <p class="text-body-2 mb-2">
        <strong>{{ normPreview.total_changes }}</strong> tag group(s) to
        change — <strong>{{ normPreview.tags_to_rename }}</strong> rename(s),
        <strong>{{ normPreview.collisions }}</strong> collision(s) merging
        <strong>{{ normPreview.tags_to_merge }}</strong> tag(s) away.
      </p>
      <SampleNameGrid v-if="normPreview.sample?.length" class="mb-3">
        <span
          v-for="s in normPreview.sample" :key="s.to + s.kind"
          class="fc-name"
        >
          <template v-if="s.merge">{{ s.from.join(' + ') }} → </template>{{ s.to }}
        </span>
      </SampleNameGrid>
      <v-btn
        color="error" variant="flat" rounded="pill"
        prepend-icon="mdi-format-letter-case"
        :disabled="!normPreview.total_changes || !!normResult"
        :loading="normCommitting"
        @click="onNormCommit"
      >Standardize {{ normPreview.total_changes }} tag group(s)</v-btn>
      <span v-if="normResult" class="ml-3 text-caption text-success">
        Queued ✓ — runs in the background (you can leave this page). It
        processes in chunks, so re-run “Preview” later to confirm it's all done.
      </span>
    </div>
  </MaintenanceTile>
</template>

<script setup>
import { useAdminStore } from '../../stores/admin.js'
import { usePreviewCommit } from '../../composables/usePreviewCommit.js'
import SampleNameGrid from '../common/SampleNameGrid.vue'
import MaintenanceTile from '../common/MaintenanceTile.vue'

const store = useAdminStore()

// Unused-tag prune. Collapse to count 0 but carry the apply's sample_names.
const {
  previewData: preview, previewing: loadingPreview, committing,
  runPreview: onPreview, runCommit: onCommit,
} = usePreviewCommit({
  preview: () => store.pruneUnusedTags({ dryRun: true }),
  commit: () => store.pruneUnusedTags({ dryRun: false }),
  emptyPreview: (r) => ({ count: 0, sample_names: r.sample_names || [] }),
})

// Standardize casing. The apply DISPATCHES a self-resuming background task (no
// poll-until-done — that would falsely report complete after the first chunk),
// so there's no emptyPreview: leave the projection up; a truthy normResult means
// "queued". The operator re-runs Preview later to confirm it's all done.
const {
  previewData: normPreview, previewing: loadingNormPreview,
  committing: normCommitting, result: normResult,
  runPreview: onNormPreview, runCommit: onNormCommit,
} = usePreviewCommit({
  preview: () => store.normalizeTags({ dryRun: true }),
  commit: () => store.normalizeTags({ dryRun: false }),
})
</script>
