<template>
	<div class="developer-settings-container">
		<n-space vertical :size="24">
			<!-- API Access 卡片 -->
			<n-card :title="$t('API Access')" class="settings-card">
				<n-space vertical :size="20">
					<div class="flex items-center justify-between flex-wrap gap-4">
						<div class="text-base text-gray-700">
							{{ $t('API key and API secret can be used to access') }}
							<a href="/docs/api" class="text-primary underline" target="_blank">
								{{ $t('Jingrow API') }}
							</a>
						</div>
						<n-button type="primary" @click="showCreateSecretDialog = true" :size="buttonSize">
							{{ apiKeyButtonLabel }}
						</n-button>
					</div>
					<div v-if="$team.pg?.user_info?.api_key">
						<ClickToCopyField :textContent="$team.pg.user_info.api_key" />
					</div>
					<div v-else class="text-base text-gray-600">
						{{ $t("You don't have an API key yet. Click the button above to create one.") }}
					</div>
				</n-space>
			</n-card>

			<!-- SSH Keys 卡片 -->
			<n-card :title="$t('SSH Keys')" class="settings-card">
				<ObjectList :options="sshKeyListOptions" />
			</n-card>

			<!-- Webhooks 卡片 -->
			<n-card
				v-if="$session.hasWebhookConfigurationAccess"
				:title="$t('Webhooks')"
				class="settings-card"
			>
				<ObjectList :options="webhookListOptions" />
			</n-card>
		</n-space>

		<!-- API Key 创建/重新生成弹窗 -->
		<n-modal
			v-model:show="showCreateSecretDialog"
			preset="card"
			:title="$t('API Access')"
			:style="modalStyle"
			:mask-closable="true"
			:close-on-esc="true"
			class="api-key-modal"
		>
			<template #header>
				<span class="text-lg font-semibold">{{ $t('API Access') }}</span>
			</template>
			<n-space vertical :size="20">
				<div v-if="createSecret.data">
					<n-alert type="warning" class="mb-4">
						{{ $t('Please copy the API key immediately. You will not be able to view it again!') }}
					</n-alert>
					<n-form-item :label="$t('API Key')">
						<ClickToCopyField :textContent="createSecret.data.api_key" />
					</n-form-item>
					<n-form-item :label="$t('API Secret')">
						<ClickToCopyField :textContent="createSecret.data.api_secret" />
					</n-form-item>
				</div>
				<div v-else class="text-base text-gray-700">
					{{ $t('API key and API secret can be used to access') }}
					<a href="/docs/api" class="text-primary underline" target="_blank">
						{{ $t('Jingrow API') }}
					</a>.
				</div>
			</n-space>
			<template #action>
				<n-space :vertical="isMobile" :size="isMobile ? 12 : 16" class="w-full">
					<n-button @click="showCreateSecretDialog = false" :block="isMobile" :size="buttonSize">
						{{ $t('Cancel') }}
					</n-button>
					<n-button
						type="primary"
						:loading="createSecret.loading"
						:disabled="!!createSecret.data"
						@click="createSecret.submit()"
						:block="isMobile"
						:size="buttonSize"
					>
						{{ $team.pg.user_info.api_key ? $t('Regenerate API Key') : $t('Create New API Key') }}
					</n-button>
				</n-space>
			</template>
		</n-modal>

		<!-- SSH Key 添加弹窗 -->
		<n-modal
			v-model:show="showAddSSHKeyDialog"
			preset="card"
			:title="$t('Add New SSH Key')"
			:style="modalStyle"
			:mask-closable="true"
			:close-on-esc="true"
			class="ssh-key-modal"
		>
			<template #header>
				<span class="text-lg font-semibold">{{ $t('Add New SSH Key') }}</span>
			</template>
			<n-space vertical :size="20">
				<p class="text-base text-gray-700">{{ $t('Add a new SSH key to your account') }}</p>
				<n-form-item :label="$t('SSH Key')" :required="true">
					<n-input
						v-model:value="sshKeyValue"
						type="textarea"
						:placeholder="sshKeyPlaceholder"
						:rows="6"
						:size="inputSize"
						class="w-full"
					/>
				</n-form-item>
				<n-alert v-if="sshKeyError" type="error" :title="sshKeyError" />
			</n-space>
			<template #action>
				<n-space :vertical="isMobile" :size="isMobile ? 12 : 16" class="w-full">
					<n-button @click="showAddSSHKeyDialog = false" :block="isMobile" :size="buttonSize">
						{{ $t('Cancel') }}
					</n-button>
					<n-button
						type="primary"
						:loading="addSSHKey.loading"
						@click="handleAddSSHKey"
						:block="isMobile"
						:size="buttonSize"
					>
						{{ $t('Add SSH Key') }}
					</n-button>
				</n-space>
			</template>
		</n-modal>

		<!-- Webhook 禁用确认弹窗 -->
		<n-modal
			v-model:show="showDisableWebhookDialog"
			preset="dialog"
			:title="$t('Disable Webhook')"
			:positive-text="$t('Disable')"
			:positive-button-props="{ type: 'error' }"
			:loading="disableWebhook.loading"
			:mask-closable="true"
			:close-on-esc="true"
			@positive-click="handleDisableWebhook"
		>
			<div class="py-4">
				<p class="text-base mb-2">
					{{ $t('Endpoint') }}: <strong>{{ selectedWebhookForAction?.endpoint }}</strong>
				</p>
				<p class="text-base">{{ $t('Are you sure you want to disable this webhook?') }}</p>
			</div>
		</n-modal>

		<!-- Webhook 删除确认弹窗 -->
		<n-modal
			v-model:show="showDeleteWebhookDialog"
			preset="dialog"
			:title="$t('Delete Webhook')"
			:positive-text="$t('Delete')"
			:positive-button-props="{ type: 'error' }"
			:loading="deleteWebhook.loading"
			:mask-closable="true"
			:close-on-esc="true"
			@positive-click="handleDeleteWebhook"
		>
			<div class="py-4">
				<p class="text-base mb-2">
					{{ $t('Endpoint') }}: <strong>{{ selectedWebhookForAction?.endpoint }}</strong>
				</p>
				<p class="text-base">{{ $t('Are you sure you want to delete this webhook?') }}</p>
			</div>
		</n-modal>

		<!-- Webhook 相关弹窗 -->
		<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>
</template>

<script setup>
import {
	NCard,
	NSpace,
	NButton,
	NModal,
	NFormItem,
	NInput,
	NAlert,
} from 'naive-ui';
import { Badge, createResource } from 'jingrow-ui';
import { toast } from 'vue-sonner';
import { computed, h, onMounted, ref, getCurrentInstance } from 'vue';
import { 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 instance = getCurrentInstance();
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);

const $team = getTeam();
const router = useRouter();
let showCreateSecretDialog = ref(false);
const showAddSSHKeyDialog = ref(false);
const sshKeyValue = ref('');
const sshKeyError = ref('');
const showAddWebhookDialog = ref(false);
const showActivateWebhookDialog = ref(false);
const showEditWebhookDialog = ref(false);
const showWebhookAttempts = ref(false);
const selectedWebhook = ref(null);
const selectedWebhookForAction = ref(null);
const showDisableWebhookDialog = ref(false);
const showDeleteWebhookDialog = ref(false);
const windowWidth = ref(window.innerWidth);

const isMobile = computed(() => windowWidth.value <= 768);
const modalStyle = computed(() => ({
	width: isMobile.value ? '95vw' : '700px',
	maxWidth: isMobile.value ? '95vw' : '90vw',
}));
const inputSize = computed(() => (isMobile.value ? 'medium' : 'large'));
const buttonSize = computed(() => (isMobile.value ? 'medium' : 'medium'));
const sshKeyPlaceholder = computed(() => {
	return $t("Starts with 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519', 'sk-ecdsa-sha2-nistp256@openssh.com', or 'sk-ssh-ed25519@openssh.com'");
});

const createSecret = createResource({
	url: 'jcloud.api.account.create_api_secret',
	onSuccess() {
		if ($team.pg.user_info.api_key) {
			toast.success($t('API key regenerated successfully'));
		} else {
			toast.success($t('API key created successfully'));
		}
		$team.reload();
	}
});

const addSSHKey = createResource({
	url: 'jcloud.api.client.insert',
	onSuccess() {
		toast.success($t('SSH key added successfully'));
		showAddSSHKeyDialog.value = false;
		sshKeyValue.value = '';
		sshKeyError.value = '';
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: $t('Failed to add SSH key')
		);
	}
});

const makeKeyDefault = createResource({
	url: 'jcloud.api.account.mark_key_as_default',
	onSuccess() {
		toast.success($t('SSH key updated successfully'));
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: $t('Failed to set SSH key as default')
		);
	}
});

const deleteSSHKey = createResource({
	url: 'jcloud.api.client.delete',
	onSuccess() {
		toast.success($t('SSH key deleted successfully'));
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: $t('Failed to delete SSH key')
		);
	}
});

const sshKeyListOptions = computed(() => ({
	resource() {
		return {
			url: 'jcloud.api.account.get_user_ssh_keys',
			initialData: [],
			auto: true
		};
	},
	columns: [
		{
			label: $t('SSH Fingerprint'),
			fieldname: 'ssh_fingerprint',
			class: 'font-mono',
			format: value => `SHA256:${value}`,
			suffix(row) {
				return row.is_default
					? h(Badge, {
							label: $t('Default'),
							theme: 'green',
							class: 'ml-2'
					  })
					: null;
			}
		},
		{
			label: $t('Added Time'),
			fieldname: 'creation',
			width: 0.1,
			format: value => date(value, 'll')
		}
	],
	primaryAction({ listResource }) {
		return {
			label: $t('Add SSH Key'),
			slots: { prefix: icon('plus') },
			onClick: () => {
				showAddSSHKeyDialog.value = true;
				sshKeyListResource = listResource;
			}
		};
	},
	rowActions({ row }) {
		return [
			{
				label: $t('Set as Default'),
				condition: () => !row.is_default,
				onClick() {
					makeKeyDefault.submit({
						key_name: row.name
					});
				}
			},
			{
				label: $t('Delete'),
				onClick() {
					deleteSSHKey.submit({
						pagetype: 'User SSH Key',
						name: row.name
					});
				}
			}
		];
	}
}));

let sshKeyListResource = null;

function handleAddSSHKey() {
	if (!sshKeyValue.value) {
		sshKeyError.value = $t('SSH key is required');
		return;
	}
	sshKeyError.value = '';
	addSSHKey
		.submit({
			pg: {
				pagetype: 'User SSH Key',
				ssh_public_key: sshKeyValue.value,
				user: $team.pg.user_info.name
			}
		})
		.then(() => {
			if (sshKeyListResource) {
				sshKeyListResource.reload();
			}
		})
		.catch(error => {
			sshKeyError.value = 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($t('Webhook deleted successfully'));
		webhookListResource.reload();
		showDeleteWebhookDialog.value = false;
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: $t('Failed to delete webhook')
		);
	}
});

const webhookListOptions = computed(() => ({
	data: () => webhookListResource.data,
	columns: [
		{
			label: $t('Endpoint'),
			fieldname: 'endpoint',
			width: 1,
			format: value => value.substring(0, 50)
		},
		{
			label: $t('Status'),
			fieldname: 'enabled',
			width: 0.1,
			type: 'Component',
			align: 'right',
			component({ row }) {
				return row.enabled
					? h(Badge, {
							label: $t('Enabled'),
							theme: 'green'
					  })
					: h(Badge, {
							label: $t('Disabled'),
							theme: 'red'
					  });
			}
		}
	],
	rowActions({ row }) {
		return [
			{
				label: $t('Activate'),
				condition: () => !Boolean(row.enabled),
				onClick() {
					selectedWebhook.value = row;
					showActivateWebhookDialog.value = true;
				}
			},
			{
				label: $t('Disable'),
				condition: () => Boolean(row.enabled),
				onClick: () => {
					selectedWebhookForAction.value = row;
					showDisableWebhookDialog.value = true;
				}
			},
			{
				label: $t('Attempts'),
				onClick: () => {
					selectedWebhook.value = row;
					showWebhookAttempts.value = true;
				}
			},
			{
				label: $t('Edit'),
				onClick() {
					selectedWebhook.value = row;
					showEditWebhookDialog.value = true;
				}
			},
			{
				label: $t('Delete'),
				onClick() {
					selectedWebhookForAction.value = row;
					showDeleteWebhookDialog.value = true;
				}
			}
		];
	},
	primaryAction() {
		return {
			label: $t('Add Webhook'),
			slots: { prefix: icon('plus') },
			onClick: () => (showAddWebhookDialog.value = true)
		};
	},
	secondaryAction() {
		return {
			label: $t('Refresh'),
			icon: 'refresh-ccw',
			onClick: () => webhookListResource.reload()
		};
	}
}));

const disableWebhook = createResource({
	url: 'jcloud.api.client.run_pg_method',
	onSuccess() {
		toast.success($t('Webhook disabled successfully'));
		webhookListResource.reload();
		showDisableWebhookDialog.value = false;
	},
	onError(err) {
		toast.error(
			err.messages.length
				? err.messages.join('\n')
				: $t('Failed to disable webhook')
		);
	}
});

function handleDisableWebhook() {
	if (!selectedWebhookForAction.value) return;
	disableWebhook.submit({
		dt: 'Jcloud Webhook',
		dn: selectedWebhookForAction.value.name,
		method: 'disable'
	});
}

function handleDeleteWebhook() {
	if (!selectedWebhookForAction.value) return;
	deleteWebhook.submit({
		pagetype: 'Jcloud Webhook',
		name: selectedWebhookForAction.value.name
	});
}

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;
	}
};

const apiKeyButtonLabel = computed(() => {
	return $team.pg?.user_info?.api_key
		? $t('Regenerate API Key')
		: $t('Create New API Key');
});

function handleResize() {
	windowWidth.value = window.innerWidth;
}

onMounted(() => {
	handleResize();
	window.addEventListener('resize', handleResize);
	if (session.hasWebhookConfigurationAccess) {
		webhookListResource.fetch();
	}
});
</script>

<style scoped>
.developer-settings-container {
	width: 100%;
	padding: 24px;
}

.settings-card {
	border-radius: 12px;
	box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
	transition: box-shadow 0.2s ease;
}

.settings-card:hover {
	box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}

:deep(.api-key-modal .n-card),
:deep(.ssh-key-modal .n-card) {
	width: 700px;
	max-width: 90vw;
}

:deep(.api-key-modal .n-card-body),
:deep(.ssh-key-modal .n-card-body) {
	padding: 24px;
}

:deep(.api-key-modal .n-form-item),
:deep(.ssh-key-modal .n-form-item) {
	margin-bottom: 0;
}

:deep(.api-key-modal .n-input),
:deep(.ssh-key-modal .n-input) {
	width: 100%;
}

:deep(.api-key-modal .n-card__action),
:deep(.ssh-key-modal .n-card__action) {
	padding: 16px 24px;
}

@media (max-width: 768px) {
	.developer-settings-container {
		padding: 16px;
	}

	.settings-card {
		border-radius: 8px;
	}

	:deep(.api-key-modal .n-card),
	:deep(.ssh-key-modal .n-card) {
		width: 95vw !important;
		max-width: 95vw !important;
		margin: 20px auto;
		border-radius: 12px;
	}

	:deep(.api-key-modal .n-card-body),
	:deep(.ssh-key-modal .n-card-body) {
		padding: 20px 16px;
	}

	:deep(.api-key-modal .n-card__header),
	:deep(.ssh-key-modal .n-card__header) {
		padding: 16px;
		font-size: 18px;
	}

	:deep(.api-key-modal .n-card__action),
	:deep(.ssh-key-modal .n-card__action) {
		padding: 12px 16px;
	}

	:deep(.api-key-modal .n-space),
	:deep(.ssh-key-modal .n-space) {
		width: 100%;
	}

	:deep(.api-key-modal .n-button),
	:deep(.ssh-key-modal .n-button) {
		width: 100%;
		font-size: 16px;
		height: 44px;
	}
}
</style>
