<script setup>
import { format, formatDistanceStrict } from 'date-fns';
import { inject, ref, useId } from 'vue';

import { del, get, post } from '#/src/api.js';
import events from '#/src/events.js';

const pageContext = inject('pageContext');
const now = pageContext.meta.now;
const user = pageContext.user;
const keys = ref(pageContext.pageProps.keys);
const newKey = ref(null);
const flushTooltipId = useId();

async function createKey() {
	const key = await post('/me/keys', null, {
		appendErrorMessage: true,
	});

	newKey.value = key;
	keys.value = await get('/me/keys');
}

async function removeKey(key) {
	if (confirm(`Are you sure you want to remove API key '${key.identifier}'? It can not be restored.`)) { // eslint-disable-line no-alert
		newKey.value = null;

		await del(`/me/keys/${key.identifier}`);

		keys.value = await get('/me/keys');
	}
}

async function flushKeys() {
	if (confirm('Are you sure you want to remove ALL your API keys? They can not be restored.')) { // eslint-disable-line no-alert
		newKey.value = null;

		await del('/me/keys');

		keys.value = [];
	}
}

function copyKey(event) {
	event.target.select();
	navigator.clipboard.writeText(newKey.value.key);

	events.emit('feedback', {
		type: 'success',
		message: 'Key copied to clipboard',
	});
}
</script>

<template>
	<section class="profile-section">
		<div class="section-header">
			<div class="keys-actions">
				<button
					class="button"
					@click="createKey"
				>
					<Icon icon="key" />
					<span class="button-label">New key</span>
				</button>

				<Icon
					v-tooltip="{ content: 'Flush all keys', ariaId: flushTooltipId }"
					icon="stack-cancel"
					class="keys-flush"
					@click="flushKeys"
				/>
			</div>
		</div>

		<div class="manager">
			<div
				v-if="newKey"
				class="newkey"
			>
				<p class="key-info">Successfully generated key with identifier <strong class="newkey-identifier ellipsis">{{ newKey.identifier }}</strong>:</p>

				<input
					:value="newKey.key"
					class="input ellipsis"
					@click="copyKey"
				>

				<p class="key-info">Please store this key securely, you will <strong>not</strong> be able to retrieve it later. If you lose it, you must generate a new key.</p>
			</div>

			<ul
				v-if="keys.length > 0"
				class="keys nolist"
			>
				<li
					v-for="key in keys"
					:key="`key-${key.id}`"
					class="key"
				>
					<div class="key-row key-header">
						<strong class="key-value key-identifier ellipsis">{{ key.identifier }}</strong>

						<span class="key-actions">
							<Icon
								icon="bin"
								class="key-remove"
								@click="removeKey(key)"
							/>
						</span>
					</div>

					<div class="key-row key-details">
						<span class="key-value key-created">
							<Icon icon="plus-circle" />

							<time
								v-tooltip="{ content: `Created ${format(key.createdAt, 'yyyy-MM-dd hh:mm:ss')}`, ariaId: `key-created-${key.id}` }"
								:datetime="key.createdAt.toISOString()"
							>{{ formatDistanceStrict(key.createdAt, now) }} ago</time>
						</span>

						<span class="key-value key-used">
							<Icon icon="history" />

							<template v-if="key.lastUsedAt">
								<time
									v-tooltip="{ content: `Last used ${format(key.lastUsedAt, 'yyyy-MM-dd hh:mm:ss')} from IP ${key.lastUsedIp}`, ariaId: `key-used-${key.id}` }"
									:datetime="key.lastUsedAt.toISOString()"
								>{{ formatDistanceStrict(key.lastUsedAt, now) }} ago</time>
							</template>

							<template v-else>Never</template>
						</span>
					</div>
				</li>
			</ul>

			<div
				v-if="keys.length > 0"
				class="info"
			>
				<h3 class="info-heading">HTTP headers</h3>

				<code class="headers">
					API-User: <strong>{{ user.id }}</strong><br>
					API-Key: <em>YourSecretKey</em>
				</code>
			</div>
		</div>
	</section>
</template>

<style scoped>
.profile-section .section-header {
	justify-content: center;
	margin-bottom: 1rem;
}

.keys-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: .5rem;
}

.keys-actions {
	display: flex;
	align-items: center;
	gap: 1rem;

	> .icon {
		padding: .5rem 1rem;
	}
}

.keys-actions,
.key-actions {
	.icon {
		height: 100%;
		fill: var(--glass);

		&:hover {
			cursor: pointer;
		}
	}
}

.keys-flush,
.key-remove {
	&:hover {
		fill: var(--error);
	}
}

.keys {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(25rem, 1fr));
	gap: .5rem;
	margin-bottom: 2rem;
}

.key {
	background: var(--background);
	box-shadow: 0 0 3px var(--shadow-weak-30);
	border-radius: .25rem;
	font-size: .9rem;
}

.key-row {
	display: flex;
	justify-content: space-between;
	align-items: center;
	overflow: hidden;
}

.key-value {
	display: flex;
	align-items: center;
	gap: .25rem;
	box-sizing: border-box;

	.icon {
		width: .9rem;
		height: .9rem;
		margin-right: .25rem;
		fill: var(--glass);
	}
}

.key-header .key-value {
	padding: .5rem .75rem;
}

.key-details .key-value {
	padding: .25rem .75rem .75rem .75rem;
}

.key-identifier {
	display: inline-block;
	width: 0;
	flex-grow: 1;
}

.key-actions .icon {
	height: 1rem;
	padding: .75rem .75rem .5rem .75rem;
	overflow: hidden;
}

.newkey {
	max-width: 100%;
	display: inline-block;
	box-sizing: border-box;
	padding: .5rem .75rem;
	margin-bottom: 1rem;
	background: var(--enabled-background);
	border: solid 1px var(--success);
	border-radius: .25rem;
	line-height: 1.5;

	.input {
		width: 24rem;
		max-width: 100%;
		padding: .25rem .5rem;
		margin-bottom: .5rem;
		font-weight: bold;
	}
}

.newkey-identifier {
	white-space: nowrap;
}

.key-info {
	margin: 0;

	&:not(:last-child) {
		margin-bottom: .25rem;
	}
}

.headers {
	display: block;
	max-width: 100%;
	padding: .5rem 0;
	white-space: nowrap;
	overflow: auto;
}

.info-heading {
	margin: 0;
}

@media(--compact) {
	.manager {
		padding: 0 1rem;
	}
}

@media(--small-20) {
	.manager {
		padding: 0 .5rem;
	}

	.keys {
		grid-template-columns: 1fr;
	}
}
</style>
