<template>
  <MaintenanceTile
    icon="mdi-checkerboard"
    title="Transparency audit"
    blurb="Find & delete images that are mostly transparent."
    destructive
    :open="audit?.status === 'running'"
  >
    <p class="fc-muted text-body-2 mb-3">
      Scan library for images whose transparent-pixel fraction exceeds
      the threshold. Animated WebPs / GIFs are skipped (the import-side
      rule does the same). Runs as a background task — ~50ms per image,
      so a 57k library takes ~50 minutes.
    </p>

    <v-text-field
      v-model.number="threshold" label="Transparency threshold (0–1)"
      type="number" min="0" max="1" step="0.01" density="compact" hide-details
      :disabled="audit && audit.status === 'running'"
      class="mb-3"
    />

    <v-btn
      v-if="!audit || audit.status !== 'running'"
      color="accent" variant="flat" rounded="pill"
      prepend-icon="mdi-magnify-scan"
      :loading="busy"
      @click="onStart"
    >Scan library</v-btn>

    <div v-if="audit && audit.status === 'running'" class="mt-3">
      <v-progress-linear indeterminate color="accent" />
      <div class="text-body-2 mt-2 d-flex align-center" style="gap: 10px;">
        <span>
          Scanning… {{ audit.scanned_count }} checked,
          {{ audit.matched_count }} matched
        </span>
        <v-btn
          variant="text" size="small" color="warning" rounded="pill"
          @click="onCancel"
        >Cancel</v-btn>
      </div>
    </div>

    <div v-if="audit && audit.status === 'ready'" class="mt-3">
      <p class="text-body-2 mb-2">
        Scan complete. <strong>{{ audit.matched_count }}</strong>
        image(s) match.
      </p>
      <v-btn
        v-if="audit.matched_count > 0"
        color="error" variant="flat" rounded="pill"
        prepend-icon="mdi-delete"
        @click="onApplyClick"
      >Delete {{ audit.matched_count }} matching...</v-btn>
    </div>

    <v-alert
      v-if="audit && audit.status === 'error'"
      type="error" variant="tonal" density="compact" class="mt-3"
    >Scan failed: {{ audit.error }}</v-alert>

    <v-alert
      v-if="audit && audit.status === 'applied'"
      type="success" variant="tonal" density="compact" class="mt-3"
    >Applied — matched images deleted.</v-alert>

    <DestructiveConfirmModal
      v-if="audit"
      v-model="showModal"
      action="delete"
      kind="audit"
      :run-id="audit.id"
      tier="C"
      :projected-counts="projectedCounts"
      description="Permanently deletes images matched by the transparency scan."
      @confirm="onConfirmedApply"
    />
  </MaintenanceTile>
</template>

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

import DestructiveConfirmModal from '../modal/DestructiveConfirmModal.vue'
import MaintenanceTile from '../common/MaintenanceTile.vue'
import { useCleanupStore } from '../../stores/cleanup.js'

const store = useCleanupStore()
const threshold = ref(0.9)
const audit = ref(null)
const busy = ref(false)
const showModal = ref(false)
const projectedCounts = ref({})
let pollTimer = null

onMounted(async () => {
  await store.loadDefaults()
  threshold.value = store.defaults.transparency_threshold
  // Reconnect to this rule's latest run so a scan started before navigating
  // away keeps showing progress / its result on return (the scan itself runs
  // backend-side regardless).
  try {
    const latest = await store.latestAuditForRule('transparency')
    if (latest) {
      audit.value = latest
      if (latest.status === 'running') startPoll(latest.id)
    }
  } catch { /* non-fatal — card still works for a fresh scan */ }
})

onUnmounted(() => stopPoll())

function startPoll(id) {
  stopPoll()
  pollTimer = setInterval(async () => {
    try {
      const fresh = await store.getAudit(id)
      audit.value = fresh
      if (fresh.status !== 'running') stopPoll()
    } catch (e) {
      stopPoll()
      toast({ text: `Audit poll failed: ${e.message}`, type: 'error' })
    }
  }, 5000)
}

function stopPoll() {
  if (pollTimer) { clearInterval(pollTimer); pollTimer = null }
}

async function onStart() {
  busy.value = true
  try {
    const res = await store.startAudit('transparency', { threshold: threshold.value })
    audit.value = await store.getAudit(res.audit_id)
    startPoll(res.audit_id)
  } catch (e) {
    toast({ text: `Scan start failed: ${e.message}`, type: 'error' })
  } finally {
    busy.value = false
  }
}

async function onCancel() {
  if (!audit.value) return
  try {
    await store.cancelAudit(audit.value.id)
    audit.value = await store.getAudit(audit.value.id)
    stopPoll()
  } catch (e) {
    toast({ text: `Cancel failed: ${e.message}`, type: 'error' })
  }
}

function onApplyClick() {
  projectedCounts.value = { 'Images to delete': audit.value.matched_count }
  showModal.value = true
}

async function onConfirmedApply(token) {
  try {
    const res = await store.applyAudit(audit.value.id, token)
    toast({
      text: `Deleted ${res.deleted} image(s)`, type: 'success',
    })
    audit.value = await store.getAudit(audit.value.id)
  } catch (e) {
    toast({ text: `Apply failed: ${e.message}`, type: 'error' })
  }
}
</script>
