<template>
  <div class="bh">
    <div class="bh-head">
      <router-link :to="`/assets/${assetid}`" class="bh-back">&larr; Back to asset</router-link>
      <h1>Configuration Backups</h1>
      <p v-if="assetname" class="bh-sub">{{ assetname }}</p>
    </div>

    <div v-if="loading" class="bh-note">Loading...</div>
    <div v-else-if="error" class="bh-error">{{ error }}</div>
    <div v-else-if="!revisions.length" class="bh-note">
      No backups on record for this asset yet.
    </div>

    <table v-else class="bh-table">
      <thead>
        <tr>
          <th>Captured</th>
          <th>Kind</th>
          <th>From PC</th>
          <th>Hash</th>
          <th>Changes</th>
          <th class="bh-actions-col">Download</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="rev in revisions" :key="rev.backuprevisionid"
            :class="{ 'bh-latest': rev.islatest }">
          <td>
            {{ formatWhen(rev.collectedat || rev.createdat) }}
            <span v-if="rev.islatest" class="bh-badge">current</span>
          </td>
          <td>{{ rev.backupkind }}</td>
          <td>{{ rev.sourcehostname || '-' }}</td>
          <td class="bh-mono">{{ rev.shorthash }}</td>
          <td>
            <button v-if="rev.storagebackend === 'shopdb'"
                    class="bh-link" @click="loadDiff(rev)">
              {{ diffs[rev.backuprevisionid] ? 'hide' : 'compare' }}
            </button>
            <span v-else class="bh-muted">-</span>
          </td>
          <td class="bh-actions">
            <!-- Share-backed revisions are not streamed by ShopDB; show the
                 UNC path so the tech can open it directly. -->
            <template v-if="rev.storagebackend === 'share'">
              <code class="bh-path" :title="rev.sharepath">{{ rev.sharepath }}</code>
            </template>
            <template v-else>
              <button v-for="fmt in rev.formats" :key="fmt.id"
                      class="bh-btn" :title="fmt.hint"
                      @click="download(rev, fmt)">
                {{ fmt.label }}
              </button>
            </template>
          </td>
        </tr>
      </tbody>
    </table>

    <div v-for="rev in revisions" :key="`d-${rev.backuprevisionid}`">
      <div v-if="diffs[rev.backuprevisionid]" class="bh-diff">
        <h3>
          Changes in revision {{ rev.backuprevisionid }}
          <span v-if="diffs[rev.backuprevisionid].againstid">
            vs {{ diffs[rev.backuprevisionid].againstid }}
          </span>
        </h3>
        <p v-if="diffs[rev.backuprevisionid].message" class="bh-muted">
          {{ diffs[rev.backuprevisionid].message }}
        </p>
        <table v-else-if="diffs[rev.backuprevisionid].changes.length" class="bh-table">
          <thead>
            <tr><th>Key</th><th>Value</th><th>Before</th><th>After</th></tr>
          </thead>
          <tbody>
            <tr v-for="(c, i) in diffs[rev.backuprevisionid].changes" :key="i">
              <td class="bh-mono">{{ c.keypath || '(root)' }}</td>
              <td class="bh-mono">{{ c.valuename }}</td>
              <td class="bh-before">{{ display(c.before) }}</td>
              <td class="bh-after">{{ display(c.after) }}</td>
            </tr>
          </tbody>
        </table>
        <p v-else class="bh-muted">No differences.</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import api from '@/api'

const route = useRoute()
const assetid = route.params.assetid

const revisions = ref([])
const diffs = ref({})
const assetname = ref('')
const loading = ref(true)
const error = ref('')

function formatWhen(value) {
  if (!value) return 'unknown'
  const d = new Date(value)
  return isNaN(d) ? value : d.toLocaleString()
}

function display(value) {
  if (value === null || value === undefined) return '(absent)'
  if (value === '') return '(empty)'
  return String(value)
}

async function load() {
  loading.value = true
  error.value = ''
  try {
    const response = await api.get(`/backups/asset/${assetid}`)
    revisions.value = response.data.data || []
  } catch (e) {
    error.value = e.response?.data?.error?.message || 'Failed to load backups.'
  } finally {
    loading.value = false
  }
  try {
    const asset = await api.get(`/assets/${assetid}`)
    assetname.value = asset.data.data?.name || ''
  } catch (e) {
    // Name is decoration; the history is still usable without it.
  }
}

async function loadDiff(rev) {
  if (diffs.value[rev.backuprevisionid]) {
    delete diffs.value[rev.backuprevisionid]
    diffs.value = { ...diffs.value }
    return
  }
  try {
    const response = await api.get(
      `/backups/revisions/${rev.backuprevisionid}/diff`)
    diffs.value = { ...diffs.value, [rev.backuprevisionid]: response.data.data }
  } catch (e) {
    diffs.value = {
      ...diffs.value,
      [rev.backuprevisionid]: {
        changes: [],
        message: e.response?.data?.error?.message || 'Could not build a diff.'
      }
    }
  }
}

async function download(rev, fmt) {
  // responseType blob so the UTF-16LE .reg is not mangled by JSON parsing;
  // the Content-Disposition filename is not readable cross-origin, so rebuild
  // it here to match what the server sends.
  const response = await api.get(
    `/backups/revisions/${rev.backuprevisionid}/download?format=${fmt.id}`,
    { responseType: 'blob' })
  const suffix = fmt.id === 'wow6432node' ? '-wow6432node' : ''
  const name = `${rev.sourcefilename || rev.backupkind}${suffix}${fmt.ext}`
    .replace(/(\.reg)+$/, '.reg')
  const link = document.createElement('a')
  link.href = URL.createObjectURL(response.data)
  link.download = name
  link.click()
  URL.revokeObjectURL(link.href)
}

onMounted(load)
</script>

<style scoped>
.bh { padding: 1.5rem; }
.bh-head { margin-bottom: 1rem; }
.bh-back { font-size: 0.85rem; }
.bh-sub { color: #666; margin: 0.2rem 0 0; }
.bh-note, .bh-muted { color: #666; }
.bh-error { color: #c00; }
.bh-table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; }
.bh-table th, .bh-table td {
  text-align: left; padding: 0.5rem 0.6rem; border-bottom: 1px solid #e0e0e0;
  vertical-align: top;
}
.bh-latest { background: #f4f9ff; }
.bh-badge {
  font-size: 0.7rem; background: #0d6efd; color: #fff;
  border-radius: 3px; padding: 0.05rem 0.35rem; margin-left: 0.4rem;
}
.bh-mono, .bh-path { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.82rem; }
.bh-path { word-break: break-all; }
.bh-actions-col { width: 22rem; }
.bh-btn {
  font-size: 0.78rem; margin: 0 0.3rem 0.3rem 0; padding: 0.25rem 0.5rem;
  border: 1px solid #0d6efd; background: #fff; color: #0d6efd;
  border-radius: 4px; cursor: pointer;
}
.bh-btn:hover { background: #0d6efd; color: #fff; }
.bh-link {
  background: none; border: none; color: #0d6efd; cursor: pointer;
  padding: 0; font-size: 0.82rem; text-decoration: underline;
}
.bh-diff { margin: 0 0 1.5rem; }
.bh-before { color: #b00; }
.bh-after { color: #070; }
</style>
