<script lang="ts">
	import { onMount } from 'svelte';
	import { api, fetchAuth } from '$lib/api';
	import { t } from '$lib/i18n';
	import PageHeader from '$lib/components/PageHeader.svelte';
	import Card from '$lib/components/Card.svelte';
	import Loading from '$lib/components/Loading.svelte';
	import MdiIcon from '$lib/components/MdiIcon.svelte';
	import ErrorBanner from '$lib/components/ErrorBanner.svelte';
	import Button from '$lib/components/Button.svelte';
	import ConfirmModal from '$lib/components/ConfirmModal.svelte';
	import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';

	// --- Export state ---
	let exportSecrets = $state('exclude');
	let exporting = $state(false);

	const categories = [
		{ key: 'providers', label: 'backup.catProviders' },
		{ key: 'telegram_bots', label: 'backup.catTelegramBots' },
		{ key: 'matrix_bots', label: 'backup.catMatrixBots' },
		{ key: 'email_bots', label: 'backup.catEmailBots' },
		{ key: 'targets', label: 'backup.catTargets' },
		{ key: 'tracking_configs', label: 'backup.catTrackingConfigs' },
		{ key: 'template_configs', label: 'backup.catTemplateConfigs' },
		{ key: 'command_configs', label: 'backup.catCommandConfigs' },
		{ key: 'command_template_configs', label: 'backup.catCommandTemplateConfigs' },
		{ key: 'notification_trackers', label: 'backup.catNotificationTrackers' },
		{ key: 'command_trackers', label: 'backup.catCommandTrackers' },
		{ key: 'actions', label: 'backup.catActions' },
		{ key: 'app_settings', label: 'backup.catAppSettings' },
	];
	let selectedCategories = $state<Record<string, boolean>>(
		Object.fromEntries(categories.map(c => [c.key, true]))
	);

	// --- Import state ---
	let importFile: File | null = $state(null);
	let importConflict = $state('skip');
	let importing = $state(false);
	let validating = $state(false);
	let validationResult: any = $state(null);
	let importResult: any = $state(null);
	let confirmImportOpen = $state(false);
	let confirmExportOpen = $state(false);

	// --- Scheduled backup state ---
	let loaded = $state(false);
	let error = $state('');
	let scheduledSettings = $state({
		backup_scheduled_enabled: 'false',
		backup_scheduled_interval_hours: '24',
		backup_secrets_mode: 'exclude',
		backup_retention_count: '5',
	});
	let savingSchedule = $state(false);

	// --- Backup files ---
	let backupFiles = $state<any[]>([]);
	let loadingFiles = $state(false);
	let confirmDeleteFile = $state('');
	let creatingBackup = $state(false);

	// --- Pending restore state ---
	let pending = $state<{ pending: boolean; uploaded_at?: string | null; uploaded_by?: string | null; conflict_mode?: string; supervised?: boolean } | null>(null);
	let postRestoreModalOpen = $state(false);
	let restartingOverlay = $state(false);

	onMount(async () => {
		try {
			const [settings, files, p] = await Promise.all([
				api('/backup/scheduled'),
				api('/backup/files'),
				api('/backup/pending-restore'),
			]);
			scheduledSettings = settings;
			backupFiles = files;
			pending = p;
		} catch (err: any) {
			error = err.message;
			snackError(err.message);
		} finally {
			loaded = true;
		}
	});

	async function cancelPending() {
		try {
			await api('/backup/pending-restore', { method: 'DELETE' });
			snackSuccess(t('backup.pendingCancelled'));
			pending = null;
		} catch (err: any) { snackError(err.message); }
	}

	async function applyAndRestart() {
		try {
			await api('/backup/apply-restart', { method: 'POST' });
			restartingOverlay = true;
			// Poll /health until the new instance is up
			const startedAt = Date.now();
			let attempts = 0;
			const poll = async () => {
				attempts += 1;
				try {
					const res = await fetch('/api/health');
					if (res.ok && Date.now() - startedAt > 2000) {
						window.location.reload();
						return;
					}
				} catch { /* still down */ }
				if (attempts < 120) setTimeout(poll, 1000);
			};
			setTimeout(poll, 1500);
		} catch (err: any) {
			restartingOverlay = false;
			snackError(err.message);
		}
	}

	async function createManualBackup() {
		creatingBackup = true;
		try {
			const mode = scheduledSettings.backup_secrets_mode || 'exclude';
			await api(`/backup/files?secrets_mode=${mode}`, { method: 'POST' });
			snackSuccess(t('backup.manualCreated'));
			await refreshFiles();
		} catch (err: any) {
			snackError(err.message);
		} finally {
			creatingBackup = false;
		}
	}

	// --- Export ---
	async function doExport() {
		if (exportSecrets === 'include') {
			confirmExportOpen = true;
			return;
		}
		await performExport();
	}

	async function performExport() {
		confirmExportOpen = false;
		exporting = true;
		try {
			const cats = Object.entries(selectedCategories)
				.filter(([_, v]) => v)
				.map(([k]) => k)
				.join(',');
			const data = await api(`/backup/export?secrets_mode=${exportSecrets}&categories=${cats}`);
			const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
			const url = URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = url;
			const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
			a.download = `notify-bridge-backup-${ts}.json`;
			a.click();
			URL.revokeObjectURL(url);
			snackSuccess(t('backup.exportSuccess'));
		} catch (err: any) {
			snackError(err.message);
		} finally {
			exporting = false;
		}
	}

	// --- Validate ---
	async function validateFile() {
		if (!importFile) return;
		validating = true;
		validationResult = null;
		importResult = null;
		try {
			const formData = new FormData();
			formData.append('file', importFile);
			const res = await fetchAuth('/backup/validate', { method: 'POST', body: formData });
			validationResult = await res.json();
		} catch (err: any) {
			snackError(err.message);
		} finally {
			validating = false;
		}
	}

	// --- Import ---
	async function doImport() {
		confirmImportOpen = true;
	}

	async function performImport() {
		confirmImportOpen = false;
		if (!importFile) return;
		importing = true;
		importResult = null;
		try {
			const formData = new FormData();
			formData.append('file', importFile);
			const res = await fetchAuth(`/backup/prepare-restore?conflict_mode=${importConflict}`, {
				method: 'POST',
				body: formData,
			});
			importResult = await res.json();
			pending = importResult;
			snackSuccess(t('backup.restorePrepared'));
			postRestoreModalOpen = true;
			importFile = null;
		} catch (err: any) {
			snackError(err.message);
		} finally {
			importing = false;
		}
	}

	// --- Scheduled settings ---
	async function saveSchedule() {
		savingSchedule = true;
		try {
			scheduledSettings = await api('/backup/scheduled', {
				method: 'PUT',
				body: JSON.stringify(scheduledSettings),
			});
			snackSuccess(t('backup.scheduleSaved'));
		} catch (err: any) {
			snackError(err.message);
		} finally {
			savingSchedule = false;
		}
	}

	// --- File management ---
	async function refreshFiles() {
		loadingFiles = true;
		try {
			backupFiles = await api('/backup/files');
		} catch (err: any) {
			snackError(err.message);
		} finally {
			loadingFiles = false;
		}
	}

	async function downloadFile(filename: string) {
		try {
			const data = await api(`/backup/files/${filename}`);
			const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
			const url = URL.createObjectURL(blob);
			const a = document.createElement('a');
			a.href = url;
			a.download = filename;
			a.click();
			URL.revokeObjectURL(url);
		} catch (err: any) {
			snackError(err.message);
		}
	}

	async function deleteFile(filename: string) {
		try {
			await api(`/backup/files/${filename}`, { method: 'DELETE' });
			snackSuccess(t('backup.fileDeleted'));
			confirmDeleteFile = '';
			await refreshFiles();
		} catch (err: any) {
			snackError(err.message);
		}
	}

	function handleFileSelect(e: Event) {
		const input = e.target as HTMLInputElement;
		if (input.files?.length) {
			importFile = input.files[0];
			validationResult = null;
			importResult = null;
		}
	}

	function formatSize(bytes: number): string {
		if (bytes < 1024) return `${bytes} B`;
		if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
		return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
	}

	let allSelected = $derived(Object.values(selectedCategories).every(v => v));
	let noneSelected = $derived(Object.values(selectedCategories).every(v => !v));

	function toggleAll() {
		const newVal = !allSelected;
		for (const key of Object.keys(selectedCategories)) {
			selectedCategories[key] = newVal;
		}
	}
</script>

<PageHeader
	title={t('backup.title')}
	emphasis={t('backup.titleEmphasis')}
	description={t('backup.description')}
	crumb="System · Maintenance"
/>

{#if !loaded}
	<Loading />
{:else}
	<ErrorBanner message={error} />

	{#if pending?.pending}
		<div class="mb-4 p-3 rounded-lg flex flex-wrap items-center gap-3 pending-banner"
			style="border: 1px solid color-mix(in srgb, var(--color-warning-fg) 40%, transparent); background: color-mix(in srgb, var(--color-warning-bg) 60%, transparent);">
			<span style="color: var(--color-warning-fg); flex-shrink: 0;">
				<MdiIcon name="mdiClockAlert" size={20} />
			</span>
			<div class="flex-1 min-w-[12rem] text-sm">
				<div class="font-medium">{t('backup.pendingTitle')}</div>
				<div class="text-xs break-words" style="color: var(--color-muted-foreground);">
					{t('backup.pendingBy').replace('{by}', pending.uploaded_by || '')} · {t('backup.pendingAt').replace('{at}', pending.uploaded_at || '')}
				</div>
			</div>
			<div class="flex items-center gap-2 flex-wrap">
				{#if pending.supervised}
					<Button size="sm" onclick={applyAndRestart}>
						<MdiIcon name="mdiRestart" size={14} /> {t('backup.restartNow')}
					</Button>
				{/if}
				<button onclick={cancelPending}
					class="px-3 py-1.5 text-sm rounded-md border border-[var(--color-border)] hover:bg-[var(--color-muted)] transition-colors">
					{t('common.cancel')}
				</button>
			</div>
		</div>
	{/if}

	<div class="space-y-6">

		<!-- Export Section -->
		<Card>
			<h3 class="text-sm font-semibold mb-4 flex items-center gap-2">
				<MdiIcon name="mdiDatabaseExport" size={18} />
				{t('backup.export')}
			</h3>
			<p class="text-xs mb-4" style="color: var(--color-muted-foreground);">{t('backup.exportDescription')}</p>

			<!-- Categories -->
			<div class="mb-4">
				<div class="flex items-center gap-2 mb-2">
					<span class="text-xs font-medium">{t('backup.categories')}</span>
					<button class="text-xs underline" style="color: var(--color-primary);" onclick={toggleAll}>
						{allSelected ? t('backup.deselectAll') : t('backup.selectAll')}
					</button>
				</div>
				<div class="grid grid-cols-2 sm:grid-cols-3 gap-1.5">
					{#each categories as cat}
						<label class="flex items-center gap-1.5 text-xs">
							<input type="checkbox" bind:checked={selectedCategories[cat.key]} />
							{t(cat.label)}
						</label>
					{/each}
				</div>
			</div>

			<!-- Secrets mode -->
			<div class="mb-4">
				<div class="block text-xs font-medium mb-2">{t('backup.secretsMode')}</div>
				<div class="flex flex-col gap-1.5">
					<label class="flex items-center gap-1.5 text-xs">
						<input type="radio" bind:group={exportSecrets} value="exclude" />
						{t('backup.secretsExclude')}
					</label>
					<label class="flex items-center gap-1.5 text-xs">
						<input type="radio" bind:group={exportSecrets} value="masked" />
						{t('backup.secretsMasked')}
					</label>
					<label class="flex items-center gap-1.5 text-xs">
						<input type="radio" bind:group={exportSecrets} value="include" />
						{t('backup.secretsInclude')}
					</label>
				</div>
				{#if exportSecrets === 'include'}
					<div class="mt-2 p-2 rounded-md text-xs flex items-center gap-2"
						style="background: var(--color-error-bg); color: var(--color-error-fg);">
						<MdiIcon name="mdiAlert" size={14} />
						{t('backup.secretsWarningExport')}
					</div>
				{/if}
			</div>

			<Button onclick={doExport} disabled={exporting || noneSelected}>
				{#if exporting}
					<MdiIcon name="mdiLoading" size={14} />
				{:else}
					<MdiIcon name="mdiDownload" size={14} />
				{/if}
				{exporting ? t('common.loading') : t('backup.exportBtn')}
			</Button>
		</Card>

		<!-- Import Section -->
		<Card>
			<h3 class="text-sm font-semibold mb-4 flex items-center gap-2">
				<MdiIcon name="mdiDatabaseImport" size={18} />
				{t('backup.import')}
			</h3>
			<p class="text-xs mb-4" style="color: var(--color-muted-foreground);">{t('backup.importDescription')}</p>

			<!-- File picker -->
			<div class="mb-4">
				<input type="file" accept=".json" onchange={handleFileSelect}
					class="text-xs file:mr-2 file:py-1.5 file:px-3 file:rounded-md file:border-0 file:text-xs file:font-medium file:cursor-pointer"
					style="file:background: var(--color-muted); file:color: var(--color-foreground);" />
			</div>

			{#if importFile}
				<!-- Validate -->
				<div class="mb-4 flex items-center gap-2">
					<Button variant="secondary" onclick={validateFile} disabled={validating}>
						{#if validating}
							<MdiIcon name="mdiLoading" size={14} />
						{:else}
							<MdiIcon name="mdiCheckCircleOutline" size={14} />
						{/if}
						{validating ? t('backup.validating') : t('backup.validateBtn')}
					</Button>
				</div>

				{#if validationResult}
					<div class="mb-4 p-3 rounded-md text-xs border" style="border-color: var(--color-border);">
						<div class="flex items-center gap-2 mb-2 font-medium">
							{#if validationResult.valid}
								<span style="color: var(--color-success-fg, green);"><MdiIcon name="mdiCheckCircle" size={14} /></span>
								<span style="color: var(--color-success-fg, green);">{t('backup.validationPassed')}</span>
							{:else}
								<MdiIcon name="mdiCloseCircle" size={14} />
								<span style="color: var(--color-error-fg);">{t('backup.validationFailed')}</span>
							{/if}
						</div>
						{#if Object.keys(validationResult.entity_counts || {}).length}
							<div class="mb-2">
								<span class="font-medium">{t('backup.entities')}:</span>
								{#each Object.entries(validationResult.entity_counts) as [cat, count]}
									<span class="inline-block mr-2">{cat}: {count}</span>
								{/each}
							</div>
						{/if}
						{#each validationResult.warnings || [] as w}
							<div class="flex items-start gap-1 mt-1" style="color: var(--color-warning-fg, orange);">
								<MdiIcon name="mdiAlert" size={12} />
								<span>{w}</span>
							</div>
						{/each}
						{#each validationResult.errors || [] as e}
							<div class="flex items-start gap-1 mt-1" style="color: var(--color-error-fg);">
								<MdiIcon name="mdiAlertCircle" size={12} />
								<span>{e}</span>
							</div>
						{/each}
					</div>
				{/if}

				<!-- Conflict mode -->
				<div class="mb-4">
					<div class="block text-xs font-medium mb-2">{t('backup.conflictMode')}</div>
					<div class="flex flex-col gap-1.5">
						<label class="flex items-center gap-1.5 text-xs">
							<input type="radio" bind:group={importConflict} value="skip" />
							{t('backup.conflictSkip')}
						</label>
						<label class="flex items-center gap-1.5 text-xs">
							<input type="radio" bind:group={importConflict} value="rename" />
							{t('backup.conflictRename')}
						</label>
						<label class="flex items-center gap-1.5 text-xs">
							<input type="radio" bind:group={importConflict} value="overwrite" />
							{t('backup.conflictOverwrite')}
						</label>
					</div>
				</div>

				<Button onclick={doImport}
					disabled={importing || !validationResult?.valid}>
					{#if importing}
						<MdiIcon name="mdiLoading" size={14} />
					{:else}
						<MdiIcon name="mdiUpload" size={14} />
					{/if}
					{importing ? t('backup.importing') : t('backup.importBtn')}
				</Button>

				{#if importResult}
					<div class="mt-4 p-3 rounded-md text-xs border" style="border-color: var(--color-border);">
						<div class="font-medium mb-1">{t('backup.importResults')}</div>
						<div class="space-y-0.5">
							<div>{t('backup.resultCreated')}: {importResult.created}</div>
							<div>{t('backup.resultSkipped')}: {importResult.skipped}</div>
							<div>{t('backup.resultOverwritten')}: {importResult.overwritten}</div>
							{#if importResult.errors?.length}
								<div style="color: var(--color-error-fg);">{t('backup.resultErrors')}: {importResult.errors.length}</div>
								{#each importResult.errors as e}
									<div class="ml-2" style="color: var(--color-error-fg);">{e}</div>
								{/each}
							{/if}
							{#if importResult.warnings?.length}
								{#each importResult.warnings as w}
									<div class="ml-2" style="color: var(--color-warning-fg, orange);">{w}</div>
								{/each}
							{/if}
						</div>
					</div>
				{/if}
			{/if}
		</Card>

		<!-- Scheduled Backups Section -->
		<Card>
			<h3 class="text-sm font-semibold mb-4 flex items-center gap-2">
				<MdiIcon name="mdiClockOutline" size={18} />
				{t('backup.scheduled')}
			</h3>

			<div class="space-y-3">
				<label class="flex items-center gap-2 text-xs">
					<input type="checkbox"
						checked={scheduledSettings.backup_scheduled_enabled === 'true'}
						onchange={() => scheduledSettings.backup_scheduled_enabled =
							scheduledSettings.backup_scheduled_enabled === 'true' ? 'false' : 'true'} />
					<span class="font-medium">{t('backup.enableScheduled')}</span>
				</label>

				{#if scheduledSettings.backup_scheduled_enabled === 'true'}
					<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
						<div>
							<label for="backup-interval" class="block text-xs font-medium mb-1">{t('backup.interval')}</label>
							<select id="backup-interval" bind:value={scheduledSettings.backup_scheduled_interval_hours}
								class="w-full px-3 py-1.5 text-sm border border-[var(--color-border)] rounded-md bg-[var(--color-background)]">
								<option value="6">6 {t('backup.hours')}</option>
								<option value="12">12 {t('backup.hours')}</option>
								<option value="24">24 {t('backup.hours')}</option>
								<option value="48">48 {t('backup.hours')}</option>
								<option value="72">72 {t('backup.hours')}</option>
								<option value="168">168 {t('backup.hours')} (7d)</option>
							</select>
						</div>
						<div>
							<label for="backup-secrets-mode" class="block text-xs font-medium mb-1">{t('backup.secretsMode')}</label>
							<select id="backup-secrets-mode" bind:value={scheduledSettings.backup_secrets_mode}
								class="w-full px-3 py-1.5 text-sm border border-[var(--color-border)] rounded-md bg-[var(--color-background)]">
								<option value="exclude">{t('backup.secretsExclude')}</option>
								<option value="masked">{t('backup.secretsMasked')}</option>
								<option value="include">{t('backup.secretsInclude')}</option>
							</select>
						</div>
						<div>
							<label for="backup-retention" class="block text-xs font-medium mb-1">{t('backup.retention')}</label>
							<select id="backup-retention" bind:value={scheduledSettings.backup_retention_count}
								class="w-full px-3 py-1.5 text-sm border border-[var(--color-border)] rounded-md bg-[var(--color-background)]">
								<option value="3">3</option>
								<option value="5">5</option>
								<option value="10">10</option>
								<option value="20">20</option>
							</select>
						</div>
					</div>
				{/if}
			</div>

			<div class="mt-4">
				<Button onclick={saveSchedule} disabled={savingSchedule}>
					{savingSchedule ? t('common.loading') : t('common.save')}
				</Button>
			</div>
		</Card>

		<!-- Saved Backup Files -->
		<Card>
			<div class="flex items-center justify-between mb-4">
				<h3 class="text-sm font-semibold flex items-center gap-2">
					<MdiIcon name="mdiFolder" size={18} />
					{t('backup.savedFiles')}
				</h3>
				<div class="flex items-center gap-2">
					<Button size="sm" onclick={createManualBackup} disabled={creatingBackup}>
						<MdiIcon name="mdiPlus" size={14} /> {creatingBackup ? t('common.loading') : t('backup.createManual')}
					</Button>
					<button onclick={refreshFiles} class="text-xs" style="color: var(--color-primary);" disabled={loadingFiles}>
						<MdiIcon name="mdiRefresh" size={14} />
					</button>
				</div>
			</div>

			{#if backupFiles.length === 0}
				<p class="text-xs" style="color: var(--color-muted-foreground);">{t('backup.noFiles')}</p>
			{:else}
				<div class="space-y-2">
					{#each backupFiles as file}
						<div class="flex items-center justify-between p-2 rounded-md border text-xs"
							style="border-color: var(--color-border);">
							<div class="flex items-center gap-2">
								<MdiIcon name="mdiFileDocument" size={14} />
								<span class="font-mono">{file.filename}</span>
								<span style="color: var(--color-muted-foreground);">({formatSize(file.size)})</span>
							</div>
							<div class="flex items-center gap-1">
								<button onclick={() => downloadFile(file.filename)}
									class="p-1 rounded hover:bg-[var(--color-muted)]" title={t('backup.download')}>
									<MdiIcon name="mdiDownload" size={14} />
								</button>
								<button onclick={() => confirmDeleteFile = file.filename}
									class="p-1 rounded hover:bg-[var(--color-muted)]" title={t('common.delete')}
									style="color: var(--color-error-fg);">
									<MdiIcon name="mdiDelete" size={14} />
								</button>
							</div>
						</div>
					{/each}
				</div>
			{/if}
		</Card>
	</div>
{/if}

<!-- Confirm plaintext export -->
<ConfirmModal
	open={confirmExportOpen}
	title={t('backup.confirmExportTitle')}
	message={t('backup.confirmExportMessage')}
	confirmLabel={t('backup.exportBtn')}
	confirmIcon="mdiDownload"
	onconfirm={performExport}
	oncancel={() => confirmExportOpen = false}
/>

<!-- Confirm import -->
<ConfirmModal
	open={confirmImportOpen}
	title={t('backup.confirmImportTitle')}
	message={t('backup.confirmImportMessage')}
	confirmLabel={t('backup.importBtn')}
	confirmIcon="mdiUpload"
	onconfirm={performImport}
	oncancel={() => confirmImportOpen = false}
/>

<!-- Confirm delete file -->
<ConfirmModal
	open={!!confirmDeleteFile}
	title={t('common.delete')}
	message={confirmDeleteFile}
	onconfirm={() => deleteFile(confirmDeleteFile)}
	oncancel={() => confirmDeleteFile = ''}
/>

<!-- Post-restore modal: Apply now or later -->
<svelte:window onkeydown={postRestoreModalOpen ? (e) => { if (e.key === 'Escape') postRestoreModalOpen = false; } : undefined} />
{#if postRestoreModalOpen && pending?.pending}
	<div class="post-restore-backdrop"
		style="position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,0.5); backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center; padding: 1rem;"
		onclick={() => postRestoreModalOpen = false}
		onkeydown={(e) => { if (e.key === 'Escape') postRestoreModalOpen = false; }}
		role="presentation">
		<!-- svelte-ignore a11y_click_events_have_key_events -->
		<div role="dialog" aria-modal="true" aria-labelledby="post-restore-title" tabindex="-1"
			style="background: var(--color-card); border: 1px solid var(--color-border); border-radius: 1rem; padding: 1.5rem; max-width: 420px; width: 100%; box-shadow: 0 20px 60px rgba(0,0,0,0.4);"
			onclick={(e) => e.stopPropagation()}>
			<div class="flex items-start gap-3 mb-4">
				<div class="flex items-center justify-center w-10 h-10 rounded-full flex-shrink-0"
					style="background: var(--color-warning-bg); color: var(--color-warning-fg);">
					<MdiIcon name="mdiClockAlert" size={22} />
				</div>
				<div class="min-w-0">
					<h3 id="post-restore-title" class="font-semibold mb-1">{t('backup.restorePrepared')}</h3>
					<p class="text-sm break-words" style="color: var(--color-muted-foreground);">{t('backup.restoreApplyPrompt')}</p>
				</div>
			</div>
			<div class="flex gap-2 justify-end flex-wrap">
				<button onclick={() => postRestoreModalOpen = false}
					class="px-3 py-2 text-sm rounded-md border border-[var(--color-border)] hover:bg-[var(--color-muted)] transition-colors">
					{t('backup.applyLater')}
				</button>
				{#if pending.supervised}
					<Button size="sm" onclick={() => { postRestoreModalOpen = false; applyAndRestart(); }}>
						<MdiIcon name="mdiRestart" size={14} /> {t('backup.restartNow')}
					</Button>
				{/if}
			</div>
		</div>
	</div>
{/if}

<!-- Restarting overlay -->
{#if restartingOverlay}
	<div role="alert" aria-live="assertive"
		style="position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; backdrop-filter: blur(4px); padding: 1rem;">
		<div class="text-center p-6" style="color: var(--color-foreground);">
			<div class="restart-spinner" style="color: var(--color-primary); margin-bottom: 1rem;">
				<MdiIcon name="mdiRestart" size={40} />
			</div>
			<p class="text-lg font-semibold">{t('backup.restartingTitle')}</p>
			<p class="text-sm mt-2" style="color: var(--color-muted-foreground);">{t('backup.restartingDescription')}</p>
		</div>
	</div>
{/if}

<style>
	.restart-spinner {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 40px;
		height: 40px;
		animation: restart-spin 1.2s linear infinite;
		transform-origin: center center;
	}
	@keyframes restart-spin {
		from { transform: rotate(0deg); }
		to { transform: rotate(360deg); }
	}
</style>
