<template>
	<div
		v-if="$appServer?.pg"
		class="grid grid-cols-1 items-start gap-5 sm:grid-cols-2"
	>
		<div
			v-for="server in !!$dbReplicaServer?.pg
				? ['Server', 'Database Server', 'Replication Server']
				: ['Server', 'Database Server']"
			class="col-span-1 rounded-md border lg:col-span-2"
		>
			<div class="grid grid-cols-2 lg:grid-cols-4">
				<template v-for="(d, i) in currentUsage(server)" :key="d.value">
					<div
						class="border-b p-5 lg:border-b-0"
						:class="{ 'border-r': i + 1 != currentUsage(server).length }"
					>
						<div
							v-if="d.type === 'header'"
							class="m-auto flex h-full items-center justify-between"
						>
							<div
								v-if="d.type === 'header'"
								class="mt-2 flex flex-col space-y-2"
							>
								<div class="text-base text-gray-700">{{ d.label }}</div>
								<div class="space-y-1">
									<div class="flex items-center text-base text-gray-900">
										{{ d.value }}
										<Tooltip v-if="d.isPremium" text="高级服务器">
											<!-- this icon isn't available in unplugin package yet -->
											<svg
												xmlns="http://www.w3.org/2000/svg"
												width="24"
												height="24"
												viewBox="0 0 24 24"
												fill="none"
												stroke="currentColor"
												stroke-width="2"
												stroke-linecap="round"
												stroke-linejoin="round"
												class="lucide lucide-circle-parking ml-2 h-4 w-4 text-gray-600"
											>
												<circle cx="12" cy="12" r="10" />
												<path d="M9 17V7h4a3 3 0 0 1 0 6H9" />
											</svg>
										</Tooltip>
									</div>
									<div class="flex space-x-1">
										<div class="text-sm text-gray-600" v-html="d.subValue" />
										<Tooltip v-if="d.help" :text="d.help">
											<i-lucide-info class="h-3.5 w-3.5 text-gray-500" />
										</Tooltip>
									</div>
								</div>
							</div>
							<Button
								v-if="d.type === 'header' && !$appServer.pg.is_self_hosted"
								@click="showPlanChangeDialog(server)"
								label="更改"
							/>
						</div>
						<div v-else-if="d.type === 'progress'">
							<div class="flex items-center justify-between space-x-2">
								<div class="text-base text-gray-700">{{ d.label }}</div>
								<div v-if="d.actions" class="flex space-x-2">
									<Button v-for="action in d.actions || []" v-bind="action" />
								</div>
								<div v-else class="h-8" />
							</div>
							<div class="mt-2">
								<Progress size="md" :value="d.progress_value || 0" />
								<div class="flex space-x-2">
									<div class="mt-2 flex justify-between">
										<div class="text-sm text-gray-600">
											{{ d.value }}
										</div>
									</div>
									<Tooltip v-if="d.help" :text="d.help">
										<i-lucide-info class="mt-2 h-4 w-4 text-gray-500" />
									</Tooltip>
								</div>
							</div>
						</div>
					</div>
				</template>
			</div>
		</div>

		<div class="rounded-md border">
			<div class="h-12 border-b px-5 py-4">
				<h2 class="text-lg font-medium text-gray-900">服务器信息</h2>
			</div>
			<div>
				<div
					v-for="d in serverInformation"
					:key="d.label"
					class="flex items-center px-5 py-3 last:pb-5 even:bg-gray-50/70"
				>
					<div class="w-1/3 text-base text-gray-700">{{ d.label }}</div>
<div class="w-2/3 text-base font-medium">{{ d.value }}</div>
				</div>
			</div>
		</div>

		<ServerLoadAverage :server="server" />
	</div>
</template>

<script>
import { toast } from 'vue-sonner';
import { h, defineAsyncComponent } from 'vue';
import { getCachedDocumentResource } from 'jingrow-ui';
import { confirmDialog, renderDialog } from '../../utils/components';
import { getToastErrorMessage } from '../../utils/toast';
import ServerPlansDialog from './ServerPlansDialog.vue';
import ServerLoadAverage from './ServerLoadAverage.vue';
import { getDocResource } from '../../utils/resource';

export default {
	props: ['server'],
	components: {
		ServerLoadAverage,
		ServerPlansDialog,
	},
	methods: {
		showPlanChangeDialog(serverType) {
			let ServerPlansDialog = defineAsyncComponent(
				() => import('./ServerPlansDialog.vue'),
			);
			renderDialog(
				h(ServerPlansDialog, {
					server:
						serverType === 'Server'
							? this.$appServer.name
							: this.$dbServer.name,
					serverType,
				}),
			);
		},
		currentUsage(serverType) {
			if (!this.$appServer?.pg) return [];
			if (!this.$dbServer?.pg) return [];

			let formatBytes = (v) => this.$format.bytes(v, 0, 2);

			let pg =
				serverType === 'Server'
					? this.$appServer.pg
					: serverType === 'Database Server'
						? this.$dbServer.pg
						: serverType === 'Replication Server'
							? this.$dbReplicaServer?.pg
							: null;

			if (!pg) return [];

			let currentPlan = pg.current_plan;
			let currentUsage = pg.usage;
			let diskSize = pg.disk_size;
			let additionalStorage = diskSize - (currentPlan?.disk || 0);
			let price = 0;
			// not using $format.planTitle cuz of manual calculation of add-on storage plan
			let priceField =
				this.$team.pg.currency === 'CNY' ? 'price_cny' : 'price_usd';

			let planDescription = '';
			if (!currentPlan?.name) {
				planDescription = '未选择计划';
			} else if (currentPlan.price_usd > 0) {
				price = currentPlan[priceField];
				planDescription = `${this.$format.userCurrency(price, 0)}/月`;
			} else {
				planDescription = currentPlan.plan_title;
			}

			return [
				{
					label:
						serverType === 'Server'
							? '应用服务器计划'
							: serverType === 'Database Server'
								? '数据库服务器计划'
								: '复制服务器计划',
					value: planDescription,
					subValue:
						additionalStorage > 0
							? `${this.$format.userCurrency(
									pg.storage_plan[priceField] * additionalStorage,
									0,
								)}/月`
							: '',
					type: 'header',
					isPremium: !!currentPlan?.premium,
					help:
						additionalStorage > 0
							? `服务器计划: ${this.$format.userCurrency(
									currentPlan[priceField],
								)}/月 & 附加存储计划: ${this.$format.userCurrency(
									pg.storage_plan[priceField] * additionalStorage,
								)}/月`
							: '',
				},
				{
					label: 'CPU',
					type: 'progress',
					progress_value: currentPlan
						? (currentUsage.vcpu / currentPlan.vcpu) * 100
						: 0,
					value: currentPlan
						? `${(((currentUsage.vcpu || 0) / currentPlan.vcpu) * 100).toFixed(
								2,
							)}% of ${currentPlan.vcpu} ${this.$format.plural(
								currentPlan.vcpu,
								'vCPU',
								'vCPUs',
							)}`
						: '0% vCPU',
				},
				{
					label: '内存',
					type: 'progress',
					progress_value: currentPlan
						? (currentUsage.memory / currentPlan.memory) * 100
						: 0,
					value: currentPlan
						? `${formatBytes(currentUsage.memory || 0)} of ${formatBytes(
								currentPlan.memory,
							)}`
						: formatBytes(currentUsage.memory || 0),
				},
				{
					label: '存储',
					type: 'progress',
					progress_value: currentPlan
						? (currentUsage.disk / (diskSize ? diskSize : currentPlan.disk)) *
100
						: 0,
					value: currentPlan
						? `${currentUsage.disk || 0} GB 共 ${
								diskSize ? diskSize : currentPlan.disk
							} GB`
						: `${currentUsage.disk || 0} GB`,
					help:
						diskSize - (currentPlan?.disk || 0) > 0
							? `附加存储: ${diskSize - (currentPlan?.disk || 0)} GB`
							: '',
					actions: [
						{
							label: '增加存储',
							icon: 'plus',
							variant: 'ghost',
							onClick: () => {
								confirmDialog({
									title: '增加存储',
									message: `输入您想要为服务器 <b>${
										pg.title || pg.name
									}</b> 增加的磁盘大小<div class="rounded mt-4 p-2 text-sm text-gray-700 bg-gray-100 border">您将按 <b>${this.$format.userCurrency(
										pg.storage_plan[priceField],
									)}/月</b> 的费率支付每增加 1GB 存储的费用。</div><p class="mt-4 text-sm text-gray-700"><strong>注意</strong>: 您只能在 6 小时内增加一次服务器的存储大小。</div>`,
									fields: [
										{
											fieldname: 'storage',
											type: 'select',
											default: 50,
											label: '存储 (GB)',
											variant: 'outline',
											// options from 5 GB to 500 GB in steps of 5 GB
											options: Array.from({ length: 100 }, (_, i) => ({
												label: `${(i + 1) * 5} GB`,
												value: (i + 1) * 5,
											})),
										},
									],
									onSuccess: ({ hide, values }) => {
										toast.promise(
											this.$appServer.increaseDiskSize.submit(
												{
													server: pg.name,
													increment: Number(values.storage),
												},
												{
													onSuccess: () => {
														hide();
														this.$router.push({
															name: '服务器详情页面',
															params: { name: this.$appServer.name },
														});
													},
													onError(e) {
														console.error(e);
													},
												},
											),
											{
												loading: '正在增加磁盘大小...',
												success: '磁盘大小已计划增加',
												error: (e) =>
													getToastErrorMessage(
														e,
														'增加磁盘大小失败',
													),
											},
										);
									},
								});
							},
						},
						{
							label: '配置自动增加存储',
							icon: 'tool',
							variant: 'ghost',
							onClick: () => {
								confirmDialog({
									title: '配置自动增加存储',
									message: `<div class="rounded my-4 p-2 text-sm text-gray-700 bg-gray-100 border">

									当可用存储达到容量的 <b>90%</b> 以上时，此功能会自动增加可用存储。默认情况下启用此功能以避免服务器/站点停机。

									<br><br>
									您可以通过将下面的最小值和最大值设置为 <b>0 GB</b> 来完全禁用此功能。但如果您这样做，<strong>我们可能无法收到来自此服务器的事件通知</strong>。

									<br><br>
									<strong>注意</strong>: 存储只能在 6 小时内自动增加一次。


									</div>输入要为服务器 <b>${
										pg.title || pg.name
									}</b> 增加的最大和最小存储量。`,
									fields: [
										{
											fieldname: 'min',
											type: 'select',
											default: String(pg.auto_add_storage_min),
											label: '最小存储增加 (GB)',
											variant: 'outline',
											// options from 5 GB to 250 GB in steps of 5 GB
											options: Array.from({ length: 51 }, (_, i) => ({
												label: `${i * 5} GB`,
												value: i * 5,
											})),
										},
										{
											fieldname: 'max',
											type: 'select',
											default: String(pg.auto_add_storage_max),
											label: '最大存储增加 (GB)',
											variant: 'outline',
											// options from 5 GB to 250 GB in steps of 5 GB
											options: Array.from({ length: 51 }, (_, i) => ({
												label: `${i * 5} GB`,
												value: i * 5,
											})),
										},
									],
									onSuccess: ({ hide, values }) => {
										toast.promise(
											this.$appServer.configureAutoAddStorage.submit(
{
													server: pg.name,
													min: Number(values.min),
													max: Number(values.max),
												},
												{
													onSuccess: () => {
														hide();

														if (pg.name === this.$appServer.name)
															this.$appServer.reload();
														else if (pg.name === this.$dbServer.name)
															this.$dbServer.reload();
														else if (pg.name === this.$replicationServer.name)
															this.$replicationServer.reload();
													},
												},
											),
											{
												loading: '正在配置自动扩容存储...',
												success: '自动扩容存储已配置',
												error: (err) => {
													return err.messages.length
														? err.messages.join('/n')
														: err.message ||
																'配置自动扩容存储失败';
												},
											},
										);
									},
								});
							},
						},
					],
				},
			];
		},
	},
	computed: {
		serverInformation() {
			return [
				{
					label: '应用服务器',
					value: this.$appServer.pg.name,
				},
				{
					label: '数据库服务器',
					value: this.$appServer.pg.database_server,
				},
				{
					label: '复制服务器',
					value: this.$appServer.pg.replication_server,
				},
				{
					label: '所有者',
					value: this.$appServer.pg.owner_email || this.$appServer.pg.team,
				},
				{
					label: '创建者',
					value: this.$appServer.pg.owner,
				},
				{
					label: '创建时间',
					value: this.$format.date(this.$appServer.pg.creation),
				},
			].filter((d) => d.value);
		},
		$appServer() {
			return getCachedDocumentResource('Server', this.server);
		},
		$dbServer() {
			return getDocResource({
				pagetype: 'Database Server',
				name: this.$appServer.pg.database_server,
				whitelistedMethods: {
					changePlan: 'change_plan',
					reboot: 'reboot',
					rename: 'rename',
				},
			});
		},
		$dbReplicaServer() {
			return getDocResource({
				pagetype: 'Database Server',
				name: this.$appServer.pg.replication_server,
				whitelistedMethods: {
					changePlan: 'change_plan',
					reboot: 'reboot',
					rename: 'rename',
				},
			});
		},
	},
};
</script>