<template>
	<MkStickyContainer>
		<template #header
			><MkPageHeader
				:actions="headerActions"
				:tabs="headerTabs"
				:display-back-button="true"
		/></template>
		<MkSpacer :content-max="800" :margin-min="16" :margin-max="32">
			<div class="backup">
				<div class="backupText">
					<div class="backupTitle">サーバ全体バックアップ</div>
					<div class="backupDescription">
						データベース、設定ファイル、内部ストレージのファイルを
						.tar.gz としてサーバ上に作成します。
					</div>
				</div>
				<FormButton primary :disabled="backuping" @click="createBackup">
					{{ backuping ? "作成中..." : "バックアップを作成" }}
				</FormButton>
			</div>
			<div v-if="backupResult" class="backupResult">
				<MkKeyValue oneline>
					<template #key>ファイル名</template>
					<template #value>{{ backupResult.fileName }}</template>
				</MkKeyValue>
				<MkKeyValue oneline>
					<template #key>保存先</template>
					<template #value>{{ backupResult.path }}</template>
				</MkKeyValue>
				<MkKeyValue oneline>
					<template #key>サイズ</template>
					<template #value>{{ bytes(backupResult.size) }}</template>
				</MkKeyValue>
				<MkKeyValue oneline>
					<template #key>メディア</template>
					<template #value>{{
						backupResult.includedMedia ? "含まれています" : "含まれていません"
					}}</template>
				</MkKeyValue>
			</div>
			<FormSuspense
				v-slot="{ result: database }"
				:p="databasePromiseFactory"
			>
				<MkKeyValue
					v-for="table in database"
					:key="table[0]"
					oneline
					style="margin: 1em 0"
				>
					<template #key>{{ table[0] }}</template>
					<template #value
						>{{ bytes(table[1].size) }} ({{
							number(table[1].count)
						}}
						recs)</template
					>
				</MkKeyValue>
			</FormSuspense>
		</MkSpacer></MkStickyContainer
	>
</template>

<script lang="ts" setup>
import { computed, ref } from "vue";
import FormSuspense from "@/components/form/suspense.vue";
import FormButton from "@/components/MkButton.vue";
import MkKeyValue from "@/components/MkKeyValue.vue";
import * as os from "@/os";
import bytes from "@/filters/bytes";
import number from "@/filters/number";
import { i18n } from "@/i18n";
import { definePageMetadata } from "@/scripts/page-metadata";

type BackupResult = {
	path: string;
	fileName: string;
	size: number;
	includedMedia: boolean;
};

const backuping = ref(false);
const backupResult = ref<BackupResult | null>(null);

const databasePromiseFactory = () =>
	os
		.api("admin/get-table-stats")
		.then((res) =>
			Object.entries(res).sort((a, b) => b[1].size - a[1].size),
		);

async function createBackup() {
	const { canceled } = await os.confirm({
		type: "warning",
		title: "サーバ全体バックアップを作成しますか？",
		text: "作成中はデータベースとファイル容量に応じて時間がかかります。保存先はサーバ上の backups ディレクトリです。",
		okText: "作成",
	});
	if (canceled) return;

	backuping.value = true;
	try {
		backupResult.value = await os.apiWithDialog("admin/create-backup");
	} finally {
		backuping.value = false;
	}
}

const headerActions = computed(() => []);

const headerTabs = computed(() => []);

definePageMetadata({
	title: i18n.ts.database,
	icon: "ph-database ph-bold ph-lg",
});
</script>

<style lang="scss" scoped>
.backup {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 16px;
	padding-bottom: 16px;
	border-bottom: solid 1px var(--divider);
}

.backupText {
	min-width: 0;
}

.backupTitle {
	font-weight: 700;
}

.backupDescription {
	margin-top: 4px;
	color: var(--fgTransparentWeak);
	font-size: 0.9em;
	line-height: 1.5;
}

.backupResult {
	margin: 0 0 16px;
	padding-bottom: 16px;
	border-bottom: solid 1px var(--divider);
}

@media (max-width: 600px) {
	.backup {
		align-items: stretch;
		flex-direction: column;
	}
}
</style>
