<template>
  <v-card class="fc-backup-card">
    <v-card-title class="d-flex align-center" style="gap: 10px;">
      <v-icon icon="mdi-database-export" size="small" />
      <span>Backups</span>
    </v-card-title>
    <v-card-text>
      <p class="fc-muted text-body-2 mb-4">
        pg_dump for the database (fast, nightly-schedulable);
        tar+zstd for the images (slow, manual only). Files live in
        <code>/images/_backups/</code>. Tag a backup to protect it
        from autoprune.
      </p>

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

      <!-- Database section -->
      <h3 class="fc-section-title">Database</h3>
      <div class="fc-settings-row mb-3">
        <v-switch
          :model-value="settings.backup_db_nightly_enabled"
          color="accent" density="compact" hide-details
          label="Nightly"
          @update:model-value="onSettingChange('backup_db_nightly_enabled', $event)"
        />
        <v-text-field
          :model-value="settings.backup_db_nightly_hour_utc"
          label="Hour (UTC)" type="number" min="0" max="23"
          density="compact" hide-details style="max-width: 110px;"
          @update:model-value="onSettingChange('backup_db_nightly_hour_utc', Number($event))"
        />
        <v-text-field
          :model-value="settings.backup_db_keep_last_n"
          label="Keep last" type="number" min="1" max="365"
          density="compact" hide-details style="max-width: 110px;"
          @update:model-value="onSettingChange('backup_db_keep_last_n', Number($event))"
        />
      </div>
      <v-btn
        color="accent" variant="flat" rounded="pill"
        prepend-icon="mdi-database-arrow-up" class="mb-3"
        :loading="dbTriggering"
        @click="onTrigger('db')"
      >Run DB backup now</v-btn>

      <BackupRunsTable
        :runs="store.dbRuns"
        @restore="onRestore"
        @delete="onDelete"
        @tag="onTag"
      />

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

      <!-- Images section -->
      <h3 class="fc-section-title">Images</h3>
      <div class="fc-settings-row mb-3">
        <v-text-field
          :model-value="settings.backup_images_keep_last_n"
          label="Keep last" type="number" min="1" max="100"
          density="compact" hide-details style="max-width: 110px;"
          @update:model-value="onSettingChange('backup_images_keep_last_n', Number($event))"
        />
      </div>
      <v-btn
        color="accent" variant="flat" rounded="pill"
        prepend-icon="mdi-folder-zip" class="mb-3"
        :loading="imagesTriggering"
        @click="onTrigger('images')"
      >Run images backup now</v-btn>
      <span class="text-caption fc-muted ml-2">
        ⓘ Hours for a 200GB+ library.
      </span>

      <BackupRunsTable
        :runs="store.imagesRuns"
        @restore="onRestore"
        @delete="onDelete"
        @tag="onTag"
      />
    </v-card-text>

    <BackupConfirmModal
      v-model="confirmOpen"
      :action="confirmAction"
      :kind="confirmKind"
      :run-id="confirmRunId"
      :description="confirmDescription"
      @confirm="onConfirmSubmit"
    />
  </v-card>
</template>

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

import { useBackupStore } from '../../stores/backup.js'
import BackupConfirmModal from '../modal/DestructiveConfirmModal.vue'
import BackupRunsTable from './BackupRunsTable.vue'

const store = useBackupStore()

const settings = computed(() => store.settings || {
  backup_db_nightly_enabled: false,
  backup_db_nightly_hour_utc: 3,
  backup_db_keep_last_n: 14,
  backup_images_keep_last_n: 3,
})

const dbTriggering = ref(false)
const imagesTriggering = ref(false)
const confirmOpen = ref(false)
const confirmAction = ref('restore')
const confirmKind = ref('db')
const confirmRunId = ref(0)
const confirmDescription = ref('')

let pollId = null
function pollOnce() {
  if (document.hidden) return
  store.loadRuns('db')
  store.loadRuns('images')
}

onMounted(() => {
  store.loadSettings()
  pollOnce()
  pollId = setInterval(pollOnce, 5000)
})
onUnmounted(() => {
  if (pollId) { clearInterval(pollId); pollId = null }
})

async function onTrigger(kind) {
  const triggeringRef = kind === 'db' ? dbTriggering : imagesTriggering
  triggeringRef.value = true
  try {
    await store.triggerBackup(kind)
    pollOnce()
  } finally {
    triggeringRef.value = false
  }
}

async function onSettingChange(field, value) {
  await store.patchSettings({ [field]: value })
}

function _openConfirm(action, run) {
  confirmAction.value = action
  confirmKind.value = run.kind
  confirmRunId.value = run.id
  confirmDescription.value = (
    action === 'restore'
      ? `Source artifact: ${run.kind === 'db' ? run.sql_path : run.tar_path}`
      : 'Removes the BackupRun row and unlinks the artifact files.'
  )
  confirmOpen.value = true
}

function onRestore(run) { _openConfirm('restore', run) }
function onDelete(run) { _openConfirm('delete', run) }

async function onTag(run) {
  const next = prompt(
    `Tag for backup #${run.id} (blank to clear):`,
    run.tag || '',
  )
  if (next === null) return
  await store.setTag(run.id, next.trim() || null)
  pollOnce()
}

async function onConfirmSubmit(token) {
  try {
    if (confirmAction.value === 'restore') {
      await store.restore(confirmRunId.value, token)
    } else {
      await store.deleteRun(confirmRunId.value, token)
    }
    pollOnce()
  } catch {
    // store.lastError already updated; surfaced in v-alert above.
  }
}
</script>

<style scoped>
.fc-backup-card { border-radius: 8px; }
.fc-muted { color: rgb(var(--v-theme-on-surface-variant)); }
.fc-section-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 16px; font-weight: 500;
  color: rgb(var(--v-theme-on-surface));
  margin-bottom: 8px;
}
.fc-settings-row {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
}
</style>
