<template>
	<div>
		<DismissableBanner
			v-if="$releaseGroup.pg.eol_versions.includes($releaseGroup.pg.version)"
			class="col-span-1 lg:col-span-2"
			title="您的站点使用的是已终止支持的版本。请升级到最新版本以获取最新功能和安全更新。"
			:id="`${$releaseGroup.name}-eol`"
			type="gray"
		>
			<Button
				class="ml-auto"
				variant="outline"
				link="https://jingrow.com/docs/sites/version-upgrade"
			>
				立即升级
			</Button>
		</DismissableBanner>
		<ObjectList class="mt-3" :options="listOptions" />
		<Dialog
			v-model="showAppVersionDialog"
			:options="{
				title: `${$releaseGroup.getAppVersions.params?.args.bench} 中的应用`,
				size: '6xl',
			}"
		>
			<template #body-content>
				<ObjectList :options="appVersionOptions" />
			</template>
		</Dialog>
	</div>
</template>
<script lang="jsx">
import Badge from '@/components/global/Badge.vue';
import { createResource, getCachedDocumentResource, Tooltip } from 'jingrow-ui';
import { defineAsyncComponent, h } from 'vue';
import { toast } from 'vue-sonner';
import ActionButton from '../components/ActionButton.vue';
import SSHCertificateDialog from '../components/group/SSHCertificateDialog.vue';
import ObjectList from '../components/ObjectList.vue';
import {
	getSitesTabColumns,
	sitesTabRoute,
	siteTabFilterControls,
} from '../objects/common';
import { confirmDialog, icon, renderDialog } from '../utils/components';
import { getToastErrorMessage } from '../utils/toast';
import DismissableBanner from '../components/DismissableBanner.vue';

export default {
	name: 'ReleaseGroupBenchSites',
	props: ['releaseGroup'],
	components: { ObjectList, DismissableBanner },
	data() {
		return {
			showAppVersionDialog: false,
			sitesGroupedByBench: [],
		};
	},
	resources: {
		benches() {
			return {
				type: 'list',
				pagetype: 'Bench',
				filters: {
					group: this.$releaseGroup.name,
					skip_team_filter_for_system_user_and_support_agent: true,
				},
				fields: ['name', 'status'],
				orderBy: 'creation desc',
				pageLength: 99999,
				auto: true,
				onSuccess() {
					this.$resources.sites.fetch();
				},
			};
		},
		sites() {
			return {
				type: 'list',
				pagetype: 'Site',
				filters: {
					group: this.$releaseGroup.name,
					skip_team_filter_for_system_user_and_support_agent: true,
				},
				fields: [
					'name',
					'status',
					'bench',
					'host_name',
					'plan.plan_title as plan_title',
					'plan.price_usd as price_usd',
					'plan.price_cny as price_cny',
					'cluster.image as cluster_image',
					'cluster.title as cluster_title',
				],
				orderBy: 'creation desc, bench desc',
				pageLength: 99999,
				transform(data) {
					return this.groupSitesByBench(data);
				},
				auto: false,
			};
		},
	},
	computed: {
		listOptions() {
			return {
				list: this.$resources.sites,
				groupHeader: ({ group: bench }) => {
					if (!bench?.status) return;

					const options = this.benchOptions(bench);
					const IconHash = icon('hash', 'w-3 h-3');
					const IconStar = icon('star', 'w-3 h-3');
					return (
						<div class="flex items-center">
							<Tooltip text="查看工作台详情">
								<a
									class="cursor-pointer text-base font-medium leading-6 text-gray-900"
									href={`/dashboard/benches/${bench.name}`}
								>
									{bench.group}
								</a>
							</Tooltip>
							{bench.status != 'Active' ? (
								<Badge class="ml-4" label={bench.status} />
							) : null}
							{bench.has_app_patch_applied && (
								<Tooltip text="此工作台中的应用可能已被修补">
									<a
										class="ml-2 rounded bg-gray-100 p-1 text-gray-700"
										href="https://jingrow.com/docs/benches/app-patches"
										target="_blank"
									>
										<IconHash />
</a>
								</Tooltip>
							)}
							{bench.has_updated_inplace && (
								<Tooltip text="此工作台已就地更新">
									<a
										class="ml-2 rounded bg-gray-100 p-1 text-gray-700"
										href="https://jingrow.com/docs/in-place-updates"
										target="_blank"
									>
										<IconStar />
									</a>
								</Tooltip>
							)}
							<ActionButton class="ml-auto" options={options} />
						</div>
					);
				},
				emptyStateMessage: this.$releaseGroup.pg.deploy_information.last_deploy
					? '未找到站点'
					: '请先创建部署以开始创建站点',
				columns: getSitesTabColumns(false),
				filterControls: siteTabFilterControls,
				route: sitesTabRoute,
				primaryAction: () => {
					return {
						label: '新建站点',
						slots: {
							prefix: icon('plus', 'w-4 h-4'),
						},
						disabled: !this.$releaseGroup.pg?.deploy_information?.last_deploy,
						route: {
							name: 'Release Group New Site',
							params: { bench: this.releaseGroup },
						},
					};
				},
			};
		},
		appVersionOptions() {
			return {
				columns: [
					{
						label: '应用',
						fieldname: 'app',
					},
					{
						label: '仓库',
						fieldname: 'repository',
						format(value, row) {
							return `${row.repository_owner}/${row.repository}`;
						},
						link: (value, row) => {
							return row.repository_url;
						},
					},
					{
						label: '分支',
						fieldname: 'branch',
						type: 'Badge',
					},
					{
						label: '提交',
						fieldname: 'hash',
						type: 'Badge',
						format(value, row) {
							return value.slice(0, 7);
						},
						link: (value, row) => {
							return `https://github.com/${row.repository_owner}/${row.repository}/commit/${value}`;
						},
					},
					{
						label: '标签',
						fieldname: 'tag',
						type: 'Badge',
					},
				],
				data: () => this.$releaseGroup.getAppVersions.data,
			};
		},
		$releaseGroup() {
			return getCachedDocumentResource('Release Group', this.releaseGroup);
		},
	},
	methods: {
		groupSitesByBench(data) {
			if (!this.$resources.benches.data) return [];
			return this.$resources.benches.data.map((bench) => {
				let sites = (data || []).filter((site) => site.bench === bench.name);
				return {
					...bench,
					collapsed: false,
					group: bench.name,
					rows: sites,
				};
			});
		},
		benchOptions(bench) {
			if (!bench) return [];

			return [
				{
					label: '在桌面查看',
					condition: () => this.$team?.pg?.is_desk_user,
					onClick: () =>
						window.open(
							`${window.location.protocol}//${window.location.host}/app/bench/${bench.name}`,
							'_blank',
						),
				},
				{
					label: '显示应用',
					onClick: () => {
						toast.promise(
							this.$releaseGroup.getAppVersions
								.submit({ bench: bench.name })
								.then(() => {
									this.showAppVersionDialog = true;
								}),
							{
								loading: '正在获取应用...',
								success: '已获取应用及其版本',
								error: '获取应用失败',
								duration: 1000,
							},
						);
					},
				},
				{
					label: 'SSH 访问',
					condition: () => bench.status === 'Active',
					onClick: () => {
						renderDialog(
							h(SSHCertificateDialog, {
								bench: bench.name,
								releaseGroup: this.$releaseGroup.name,
							}),
						);
					},
				},
				{
					label: '查看日志',
					condition: () => bench.status === 'Active',
					onClick: () => {
						let BenchLogsDialog = defineAsyncComponent(
							() => import('../components/group/BenchLogsDialog.vue'),
						);

						renderDialog(
							h(BenchLogsDialog, {
								bench: bench.name,
							}),
						);
					},
				},
				{
					label: '更新所有站点',
condition: () => bench.status === 'Active' && bench.rows.length > 0,
					onClick: () => {
						confirmDialog({
							title: '更新所有站点',
							message: `您确定要将工作台 <b>${bench.name}</b> 中的所有站点更新到最新版本吗？`,
							primaryAction: {
								label: '更新',
								variant: 'solid',
								onClick: ({ hide }) => {
									toast.promise(
										this.runBenchMethod(bench.name, 'update_all_sites'),
										{
											loading: '正在为站点安排更新...',
											success: () => {
												hide();
												return '站点已安排更新';
											},
											error: (e) => {
												hide();
												return getToastErrorMessage(
													e,
													'更新站点失败',
												);
											},
											duration: 1000,
										},
									);
								},
							},
						});
					},
				},
				{
					label: '重启工作台',
					condition: () => bench.status === 'Active',
					onClick: () => {
						confirmDialog({
							title: '重启工作台',
							message: `您确定要重启工作台 <b>${bench.name}</b> 吗？`,
							primaryAction: {
								label: '重启',
								variant: 'solid',
								theme: 'red',
								onClick: ({ hide }) => {
									toast.promise(this.runBenchMethod(bench.name, 'restart'), {
										loading: '正在重启工作台...',
										success: () => {
											hide();
											return '工作台将很快重启';
										},
										error: (e) => {
											hide();
											return getToastErrorMessage(e, '重启工作台失败');
										},
										duration: 1000,
									});
								},
							},
						});
					},
				},
				{
					label: '重建资源',
					condition: () =>
						bench.status === 'Active' &&
						(Number(this.$releaseGroup.pg.version.split(' ')[1]) > 13 ||
							this.$releaseGroup.pg.version === 'Nightly'),
					onClick: () => {
						confirmDialog({
							title: '重建资源',
							message: `您确定要为工作台 <b>${bench.name}</b> 重建资源吗？`,
							primaryAction: {
								label: '重建',
								variant: 'solid',
								theme: 'red',
								onClick: ({ hide }) => {
									toast.promise(this.runBenchMethod(bench.name, 'rebuild'), {
										loading: '正在重建资源...',
										success: () => {
											hide();
											return '资源将在后台重建。这可能需要几分钟时间。';
										},
										error: (e) => {
											hide();
											return getToastErrorMessage(
												e,
												'重建资源失败',
											);
										},
										duration: 1000,
									});
								},
							},
						});
					},
				},
				{
					label: '归档工作台',
					onClick: () => {
						confirmDialog({
							title: '归档工作台',
							message: `您确定要归档工作台 <b>${bench.name}</b> 吗？`,
							primaryAction: {
								label: '归档',
								variant: 'solid',
								theme: 'red',
								onClick: ({ hide }) => {
									toast.promise(this.runBenchMethod(bench.name, 'archive'), {
										loading: '正在安排工作台归档...',
										success: () => {
											hide();
											return '工作台已安排归档';
										},
										error: (e) =>
											getToastErrorMessage(e, '归档工作台失败'),
									});
								},
							},
						});
					},
				},
				{
					label: '查看进程',
					condition: () => bench.status === 'Active',
					onClick: () => {
						let SupervisorProcessesDialog = defineAsyncComponent(
							() => import('../components/group/SupervisorProcessesDialog.vue'),
						);

						renderDialog(
							h(SupervisorProcessesDialog, {
								bench: bench.name,
							}),
						);
					},
				},
			];
		},
		runBenchMethod(name, methodName) {
			const method = createResource({
				url: 'jcloud.api.client.run_pg_method',
			});
			return method.submit({
				dt: 'Bench',
				dn: name,
				method: methodName,
			});
		},
	},
};
</script>