<template>
	<div class="backup-page">
		<h2>Backup & Wiederherstellung</h2>

		<!-- Messages -->
		<div v-if="store.error" class="backup-page__message backup-page__message--error">
			{{ store.error }}
			<NcButton @click="store.clearError()">Schliessen</NcButton>
		</div>
		<div v-if="store.success" class="backup-page__message backup-page__message--success">
			{{ store.success }}
			<NcButton @click="store.clearSuccess()">Schliessen</NcButton>
		</div>

		<!-- App Update -->
		<div class="backup-page__section">
			<h3>App-Update</h3>
			<div class="backup-page__update">
				<div class="backup-page__update-status">
					<span>Installierte Version: <strong>v{{ store.updateInfo?.currentVersion || '...' }}</strong></span>
					<template v-if="store.updateInfo">
						<template v-if="store.updateInfo.available">
							<span class="backup-page__badge backup-page__badge--update">
								v{{ store.updateInfo.latestVersion }} verfuegbar
							</span>
						</template>
						<template v-else-if="store.updateInfo.latestVersion">
							<span class="backup-page__badge">Aktuell</span>
						</template>
						<template v-else-if="store.updateInfo.error">
							<span class="backup-page__badge backup-page__badge--none"
								:title="store.updateInfo.errorDetail || store.updateInfo.error">
								Pruefung fehlgeschlagen
							</span>
						</template>
					</template>
				</div>
				<div v-if="store.updateInfo?.error" class="backup-page__update-error">
					<strong>Update-Check fehlgeschlagen</strong>
					<p>{{ store.updateInfo.error }}</p>
					<details v-if="store.updateInfo.errorDetail">
						<summary>Technische Details</summary>
						<pre class="backup-page__update-error-detail">{{ store.updateInfo.errorDetail }}</pre>
						<div v-if="store.updateInfo.targetUrl">
							Ziel: <code>{{ store.updateInfo.targetUrl }}</code>
						</div>
					</details>
				</div>
				<div v-if="store.updateInfo?.releaseBody" class="backup-page__update-notes">
					{{ store.updateInfo.releaseBody }}
				</div>
				<div class="backup-page__update-actions">
					<NcButton @click="store.checkForUpdate()">
						Nach Updates suchen
					</NcButton>
					<NcButton v-if="store.updateInfo?.available"
						type="primary"
						:disabled="store.updating"
						@click="confirmUpdate">
						<NcLoadingIcon v-if="store.updating" :size="20" />
						<template v-else>Update installieren</template>
					</NcButton>
					<NcButton :disabled="store.updating"
						@click="showManualUpdate = !showManualUpdate">
						{{ showManualUpdate ? 'Manuelles Update schließen' : 'Manuelles Update…' }}
					</NcButton>
				</div>

				<!-- Manual update panel (upload .tar.gz + .sig) -->
				<div v-if="showManualUpdate" class="backup-page__manual-update">
					<h4>Manuelles Update</h4>
					<p class="backup-page__manual-update-hint">
						Wähle das Release-Archiv (<code>.tar.gz</code>) und die dazugehörige
						Signatur (<code>.tar.gz.sig</code>). Die Signatur wird <strong>vor</strong>
						der Installation gegen den eingebetteten öffentlichen Schlüssel geprüft —
						nur gültig signierte Pakete werden installiert.
					</p>
					<div class="backup-page__manual-update-fields">
						<label>
							<span>Archiv (.tar.gz)</span>
							<input ref="archiveInput"
								type="file"
								accept=".tar.gz,application/gzip,application/x-gzip"
								:disabled="store.updating"
								@change="onArchivePick">
						</label>
						<label>
							<span>Signatur (.tar.gz.sig)</span>
							<input ref="signatureInput"
								type="file"
								accept=".sig,application/octet-stream"
								:disabled="store.updating"
								@change="onSignaturePick">
						</label>
					</div>
					<div class="backup-page__manual-update-actions">
						<NcButton type="primary"
							:disabled="store.updating || !manualArchive || !manualSignature"
							@click="confirmManualUpdate">
							<NcLoadingIcon v-if="store.updating" :size="20" />
							<template v-else>Manuell installieren</template>
						</NcButton>
						<NcButton :disabled="store.updating" @click="resetManualUpdate">
							Auswahl zurücksetzen
						</NcButton>
					</div>
				</div>
			</div>
		</div>

		<!-- Schedule settings -->
		<div class="backup-page__section">
			<h3>Automatische Backups</h3>
			<div class="backup-page__settings">
				<div class="backup-page__setting">
					<label for="backup-schedule">Zeitplan</label>
					<select id="backup-schedule"
						:value="store.settings.schedule"
						class="backup-page__select"
						@change="updateSchedule($event.target.value)">
						<option value="disabled">Deaktiviert</option>
						<option value="daily">Taeglich</option>
						<option value="weekly">Woechentlich</option>
					</select>
				</div>
				<div class="backup-page__setting">
					<label for="backup-retention">Aufbewahrung (Anzahl)</label>
					<input id="backup-retention"
						type="number"
						min="1"
						max="100"
						:value="store.settings.retentionCount"
						class="backup-page__input"
						@change="updateRetention(parseInt($event.target.value))">
				</div>
				<div class="backup-page__setting">
					<label>Automatisches Passwort</label>
					<span v-if="store.settings.hasPassword" class="backup-page__badge">Gesetzt</span>
					<span v-else class="backup-page__badge backup-page__badge--none">Nicht gesetzt</span>
				</div>
			</div>
		</div>

		<!-- Manual backup -->
		<div class="backup-page__section">
			<h3>Manuelles Backup</h3>
			<div class="backup-page__create">
				<div class="backup-page__setting">
					<label for="backup-password">Passwort (optional)</label>
					<input id="backup-password"
						v-model="createPassword"
						type="password"
						placeholder="Ohne Passwort"
						class="backup-page__input">
				</div>
				<NcButton type="primary"
					:disabled="store.creating"
					@click="doCreate">
					<NcLoadingIcon v-if="store.creating" :size="20" />
					<template v-else>Backup erstellen</template>
				</NcButton>
			</div>
		</div>

		<!-- Backup list -->
		<div class="backup-page__section">
			<h3>Vorhandene Backups</h3>

			<NcLoadingIcon v-if="store.loading && store.backups.length === 0"
				:size="48"
				class="backup-page__loading" />

			<div v-else-if="store.backups.length === 0" class="backup-page__empty">
				Keine Backups vorhanden.
			</div>

			<table v-else class="backup-page__table">
				<thead>
					<tr>
						<th>Dateiname</th>
						<th>Erstellt</th>
						<th>Groesse</th>
						<th>Tabellen</th>
						<th>Zeilen</th>
						<th>Ausloser</th>
						<th>Aktionen</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="backup in store.backups" :key="backup.filename">
						<td>{{ backup.filename }}</td>
						<td>{{ formatDateTime(backup.createdAt) }}</td>
						<td>{{ formatBytes(backup.size) }}</td>
						<td>{{ Object.keys(backup.tables || {}).length }}</td>
						<td>{{ totalRows(backup) }}</td>
						<td>{{ formatTrigger(backup.triggeredBy) }}</td>
						<td class="backup-page__actions">
							<NcButton @click="store.downloadBackup(backup.filename)">
								Download
							</NcButton>
							<NcButton type="warning"
								:disabled="store.restoring"
								@click="confirmRestore(backup)">
								Wiederherstellen
							</NcButton>
							<NcButton type="error"
								@click="confirmDelete(backup)">
								Loeschen
							</NcButton>
						</td>
					</tr>
				</tbody>
			</table>
		</div>

		<!-- Restore confirmation dialog -->
		<div v-if="restoreTarget" class="backup-page__dialog-backdrop">
			<div class="backup-page__dialog">
				<h3>Backup wiederherstellen</h3>
				<p>
					<strong>WARNUNG:</strong> Alle bestehenden Daten werden geloescht und durch
					das Backup <strong>{{ restoreTarget.filename }}</strong> ersetzt.
				</p>
				<p>Erstellt: {{ formatDateTime(restoreTarget.createdAt) }}</p>
				<div class="backup-page__setting">
					<label for="restore-password">Passwort (falls verschluesselt)</label>
					<input id="restore-password"
						v-model="restorePassword"
						type="password"
						placeholder="Ohne Passwort"
						class="backup-page__input">
				</div>
				<div class="backup-page__dialog-actions">
					<NcButton @click="restoreTarget = null">Abbrechen</NcButton>
					<NcButton type="error"
						:disabled="store.restoring"
						@click="doRestore">
						<NcLoadingIcon v-if="store.restoring" :size="20" />
						<template v-else>Jetzt wiederherstellen</template>
					</NcButton>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { NcButton, NcLoadingIcon } from '@nextcloud/vue'
import { useBackupStore } from '../stores/backup.js'

const store = useBackupStore()

const createPassword = ref('')
const restoreTarget = ref(null)
const restorePassword = ref('')
const showManualUpdate = ref(false)
const manualArchive = ref(null)
const manualSignature = ref(null)
const archiveInput = ref(null)
const signatureInput = ref(null)

onMounted(() => {
	store.fetchBackups()
	store.fetchSettings()
	store.checkForUpdate()
})

async function doCreate() {
	await store.createBackup(createPassword.value || null)
	createPassword.value = ''
}

function confirmRestore(backup) {
	restoreTarget.value = backup
	restorePassword.value = ''
}

async function doRestore() {
	const filename = restoreTarget.value.filename
	restoreTarget.value = null
	await store.restoreBackup(filename, restorePassword.value || null)
}

async function confirmUpdate() {
	if (confirm('Update installieren? Die App-Dateien werden ersetzt und die Seite wird neu geladen.')) {
		const result = await store.installUpdate(false)
		if (result?.success) {
			window.location.reload()
		}
	}
}

function onArchivePick(event) {
	manualArchive.value = event.target.files?.[0] || null
}

function onSignaturePick(event) {
	manualSignature.value = event.target.files?.[0] || null
}

function resetManualUpdate() {
	manualArchive.value = null
	manualSignature.value = null
	if (archiveInput.value) archiveInput.value.value = ''
	if (signatureInput.value) signatureInput.value.value = ''
}

async function confirmManualUpdate() {
	if (!manualArchive.value || !manualSignature.value) return
	const msg = `Manuelles Update mit "${manualArchive.value.name}" installieren? Die Signatur wird vor der Installation geprüft. Die Seite wird danach neu geladen.`
	if (!confirm(msg)) return
	try {
		const result = await store.installManualUpdate(manualArchive.value, manualSignature.value)
		if (result?.success) {
			resetManualUpdate()
			showManualUpdate.value = false
			window.location.reload()
		}
	} catch {
		// error shown via store.error
	}
}

function confirmDelete(backup) {
	if (confirm(`Backup "${backup.filename}" wirklich loeschen?`)) {
		store.deleteBackup(backup.filename)
	}
}

function updateSchedule(value) {
	store.updateSettings({ schedule: value })
}

function updateRetention(value) {
	if (value >= 1) {
		store.updateSettings({ retentionCount: value })
	}
}

function formatDateTime(isoString) {
	if (!isoString) return '-'
	const d = new Date(isoString)
	return d.toLocaleDateString('de-DE') + ' ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })
}

function formatBytes(bytes) {
	if (!bytes) return '-'
	if (bytes >= 1048576) return (bytes / 1048576).toFixed(2) + ' MB'
	if (bytes >= 1024) return (bytes / 1024).toFixed(1) + ' KB'
	return bytes + ' B'
}

function totalRows(backup) {
	if (!backup.tables) return 0
	return Object.values(backup.tables).reduce((sum, n) => sum + n, 0)
}

function formatTrigger(trigger) {
	const map = { manual: 'Manuell', scheduled: 'Geplant', cli: 'CLI' }
	return map[trigger] || trigger || '-'
}
</script>

<style scoped>
.backup-page { padding: 20px; max-width: 1200px; }
.backup-page h2 { margin: 0 0 20px 0; }
.backup-page__section { margin-bottom: 32px; }
.backup-page__section h3 { margin: 0 0 12px 0; }

.backup-page__message { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border-radius: var(--border-radius); margin-bottom: 16px; color: white; }
.backup-page__message--error { background: var(--color-error); }
.backup-page__message--success { background: var(--color-success); }

.backup-page__settings { display: flex; gap: 24px; flex-wrap: wrap; align-items: flex-end; padding: 12px 16px; background: var(--color-background-dark); border-radius: var(--border-radius-large); }
.backup-page__setting { display: flex; flex-direction: column; gap: 4px; }
.backup-page__setting label { font-size: 0.8em; color: var(--color-text-lighter); font-weight: 500; }
.backup-page__select { padding: 6px 8px; border: 1px solid var(--color-border); border-radius: var(--border-radius); background: var(--color-main-background); }
.backup-page__input { padding: 6px 8px; border: 1px solid var(--color-border); border-radius: var(--border-radius); background: var(--color-main-background); }

.backup-page__badge { display: inline-block; padding: 2px 8px; border-radius: var(--border-radius-pill); font-size: 0.85em; font-weight: 500; background: var(--color-success); color: white; }
.backup-page__badge--none { background: var(--color-text-lighter); }
.backup-page__badge--update { background: var(--color-primary); }

.backup-page__update { padding: 12px 16px; background: var(--color-background-dark); border-radius: var(--border-radius-large); }
.backup-page__update-status { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.backup-page__update-notes { font-size: 0.9em; color: var(--color-text-lighter); margin-bottom: 12px; white-space: pre-line; }
.backup-page__update-error { margin: 8px 0 12px; padding: 10px 14px; border-radius: var(--border-radius); background: color-mix(in srgb, var(--color-error) 10%, transparent); border: 1px solid color-mix(in srgb, var(--color-error) 40%, transparent); font-size: 0.9em; }
.backup-page__update-error strong { color: var(--color-error); }
.backup-page__update-error p { margin: 4px 0 8px; }
.backup-page__update-error summary { cursor: pointer; color: var(--color-text-lighter); font-size: 0.85em; }
.backup-page__update-error-detail { white-space: pre-wrap; word-break: break-word; font-size: 0.8em; margin: 4px 0; padding: 6px 8px; background: var(--color-background-dark); border-radius: var(--border-radius); }
.backup-page__update-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.backup-page__manual-update { margin-top: 16px; padding: 14px 16px; border: 1px dashed var(--color-border); border-radius: var(--border-radius); background: var(--color-background-dark); }
.backup-page__manual-update h4 { margin: 0 0 6px; }
.backup-page__manual-update-hint { font-size: 0.85em; color: var(--color-text-lighter); margin: 0 0 12px; }
.backup-page__manual-update-hint code { font-family: monospace; background: var(--color-background-darker, var(--color-background-dark)); padding: 1px 4px; border-radius: 3px; }
.backup-page__manual-update-fields { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.backup-page__manual-update-fields label { display: flex; flex-direction: column; font-size: 0.9em; gap: 4px; }
.backup-page__manual-update-fields label span { color: var(--color-text-lighter); }
.backup-page__manual-update-fields input[type="file"] { font-size: 0.85em; }
.backup-page__manual-update-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.backup-page__create { display: flex; gap: 16px; align-items: flex-end; }
.backup-page__loading { display: flex; justify-content: center; margin-top: 40px; }
.backup-page__empty { color: var(--color-text-lighter); padding: 24px; text-align: center; }

.backup-page__table { width: 100%; border-collapse: collapse; font-size: 0.9em; }
.backup-page__table th { text-align: left; padding: 10px 12px; border-bottom: 2px solid var(--color-border-dark); font-weight: bold; white-space: nowrap; }
.backup-page__table td { padding: 8px 12px; border-bottom: 1px solid var(--color-border); vertical-align: middle; }
.backup-page__table tr:hover { background: var(--color-background-hover); }
.backup-page__actions { white-space: nowrap; }
.backup-page__actions :deep(.button-vue) { display: inline-flex; margin: 2px; }

.backup-page__dialog-backdrop { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 1000; }
.backup-page__dialog { background: var(--color-main-background); padding: 24px; border-radius: var(--border-radius-large); max-width: 520px; width: 90%; box-shadow: 0 4px 24px rgba(0,0,0,0.2); }
.backup-page__dialog h3 { margin: 0 0 12px 0; }
.backup-page__dialog p { margin: 0 0 12px 0; }
.backup-page__dialog-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
</style>
