<template>
  <MaintenanceTile
    icon="mdi-post-outline"
    title="Bare posts"
    blurb="Delete empty post shells with no images or attachments."
    destructive
  >
    <p class="fc-muted text-body-2 mb-3">
      Post rows with no images (neither their own nor a cross-posted duplicate)
      and no attachments — the empty “Post 12345 / (no description)” shells a
      backfill can leave when a post's only content was a duplicate that links to
      an earlier post. Posts that gained a duplicate-image link are spared.
    </p>

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

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

    <div v-if="preview">
      <p class="text-body-2 mb-2">
        <strong>{{ preview.count }}</strong> bare post(s).
        <span v-if="preview.count > 50" class="fc-muted">Showing first 50.</span>
        <span v-else-if="!preview.count" class="fc-muted">Nothing to clean up.</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 }} bare post(s)</v-btn>
      <span v-if="deleted != null" class="ml-3 text-caption text-success">
        Deleted {{ deleted }} ✓
      </span>
    </div>
  </MaintenanceTile>

  <MaintenanceTile
    icon="mdi-merge"
    title="Duplicate posts"
    blurb="Merge gallery-dl + native duplicate post records into one."
    destructive
  >
    <p class="fc-muted text-body-2 mb-3">
      When an artist was first downloaded by gallery-dl and later re-walked by the
      native ingester, the same post can exist twice (once keyed by the file's
      attachment id, once by the real post id). This merges each pair onto one
      canonical post (keeping the native post-id key), moving images, attachments
      and links onto the survivor. Images themselves are never touched.
    </p>

    <v-btn
      color="accent" variant="flat" rounded="pill"
      prepend-icon="mdi-magnify"
      :loading="loadingDupPreview"
      class="mb-3"
      @click="onPreviewDupes"
    >Preview duplicate posts</v-btn>

    <div v-if="dupPreview">
      <p class="text-body-2 mb-2">
        <strong>{{ dupPreview.groups }}</strong> duplicate group(s),
        <strong>{{ dupPreview.posts_to_merge }}</strong> redundant row(s) to merge.
        <span v-if="dupPreview.groups > 50" class="fc-muted">Showing first 50.</span>
        <span v-else-if="!dupPreview.groups" class="fc-muted">No duplicates found.</span>
      </p>
      <SampleNameGrid
        v-if="dupSampleNames.length"
        :names="dupSampleNames" class="mb-3"
      />
      <v-btn
        color="error" variant="flat" rounded="pill"
        prepend-icon="mdi-merge"
        :disabled="!dupPreview.groups"
        :loading="merging"
        @click="onMergeDupes"
      >Merge {{ dupPreview.posts_to_merge }} duplicate(s)</v-btn>
      <span v-if="merged != null" class="ml-3 text-caption text-success">
        Merged {{ merged }} ✓
      </span>
    </div>
  </MaintenanceTile>
</template>

<script setup>
import { computed, ref } from 'vue'

import { useAdminStore } from '../../stores/admin.js'
import SampleNameGrid from '../common/SampleNameGrid.vue'
import MaintenanceTile from '../common/MaintenanceTile.vue'

const store = useAdminStore()
const preview = ref(null)
const loadingPreview = ref(false)
const committing = ref(false)
const deleted = ref(null)

const dupPreview = ref(null)
const loadingDupPreview = ref(false)
const merging = ref(false)
const merged = ref(null)
const dupSampleNames = computed(() =>
  (dupPreview.value?.sample ?? []).map(
    (g) => `${g.title} — ${g.rows} rows`,
  ),
)

async function onPreview() {
  loadingPreview.value = true
  deleted.value = null
  try {
    preview.value = await store.pruneBarePosts({ dryRun: true })
  } finally {
    loadingPreview.value = false
  }
}

async function onCommit() {
  committing.value = true
  try {
    const result = await store.pruneBarePosts({ dryRun: false })
    deleted.value = result.deleted ?? 0
    // Reflect the completed sweep — the predicate is identical to the preview,
    // so after a commit there is nothing left to delete.
    preview.value = { count: 0, sample_names: [] }
  } finally {
    committing.value = false
  }
}

async function onPreviewDupes() {
  loadingDupPreview.value = true
  merged.value = null
  try {
    dupPreview.value = await store.reconcileDuplicatePosts({ dryRun: true })
  } finally {
    loadingDupPreview.value = false
  }
}

async function onMergeDupes() {
  merging.value = true
  try {
    const result = await store.reconcileDuplicatePosts({ dryRun: false })
    merged.value = result.merged ?? 0
    // Same predicate as the preview — after the merge there are no dup groups left.
    dupPreview.value = { groups: 0, posts_to_merge: 0, sample: [] }
  } finally {
    merging.value = false
  }
}
</script>
