import {
	createListResource,
	createResource,
	LoadingIndicator,
} from 'jingrow-ui';
import { defineAsyncComponent, h } from 'vue';
import { unparse } from 'papaparse';
import { toast } from 'vue-sonner';
import AddDomainDialog from '../components/AddDomainDialog.vue';
import GenericDialog from '../components/GenericDialog.vue';
import ObjectList from '../components/ObjectList.vue';
import SiteActions from '../components/SiteActions.vue';
import { getTeam, switchToTeam } from '../data/team';
import router from '../router';
import { getRunningJobs } from '../utils/agentJob';
import { confirmDialog, icon, renderDialog } from '../utils/components';
import dayjs from '../utils/dayjs';
import { bytes, date, userCurrency, getStatusLabel, getDeployTypeLabel } from '../utils/format';
import { getToastErrorMessage } from '../utils/toast';
import { getDocResource } from '../utils/resource';
import { trialDays } from '../utils/site';
import { clusterOptions, getUpsellBanner } from './common';
import { getAppsTab } from './common/apps';
import { isMobile } from '../utils/device';
import { getJobsTab } from './common/jobs';

export default {
	pagetype: 'Site',
	whitelistedMethods: {
		activate: 'activate',
		addDomain: 'add_domain',
		archive: 'archive',
		backup: 'backup',
		clearSiteCache: 'clear_site_cache',
		deactivate: 'deactivate',
		disableReadWrite: 'disable_read_write',
		enableReadWrite: 'enable_read_write',
		installApp: 'install_app',
		uninstallApp: 'uninstall_app',
		migrate: 'migrate',
		moveToBench: 'move_to_bench',
		moveToGroup: 'move_to_group',
		loginAsAdmin: 'login_as_admin',
		loginAsTeam: 'login_as_team',
		isSetupWizardComplete: 'is_setup_wizard_complete',
		reinstall: 'reinstall',
		removeDomain: 'remove_domain',
		redirectToPrimary: 'set_redirect',
		removeRedirect: 'unset_redirect',
		setPrimaryDomain: 'set_host_name',
		restoreSite: 'restore_site',
		restoreSiteFromFiles: 'restore_site_from_files',
		scheduleUpdate: 'schedule_update',
		editScheduledUpdate: 'edit_scheduled_update',
		cancelUpdate: 'cancel_scheduled_update',
		setPlan: 'set_plan',
		updateConfig: 'update_config',
		deleteConfig: 'delete_config',
		sendTransferRequest: 'send_change_team_request',
		addTag: 'add_resource_tag',
		removeTag: 'remove_resource_tag',
		getBackupDownloadLink: 'get_backup_download_link',
		fetchDatabaseTableSchemas: 'fetch_database_table_schemas',
	},
	list: {
		route: '/sites',
		title: '站点',
		fields: [
			'plan.plan_title as plan_title',
			'plan.price_usd as price_usd',
			'plan.price_cny as price_cny',
			'group.title as group_title',
			'group.public as group_public',
			'group.team as group_team',
			'group.version as version',
			'cluster.image as cluster_image',
			'cluster.title as cluster_title',
			'trial_end_date',
			'site_end_date',
		],
		orderBy: 'creation desc',
		searchField: 'host_name',
		filterControls() {
			return [
				{
					type: 'select',
					label: '状态',
					fieldname: 'status',
					options: [
						{ label: '', value: '' },
						{ label: '激活', value: 'Active' },
						{ label: '未激活', value: 'Inactive' },
						{ label: '已暂停', value: 'Suspended' },
						{ label: '损坏', value: 'Broken' },
						{ label: '已归档', value: 'Archived' },
					],
				},
				{
					type: 'link',
					label: '版本',
					fieldname: 'group.version',
					options: {
						pagetype: 'Jingrow Version',
					},
				},
				{
					type: 'link',
					label: '站点分组',
					fieldname: 'group',
					options: {
						pagetype: 'Release Group',
					},
				},
				{
					type: 'select',
					label: '区域',
					fieldname: 'cluster',
					options: clusterOptions,
				},
				{
					type: 'link',
					label: '标签',
					fieldname: 'tags.tag',
					options: {
						pagetype: 'Jcloud Tag',
						filters: {
							pagetype_name: 'Site',
						},
					},
				},
			];
		},
		columns: [
			{
				label: '站点',
				fieldname: 'host_name',
				width: 1.5,
				class: 'font-medium',
				format(value, row) {
					return value || row.name;
				},
			},
			{
				label: '状态',
				fieldname: 'status',
				type: 'Badge',
				width: '140px',
				format(value) {
					const statusMap = {
						'Active': '激活',
						'Inactive': '未激活',
						'Suspended': '已暂停',
						'Broken': '损坏',
						'Archived': '已归档',
						'Pending': '待处理',
						'Installing': '安装中',
						'Update Available': '可更新',
						'Running': '运行中',
						'Success': '成功',
						'Failure': '失败'
					};
					return statusMap[value] || value;
				}
			},
			{
				label: '计划',
				fieldname: 'plan',
				width: 0.85,
				format(value, row) {
					if (row.trial_end_date) {
						return trialDays(row.trial_end_date);
					}
					const $team = getTeam();
					if (row.price_usd > 0) {
						const china = $team.pg?.currency === 'CNY';
						const formattedValue = userCurrency(
							china ? row.price_cny : row.price_usd,
							0,
						);
						return `${formattedValue}/月`;
					}
					return row.plan_title;
				},
			},
			{
				label: '区域',
				fieldname: 'cluster',
				width: 1,
				format(value, row) {
					return row.cluster_title || value;
				},
				prefix(row) {
					return h('img', {
						src: row.cluster_image,
						class: 'w-4 h-4',
						alt: row.cluster_title,
					});
				},
			},
			{
				label: '站点分组',
				fieldname: 'group',
				width: '15rem',
				format(value, row) {
					return row.group_public ? '公域' : row.group_title || value;
				},
			},
			{
				label: '版本',
				fieldname: 'version',
				width: 0.5,
			},
			{
				label: '到期时间',
				fieldname: 'site_end_date',
				width: 1,
				format(value) {
					return value ? date(value, 'YYYY-MM-DD') : '';
				},
			},
		],
		primaryAction({ listResource: sites }) {
			return {
				label: '新建站点',
				variant: 'solid',
				slots: {
					prefix: icon('plus'),
				},
				onClick() {
					router.push({ name: 'New Site' });
				},
			};
		},
		moreActions({ listResource: sites }) {
			return [
				{
					label: '导出为CSV',
					icon: 'download',
					onClick() {
						const fields = [
							'host_name',
							'plan_title',
							'cluster_title',
							'group_title',
							'version',
						];

						const data = sites.data.map((site) => {
							const row = {};
							fields.forEach((field) => {
								row[field] = site[field];
							});
							return row;
						});

						let csv = unparse({
							fields,
							data,
						});
						csv = '\uFEFF' + csv; // for utf-8

						// create a blob and trigger a download
						const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
						const today = new Date().toISOString().split('T')[0];
						const filename = `sites-${today}.csv`;
						const link = document.createElement('a');
						link.href = URL.createObjectURL(blob);
						link.download = filename;
						link.click();
						URL.revokeObjectURL(link.href);
					},
				},
			];
		},
	},
	detail: {
		titleField: 'name',
		route: '/sites/:name',
		statusBadge({ documentResource: site }) {
			const statusMap = {
				'Active': '激活',
				'Inactive': '未激活',
				'Suspended': '已暂停',
				'Broken': '损坏',
				'Archived': '已归档',
				'Pending': '待处理',
				'Installing': '安装中',
				'Running': '运行中',
				'Success': '成功',
				'Failure': '失败'
			};
			return { label: statusMap[site.pg.status] || site.pg.status };
		},
		breadcrumbs({ items, documentResource: site }) {
			let breadcrumbs = [];
			let $team = getTeam();
			let siteCrumb = {
				label: site.pg.host_name || site.pg?.name,
				route: `/sites/${site.pg?.name}`,
			};

			if (
				(site.pg.server_team == $team.pg?.name &&
					site.pg.group_team == $team.pg?.name) ||
				$team.pg?.is_desk_user
			) {
				breadcrumbs.push({
					label: site.pg?.server_title || site.pg?.server,
					route: `/servers/${site.pg?.server}`,
				});
			}
			if (
				site.pg.group_team == $team.pg?.name ||
				$team.pg?.is_desk_user ||
				$team.pg?.is_support_agent
			) {
				breadcrumbs.push(
					{
						label: site.pg?.group_title,
						route: `/groups/${site.pg?.group}`,
					},
					siteCrumb,
				);
			} else {
				breadcrumbs.push(...items.slice(0, -1), siteCrumb);
			}
			return breadcrumbs;
		},
		tabs: [
			{
				label: '概览',
				icon: icon('home'),
				route: 'overview',
				type: 'Component',
				condition: (site) => site.pg?.status !== 'Archived',
				component: defineAsyncComponent(
					() => import('../components/SiteOverview.vue'),
				),
				props: (site) => {
					return { site: site.pg?.name };
				},
			},
			getAppsTab(true),
			{
				label: '域名',
				icon: icon('external-link'),
				route: 'domains',
				type: 'list',
				condition: (site) => site.pg?.status !== 'Archived',
				list: {
					pagetype: 'Site Domain',
					fields: ['redirect_to_primary'],
					filters: (site) => {
						return { site: site.pg?.name };
					},
					columns: [
						{
							label: '域名',
							fieldname: 'domain',
						},
						{
							label: '状态',
							fieldname: 'status',
							type: 'Badge',
							format(value) {
								const statusMap = {
									'Active': '激活',
									'Inactive': '未激活',
									'Suspended': '已暂停',
									'Broken': '损坏',
									'Archived': '已归档',
									'Pending': '待处理',
									'Installing': '安装中',
									'Running': '运行中',
									'Success': '成功',
									'Failure': '失败'
								};
								return statusMap[value] || value;
							}
						},
						{
							label: '主域名',
							fieldname: 'primary',
							type: 'Icon',
							Icon(value) {
								return value ? 'check' : '';
							},
						},
						{
							label: 'DNS 类型',
							fieldname: 'dns_type',
							type: 'Badge',
						},
					],
					banner({ documentResource: site }) {
						if (site.pg.broken_domain_error) {
							return {
								title:
									'获取您的域名的 HTTPS 证书时出错。',
								type: 'error',
								button: {
									label: '查看错误',
									variant: 'outline',
									onClick() {
										renderDialog(
											h(
												GenericDialog,
												{
													options: {
														title: '获取证书时出错',
														size: 'xl',
													},
												},
												{
													default: () => {
														return h('pre', {
															class:
																'whitespace-pre-wrap text-sm rounded border-2 p-3 border-gray-200 bg-gray-100',
															innerHTML: site.pg.broken_domain_error,
														});
													},
												},
											),
										);
									},
								},
							};
						} else {
							return null;
						}
					},
					primaryAction({ listResource: domains, documentResource: site }) {
						return {
							label: '添加域名',
							slots: {
								prefix: icon('plus'),
							},
							onClick() {
								renderDialog(
									h(AddDomainDialog, {
										site: site.pg,
										onDomainAdded() {
											domains.reload();
										},
									}),
								);
							},
						};
					},
					rowActions({ row, listResource: domains, documentResource: site }) {
						return [
							{
								label: '移除',
								condition: () => row.domain !== site.pg?.name,
								onClick() {
									confirmDialog({
										title: `移除域名`,
										message: `您确定要从站点 <b>${site.pg?.name}</b> 中移除域名 <b>${row.domain}</b> 吗？`,
										onSuccess({ hide }) {
											if (site.removeDomain.loading) return;
											toast.promise(
												site.removeDomain.submit({
													domain: row.domain,
												}),
												{
													loading: '正在移除域名...',
													success: () => {
														hide();
														return '域名已移除';
													},
													error: (e) => getToastErrorMessage(e),
												},
											);
										},
									});
								},
							},
							{
								label: '设为主域名',
								condition: () => !row.primary && row.status === 'Active',
								onClick() {
									confirmDialog({
										title: `设为主域名`,
										message: `您确定要将域名 <b>${row.domain}</b> 设为站点 <b>${site.pg?.name}</b> 的主域名吗？`,
										onSuccess({ hide }) {
											if (site.setPrimaryDomain.loading) return;
											toast.promise(
												site.setPrimaryDomain.submit({
													domain: row.domain,
												}),
												{
													loading: '正在设置主域名...',
													success: () => {
														hide();
														return '主域名已设置';
													},
													error: (e) => getToastErrorMessage(e),
												},
											);
										},
									});
								},
							},
							{
								label: '重定向到主域名',
								condition: () =>
									!row.primary &&
									!row.redirect_to_primary &&
									row.status === 'Active',
								onClick() {
									confirmDialog({
										title: `重定向域名`,
										message: `您确定要将域名 <b>${row.domain}</b> 重定向到站点 <b>${site.pg?.name}</b> 的主域名吗？`,
										onSuccess({ hide }) {
											if (site.redirectToPrimary.loading) return;
											toast.promise(
												site.redirectToPrimary.submit({
													domain: row.domain,
												}),
												{
													loading: '正在重定向域名...',
													success: () => {
														hide();
														return '域名已重定向';
													},
													error: (e) => getToastErrorMessage(e),
												},
											);
										},
									});
								},
							},
							{
								label: '移除重定向',
								condition: () =>
									!row.primary &&
									row.redirect_to_primary &&
									row.status === 'Active',
								onClick() {
									confirmDialog({
										title: `移除重定向`,
										message: `您确定要移除从域名 <b>${row.domain}</b> 到站点 <b>${site.pg?.name}</b> 主域名的重定向吗？`,
										onSuccess({ hide }) {
											if (site.removeRedirect.loading) return;
											toast.promise(
												site.removeRedirect.submit({
													domain: row.domain,
												}),
												{
													loading: '正在移除重定向...',
													success: () => {
														hide();
														return '重定向已移除';
													},
													error: (e) => getToastErrorMessage(e),
												},
											);
										},
									});
								},
							},
						];
					},
				},
			},
			{
				label: '备份',
				icon: icon('archive'),
				route: 'backups',
				type: 'list',
				list: {
					pagetype: 'Site Backup',
					filters: (site) => {
						return {
							site: site.pg?.name,
							files_availability: 'Available',
							status: ['in', ['Pending', 'Running', 'Success']],
						};
					},
					orderBy: 'creation desc',
					fields: [
						'job',
						'status',
						'database_url',
						'public_url',
						'private_url',
						'config_file_url',
						'site',
						'remote_database_file',
						'remote_public_file',
						'remote_private_file',
						'remote_config_file',
						'physical',
					],
					columns: [
						{
							label: '时间戳',
							fieldname: 'creation',
							width: 1,
							format(value) {
								return `备份于 ${date(value, 'llll')}`;
							},
						},

						{
							label: '数据库',
							fieldname: 'database_size',
							width: 0.5,
							format(value) {
								return value ? bytes(value) : '';
							},
						},
						{
							label: '公共文件',
							fieldname: 'public_size',
							width: 0.5,
							format(value) {
								return value ? bytes(value) : '';
							},
						},
						{
							label: '私有文件',
							fieldname: 'private_size',
							width: 0.5,
							format(value) {
								return value ? bytes(value) : '';
							},
						},
						{
							label: '包含文件的备份',
							fieldname: 'with_files',
							type: 'Icon',
							width: 0.5,
							Icon(value) {
								return value ? 'check' : '';
							},
						},
						{
							label: '异地备份',
							fieldname: 'offsite',
							width: 0.5,
							type: 'Icon',
							Icon(value) {
								return value ? 'check' : '';
							},
						},
					],
					filterControls() {
						return [
							{
								type: 'checkbox',
								label: '异地备份',
								fieldname: 'offsite',
							},
						];
					},
					rowActions({ row, documentResource: site }) {
						if (row.status != 'Success') return;

						function getFileName(file) {
							if (file == 'database') return 'database';
							if (file == 'public') return 'public files';
							if (file == 'private') return 'private files';
							if (file == 'config') return 'config file';
						}

						function confirmDownload(backup, file) {
							confirmDialog({
								title: '下载备份',
								message: `您将下载站点 <b>${
									site.pg?.host_name || site.pg?.name
								}</b> 的 ${getFileName(file)} 备份，该备份创建于 ${date(backup.creation, 'llll')}。${
									!backup.offsite
										? '<br><br><div class="p-2 bg-gray-100 border-gray-200 rounded">您需要以 <b>系统管理员</b> 身份登录 <em>您的站点</em> 才能下载备份。<div>'
										: ''
								}`,
								onSuccess() {
									downloadBackup(backup, file);
								},
							});
						}

						async function downloadBackup(backup, file) {
							// file: database, public, or private
							if (backup.offsite) {
								site.getBackupDownloadLink.submit(
									{ backup: backup.name, file },
									{
										onSuccess(r) {
											// TODO: fix this in documentResource, it should return message directly
											if (r.message) {
												window.open(r.message);
											}
										},
									},
								);
							} else {
								const url =
									file == 'config'
										? backup.config_file_url
										: backup[file + '_url'];

								const domainRegex = /^(https?:\/\/)?([^/]+)\/?/;
								const newUrl = url.replace(
									domainRegex,
									`$1${site.pg.host_name}/`,
								);
								window.open(newUrl);
							}
						}

						return [
							{
								group: '详情',
								items: [
									{
										label: '查看任务',
										onClick() {
											router.push({
												name: 'Site Job',
												params: { name: site.name, id: row.job },
											});
										},
									},
								],
							},
							{
								group: '下载',
								items: [
									{
										label: '下载数据库',
										onClick() {
											return confirmDownload(row, 'database');
										},
									},
									{
										label: '下载公共文件',
										onClick() {
											return confirmDownload(row, 'public');
										},
										condition: () => row.public_url,
									},
									{
										label: '下载私有文件',
										onClick() {
											return confirmDownload(row, 'private');
										},
										condition: () => row.private_url,
									},
									{
										label: '下载配置文件',
										onClick() {
											return confirmDownload(row, 'config');
										},
										condition: () => row.config_file_url,
									},
								],
							},
							{
								group: '恢复',
								condition: () => row.offsite,
								items: [
									{
										label: '恢复备份',
										condition: () => site.pg.status !== 'Archived',
										onClick() {
											confirmDialog({
												title: '恢复备份',
												message: `您确定要将您的站点恢复到<b>${dayjs(
													row.creation,
												).format('lll')}</b>的异地备份吗？`,
												onSuccess({ hide }) {
													toast.promise(
														site.restoreSiteFromFiles.submit({
															files: {
																database: row.remote_database_file,
																public: row.remote_public_file,
																private: row.remote_private_file,
																config: row.remote_config_file,
															},
														}),
														{
															loading: '正在安排备份恢复...',
															success: (jobId) => {
																hide();
																router.push({
																	name: 'Site Job',
																	params: {
																		name: site.name,
																		id: jobId,
																	},
																});
																return '备份恢复已成功安排。';
															},
															error: (e) => getToastErrorMessage(e),
														},
													);
												},
											});
										},
									},
									{
										label: '在另一个站点上恢复备份',
										onClick() {
											let SelectSiteForRestore = defineAsyncComponent(
												() =>
													import('../components/site/SelectSiteForRestore.vue'),
											);
											renderDialog(
												h(SelectSiteForRestore, {
													site: site.name,
													onRestore(siteName) {
														const restoreSite = createResource({
															url: 'jcloud.api.site.restore',
														});

														return toast.promise(
															restoreSite.submit({
																name: siteName,
																files: {
																	database: row.remote_database_file,
																	public: row.remote_public_file,
																	private: row.remote_private_file,
																	config: row.remote_config_file,
																},
															}),
															{
																loading: '正在安排备份恢复...',
																success: (jobId) => {
																	router.push({
																		name: 'Site Job',
																		params: { name: siteName, id: jobId },
																	});
																	return '备份恢复已成功安排。';
																},
																error: (e) => getToastErrorMessage(e),
															},
														);
													},
												}),
											);
										},
									},
								],
							},
						].filter((d) => (d.condition ? d.condition() : true));
					},
					primaryAction({ listResource: backups, documentResource: site }) {
						return {
							label: '安排备份',
							slots: {
								prefix: icon('upload-cloud'),
							},
							loading: site.backup.loading,
							onClick() {
								confirmDialog({
									title: '安排备份',
									message:
										'您确定要安排备份吗？这将创建一个本地备份。',
									onSuccess({ hide }) {
										toast.promise(
											site.backup.submit({
												with_files: true,
											}),
											{
												loading: '正在安排备份...',
												success: () => {
													hide();
													router.push({
														name: 'Site Jobs',
														params: { name: site.name },
													});
													return '备份已成功安排。';
												},
												error: (e) => getToastErrorMessage(e),
											},
										);
									},
								});
							},
						};
					},
				},
			},
			getJobsTab('Site'),
			{
				label: '操作',
				icon: icon('sliders'),
				route: 'actions',
				type: 'Component',
				condition: (site) => site.pg?.status !== 'Archived',
				component: SiteActions,
				props: (site) => {
					return { site: site.pg?.name };
				},
			},
			{
				label: '更新',
				icon: icon('arrow-up-circle'),
				route: 'updates',
				type: 'list',
				condition: (site) => site.pg?.status !== 'Archived',
				childrenRoutes: ['Site Update'],
				list: {
					pagetype: 'Site Update',
					filters: (site) => {
						return { site: site.pg?.name };
					},
					orderBy: 'creation',
					fields: [
						'difference',
						'update_job.end as updated_on',
						'update_job',
						'backup_type',
						'recover_job',
					],
					columns: [
						{
							label: '类型',
							fieldname: 'deploy_type',
							width: 0.3,
							format(value) {
								return getDeployTypeLabel(value);
							}
						},
						{
							label: '状态',
							fieldname: 'status',
							type: 'Badge',
							width: 0.5,
							format(value) {
								return getStatusLabel(value);
							}
						},
						// {
						// 	label: '备份',
						// 	width: 0.4,
						// 	type: 'Component',
						// 	component({ row }) {
						// 		return h(
						// 			'div',
						// 			{
						// 				class: 'truncate text-base',
						// 			},
						// 			row.skipped_backups
						// 				? '跳过'
						// 				: row.backup_type || '逻辑',
						// 		);
						// 	},
						// },
						{
							label: '创建者',
							fieldname: 'owner',
						},
						{
							label: '计划时间',
							fieldname: 'scheduled_time',
							format(value) {
								return date(value, 'lll');
							},
						},
						{
							label: '更新时间',
							fieldname: 'updated_on',
							format(value) {
								return date(value, 'lll');
							},
						},
					],
					rowActions({ row, documentResource: site }) {
						return [
							{
								label: '编辑',
								condition: () => row.status === 'Scheduled',
								onClick() {
									let SiteUpdateDialog = defineAsyncComponent(
										() => import('../components/SiteUpdateDialog.vue'),
									);
									renderDialog(
										h(SiteUpdateDialog, {
											site: site.pg?.name,
											existingUpdate: row.name,
										}),
									);
								},
							},
							{
								label: '取消',
								condition: () => row.status === 'Scheduled',
								onClick() {
									confirmDialog({
										title: '取消更新',
										message: `您确定要取消计划的更新吗？`,
										onSuccess({ hide }) {
											if (site.cancelUpdate.loading) return;
											toast.promise(
												site.cancelUpdate.submit({ site_update: row.name }),
												{
													loading: '正在取消更新...',
													success: () => {
														hide();
														site.reload();
														return '更新已取消';
													},
													error: (e) => getToastErrorMessage(e),
												},
											);
										},
									});
								},
							},
							{
								label: '查看任务',
								condition: () => row.status !== 'Scheduled',
								onClick() {
									router.push({
										name: 'Site Update',
										params: { id: row.name },
									});
								},
							},
							{
								label: '立即更新',
								condition: () => row.status === 'Scheduled',
								onClick() {
									let siteUpdate = getDocResource({
										pagetype: 'Site Update',
										name: row.name,
										whitelistedMethods: {
											updateNow: 'start',
										},
									});

									toast.promise(siteUpdate.updateNow.submit(), {
										loading: '正在更新站点...',
										success: () => {
											router.push({
												name: 'Site Update',
												params: { id: row.name },
											});

											return '站点更新已启动';
										},
										error: '更新站点失败',
									});
								},
							},
							{
								label: '查看应用更改',
								onClick() {
									createListResource({
										pagetype: 'Deploy Candidate Difference App',
										fields: [
											'difference.github_diff_url as diff_url',
											'difference.source_hash as source_hash',
											'difference.destination_hash as destination_hash',
											'app.title as app',
										],
										filters: {
											parenttype: 'Deploy Candidate Difference',
											parent: row.difference,
										},
										auto: true,
										pageLength: 99,
										onSuccess(data) {
											if (data?.length) {
												renderDialog(
													h(
														GenericDialog,
														{
															options: {
																title: '应用更改',
																size: '2xl',
															},
														},
														{
															default: () =>
																h(ObjectList, {
																	options: {
																		data: () => data,
																		columns: [
																			{
																				label: '应用',
																				fieldname: 'app',
																			},
																			{
																				label: '从',
																				fieldname: 'source_hash',
																				type: 'Button',
																				Button({ row }) {
																					return {
																						label:
																							row.source_tag ||
																							row.source_hash.slice(0, 7),
																						variant: 'ghost',
																						class: 'font-mono',
																						link: `${
																							row.diff_url.split('/compare')[0]
																						}/commit/${row.source_hash}`,
																					};
																				},
																			},
																			{
																				label: '到',
																				fieldname: 'destination_hash',
																				type: 'Button',
																				Button({ row }) {
																					return {
																						label:
																							row.destination_tag ||
																							row.destination_hash.slice(0, 7),
																						variant: 'ghost',
																						class: 'font-mono',
																						link: `${
																							row.diff_url.split('/compare')[0]
																						}/commit/${row.destination_hash}`,
																					};
																				},
																			},
																			{
																				label: '应用变更',
																				fieldname: 'diff_url',
																				align: 'right',
																				type: 'Button',
																				Button({ row }) {
																					return {
																						label: '查看',
																						variant: 'ghost',
																						slots: {
																							prefix: icon('external-link'),
																						},
																						link: row.diff_url,
																					};
																				},
																			},
																		],
																	},
																}),
														},
													),
												);
											} else toast.error('未找到应用变更');
										},
									});
								},
							},
						];
					},
					actions({ documentResource: site }) {
						if (site.pg.group_public) return [];

						return [
							{
								label: '配置',
								slots: {
									prefix: icon('settings'),
								},
								onClick() {
									let ConfigureAutoUpdateDialog = defineAsyncComponent(
										() =>
											import(
												'../components/site/ConfigureAutoUpdateDialog.vue'
											),
									);

									renderDialog(
										h(ConfigureAutoUpdateDialog, {
											site: site.pg?.name,
										}),
									);
								},
							},
						];
					},
				},
			},

		],
		actions(context) {
			let { documentResource: site } = context;
			let $team = getTeam();
			let runningJobs = getRunningJobs({ site: site.pg?.name });

			return [
				{
					label: '进行中的任务',
					slots: {
						prefix: () => h(LoadingIndicator, { class: 'w-4 h-4' }),
					},
					condition() {
						return (
							runningJobs.filter((job) =>
								['Pending', 'Running'].includes(job.status),
							).length > 0
						);
					},
					onClick() {
						router.push({
							name: 'Site Jobs',
							params: { name: site.name },
						});
					},
				},
				{
					label: '有可用更新',
					variant: site.pg?.setup_wizard_complete ? 'solid' : 'subtle',
					slots: {
						prefix: icon('alert-circle'),
					},
					condition() {
						return (
							!site.pg?.has_scheduled_updates &&
							site.pg.update_information?.update_available &&
							['Active', 'Inactive', 'Suspended', 'Broken'].includes(
								site.pg.status,
							)
						);
					},

					onClick() {
						let SiteUpdateDialog = defineAsyncComponent(
							() => import('../components/SiteUpdateDialog.vue'),
						);
						renderDialog(h(SiteUpdateDialog, { site: site.pg?.name }));
					},
				},
				{
					label: '已安排更新',
					slots: {
						prefix: icon('calendar'),
					},
					condition: () => site.pg?.has_scheduled_updates,
					onClick() {
						router.push({
							name: 'Site Detail Updates',
							params: { name: site.name },
						});
					},
				},
				{
					label: '模拟站点所有者',
					title: '模拟站点所有者', // for label to pop-up on hover
					slots: {
						icon: defineAsyncComponent(
							() => import('~icons/lucide/venetian-mask'),
						),
					},
					condition: () =>
						$team.pg?.is_desk_user && site.pg.team !== $team.name,
					onClick() {
						switchToTeam(site.pg.team);
					},
				},
				{
					label: '访问站点',
					slots: {
						prefix: icon('external-link'),
					},
					condition: () =>
						site.pg.status !== 'Archived' && site.pg?.setup_wizard_complete,
					onClick() {
						window.open(`https://${site.name}/app`, '_blank');
					},
				},
				{
					label: '设置站点',
					slots: {
						prefix: icon('external-link'),
					},
					variant: 'solid',
					condition: () =>
						site.pg.status === 'Active' && !site.pg?.setup_wizard_complete,
					onClick() {
						if (site.pg.additional_system_user_created) {
							site.loginAsTeam
								.submit({ reason: '' })
								.then((url) => window.open(url, '_blank'));
						} else {
							site.loginAsAdmin
								.submit({ reason: '' })
								.then((url) => window.open(url, '_blank'));
						}
					},
				},
				{
					label: '选项',
					context,
					options: [
						{
							label: '在 Desk 中查看',
							icon: 'external-link',
							condition: () => $team.pg?.is_desk_user,
							onClick: () => {
								window.open(
									`${window.location.protocol}//${window.location.host}/app/site/${site.name}`,
									'_blank',
								);
							},
						},
						{
							label: '以管理员身份登录',
							icon: 'external-link',
							condition: () => ['Active', 'Broken'].includes(site.pg.status),
							onClick: () => {
								confirmDialog({
									title: '以管理员身份登录',
									message: `您确定要以管理员身份登录站点 <b>${site.pg?.name}</b> 吗？`,
									fields:
										$team.name !== site.pg.team
											? [
													{
														label: '原因',
														type: 'textarea',
														fieldname: 'reason',
													},
												]
											: [],
									onSuccess: ({ hide, values }) => {
										if (!values.reason && $team.name !== site.pg.team) {
											throw new Error('原因必填');
										}
										return site.loginAsAdmin
											.submit({ reason: values.reason })
											.then((result) => {
												let url = result;
												window.open(url, '_blank');
												hide();
											});
									},
								});
							},
						},
					],
				},
			];
		},
	},

	routes: [
		{
			name: '站点更新',
			path: 'updates/:id',
			component: () => import('../pages/SiteUpdate.vue'),
		},
		{
			name: 'Site Job',
			path: 'jobs/:id',
			component: () => import('../pages/JobPage.vue')
		}
	],
};