<template>
	<div class="p-5">
		<div class="grid grid-cols-1 gap-5">
			<div
				class="mx-auto min-w-[48rem] max-w-3xl space-y-6 rounded-md border p-4"
			>
				<div class="flex items-center justify-between">
					<div class="text-xl font-semibold">API 访问</div>
					<Button @click="showCreateSecretDialog = true">{{
						$team.pg?.user_info?.api_key
							? '重新生成 API 密钥'
							: '创建新的 API 密钥'
					}}</Button>
				</div>
				<div v-if="$team.pg?.user_info?.api_key">
					<ClickToCopyField
						v-if="$team.pg?.user_info?.api_key"
						:textContent="$team.pg.user_info.api_key"
					/>
				</div>
				<div v-else class="pb-2 text-base text-gray-700">
					您还没有 API 密钥。点击上面的按钮创建一个。
				</div>
				<Dialog
					v-model="showCreateSecretDialog"
					:options="{
						title: 'API 访问',
						size: 'xl',
						actions: [
							{
								label: $team.pg.user_info.api_key
									? '重新生成 API 密钥'
									: '创建新的 API 密钥',
								variant: 'solid',
								disabled: createSecret.data,
								loading: createSecret.loading,
								onClick() {
									createSecret.submit();
								}
							}
						]
					}"
				>
					<template #body-content>
						<div v-if="createSecret.data">
							<p class="text-base">
								请立即复制 API 密钥。您将无法再次查看它！
							</p>
							<label class="block pt-2">
								<span class="mb-2 block text-sm leading-4 text-gray-700"
									>API key</span
								>
								<ClickToCopyField :textContent="createSecret.data.api_key" />
							</label>
							<label class="block pt-2">
								<span class="mb-2 block text-sm leading-4 text-gray-700"
									>API secret</span
								>
								<ClickToCopyField :textContent="createSecret.data.api_secret" />
							</label>
						</div>
						<div v-else class="text-base text-gray-700">
							API key 和 API secret 可用于访问
							<a href="/docs/api" class="underline" target="_blank"
								>今果 Jingrow API</a
							>.
						</div>
					</template>
				</Dialog>
			</div>
			<div
				class="mx-auto min-w-[48rem] max-w-3xl space-y-6 rounded-md border p-4"
			>
				<div class="flex items-center justify-between">
					<div class="text-xl font-semibold">SSH 密钥</div>
				</div>
				<ObjectList :options="sshKeyListOptions" />
			</div>
			<div
				v-if="$session.hasWebhookConfigurationAccess"
				class="mx-auto min-w-[48rem] max-w-3xl space-y-6 rounded-md border p-4"
			>
				<div class="flex items-center justify-between">
					<div class="text-xl font-semibold">Webhooks</div>
				</div>
				<ObjectList :options="webhookListOptions" />
				<AddNewWebhookDialog
					v-if="showAddWebhookDialog"
					v-model="showAddWebhookDialog"
					@success="onNewWebhookSuccess"
				/>
				<ActivateWebhookDialog
					v-if="showActivateWebhookDialog"
					v-model="showActivateWebhookDialog"
					@success="onWebHookActivated"
					:webhook="selectedWebhook"
				/>
				<EditWebhookDialog
					v-if="showEditWebhookDialog"
					v-model="showEditWebhookDialog"
					@success="onWebHookUpdated"
					:webhook="selectedWebhook"
				/>
				<WebhookAttemptsDialog
					v-if="showWebhookAttempts"
					v-model="showWebhookAttempts"
					:name="selectedWebhook.name"
				/>
			</div>
		</div>
	</div>
</template>

<script setup>
import { Badge, createResource } from 'jingrow-ui';
import { toast } from 'vue-sonner';
import { computed, h, onMounted, ref } from 'vue';
import { confirmDialog, icon } from '../../utils/components';
import ObjectList from '../ObjectList.vue';
import { getTeam } from '../../data/team';
import { date } from '../../utils/format';
import ClickToCopyField from '../ClickToCopyField.vue';
import AddNewWebhookDialog from './AddNewWebhookDialog.vue';
import ActivateWebhookDialog from './ActivateWebhookDialog.vue';
import EditWebhookDialog from './EditWebhookDialog.vue';
import { useRouter } from 'vue-router';
import WebhookAttemptsDialog from './WebhookAttemptsDialog.vue';
import { session } from '../../data/session';

const $team = getTeam();
const router = useRouter();
let showCreateSecretDialog = ref(false);
const showAddWebhookDialog = ref(false);
const showActivateWebhookDialog = ref(false);
const showEditWebhookDialog = ref(false);
const showWebhookAttempts = ref(false);
const selectedWebhook = ref(null);

const createSecret = createResource({
	url: 'jcloud.api.account.create_api_secret',
	onSuccess() {
		if ($team.pg.user_info.api_key) {
			toast.success('API 密钥已成功重新生成');
		} else {
			toast.success('API 密钥已成功创建');
		}
	}
});

const addSSHKey = createResource({
	url: 'jcloud.api.client.insert',
	onSuccess() {
		toast.success('SSH 密钥已成功添加');
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: 'SSH 密钥无法添加'
		);
	}
});

const makeKeyDefault = createResource({
	url: 'jcloud.api.account.mark_key_as_default',
	onSuccess() {
		toast.success('SSH 密钥已成功更新');
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: 'SSH 密钥无法设置为默认'
		);
	}
});

const deleteSSHKey = createResource({
	url: 'jcloud.api.client.delete',
	onSuccess() {
		toast.success('SSH 密钥已成功删除');
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: 'SSH 密钥无法删除'
		);
	}
});

const sshKeyListOptions = computed(() => ({
	resource() {
		return {
			url: 'jcloud.api.account.get_user_ssh_keys',
			initialData: [],
			auto: true
		};
	},
	columns: [
		{
			label: 'SSH 指纹',
			fieldname: 'ssh_fingerprint',
			class: 'font-mono',
			format: value => `SHA256:${value}`,
			suffix(row) {
				return row.is_default
					? h(Badge, {
							label: '默认',
							theme: 'green',
							class: 'ml-2'
					  })
					: null;
			}
		},
		{
			label: '添加时间',
			fieldname: 'creation',
			width: 0.1,
			format: value => date(value, 'll')
		}
	],
	primaryAction({ listResource }) {
		return {
			label: '添加 SSH 密钥',
			slots: { prefix: icon('plus') },
			onClick: () => renderAddNewKeyDialog(listResource)
		};
	},
	rowActions({ row }) {
		return [
			{
				label: '设为默认',
				condition: () => !row.is_default,
				onClick() {
					makeKeyDefault.submit({
						key_name: row.name
					});
				}
			},
			{
				label: '删除',
				onClick() {
					deleteSSHKey.submit({
						pagetype: 'User SSH Key',
						name: row.name
					});
				}
			}
		];
	}
}));

function renderAddNewKeyDialog(listResource) {
	confirmDialog({
		title: '添加新 SSH 密钥',
		message: '向您的账户添加新的 SSH 密钥',
		fields: [
			{
				label: 'SSH 密钥',
				fieldname: 'sshKey',
				type: 'textarea',
				placeholder:
					"以 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', 或 'sk-ssh-ed25519@openssh.com' 开头",
				required: true
			}
		],
		primaryAction: {
			label: '添加 SSH 密钥',
			variant: 'solid',
			onClick({ hide, values }) {
				if (!values.sshKey) throw new Error('SSH 密钥是必填项');
				addSSHKey
					.submit({
						pg: {
							pagetype: 'User SSH Key',
ssh_public_key: values.sshKey,
							user: $team.pg.user_info.name
						}
					})
					.then(() => {
						listResource.reload();
						hide();
					})
					.catch(error => {
						toast.error(error.message);
					});
			}
		}
	});
}

const webhookListResource = createResource({
	url: 'jcloud.api.client.get_list',
	params: {
		pagetype: 'Jcloud Webhook',
		fields: ['name', 'enabled', 'endpoint']
	},
	initialData: [],
	auto: false
});

const deleteWebhook = createResource({
	url: 'jcloud.api.client.delete',
	onSuccess() {
		toast.success('Webhook 删除成功');
		webhookListResource.reload();
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: 'Webhook 无法删除'
		);
	}
});

const webhookListOptions = computed(() => ({
	data: () => webhookListResource.data,
	columns: [
		{
			label: '端点',
			fieldname: 'endpoint',
			width: 1,
			format: value => value.substring(0, 50)
		},
		{
			label: '状态',
			fieldname: 'enabled',
			width: 0.1,
			type: 'Component',
			align: 'right',
			component({ row }) {
				return row.enabled
					? h(Badge, {
							label: '启用',
							theme: 'green'
					  })
					: h(Badge, {
							label: '禁用',
							theme: 'red'
					  });
			}
		}
	],
	rowActions({ row }) {
		return [
			{
				label: '激活',
				condition: () => !Boolean(row.enabled),
				onClick() {
					selectedWebhook.value = row;
					showActivateWebhookDialog.value = true;
				}
			},
			{
				label: '禁用',
				condition: () => Boolean(row.enabled),
				onClick: () => {
					confirmDialog({
						title: '禁用 Webhook',
						message: `端点 - ${row.endpoint}<br>确定要禁用该 webhook 吗？<br>`,
						primaryAction: {
							label: '禁用',
							variant: 'solid',
							theme: 'red',
							onClick({ hide }) {
								disableWebhook
									.submit({
										dt: 'Jcloud Webhook',
										dn: row.name,
										method: 'disable'
									})
									.then(hide);
								return disableWebhook.promise;
							}
						}
					});
				}
			},
			{
				label: '尝试',
				onClick: () => {
					selectedWebhook.value = row;
					showWebhookAttempts.value = true;
				}
			},
			{
				label: '编辑',
				onClick() {
					selectedWebhook.value = row;
					showEditWebhookDialog.value = true;
				}
			},
			{
				label: '删除',
				onClick() {
					confirmDialog({
						title: '删除 Webhook',
						message: `端点 - ${row.endpoint}<br>确定要删除该 webhook 吗？<br>`,
						primaryAction: {
							label: '删除',
							variant: 'solid',
							theme: 'red',
							onClick({ hide }) {
								deleteWebhook
									.submit({
										pagetype: 'Jcloud Webhook',
										name: row.name
									})
									.then(hide);
								return deleteWebhook.promise;
							}
						}
					});
				}
			}
		];
	},
	primaryAction() {
		return {
			label: '添加 Webhook',
			slots: { prefix: icon('plus') },
			onClick: () => (showAddWebhookDialog.value = true)
		};
	},
	secondaryAction() {
		return {
			label: '刷新',
			icon: 'refresh-ccw',
			onClick: () => webhookListResource.reload()
		};
	}
}));

const disableWebhook = createResource({
	url: 'jcloud.api.client.run_pg_method',
	onSuccess() {
		toast.success('Webhook 禁用成功');
		webhookListResource.reload();
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: 'Webhook 无法禁用'
		);
	}
});

const onNewWebhookSuccess = () => {
	webhookListResource.reload();
	showAddWebhookDialog.value = false;
};

const onWebHookActivated = () => {
	webhookListResource.reload();
	showActivateWebhookDialog.value = false;
};

const onWebHookUpdated = activationRequired => {
webhookListResource.reload();
	showEditWebhookDialog.value = false;
	if (activationRequired) {
		showActivateWebhookDialog.value = true;
	}
};

onMounted(() => {
	if (session.hasWebhookConfigurationAccess) {
		webhookListResource.fetch();
	}
});
</script>