<template>
	<div class="page">
		<div class="manager">
			<div class="keys-header">
				<h2 class="heading">API keys</h2>

				<div class="keys-actions">
					<Icon
						v-tooltip="'Flush all keys'"
						icon="stack-cancel"
						@click="flushKeys"
					/>

					<button
						class="button"
						@click="createKey"
					>New key</button>
				</div>
			</div>

			<div
				v-if="newKey"
				class="newkey"
			>
				<p class="key-info">
					Your new key identified by <strong>{{ newKey.identifier }}</strong> is
					<input
						:value="newKey.key"
						class="input"
						@click="copyKey"
					>
				</p>

				<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"
								@click="removeKey(key)"
							/>
						</span>
					</div>

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

							<time
								v-tooltip="format(key.createdAt, 'yyyy-MM-dd hh:mm:ss')"
								:datetime="key.createdAt.toISOString()"
							>{{ formatDistanceToNowStrict(key.createdAt) }} ago</time>
						</span>

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

							<template v-if="key.lastUsedAt">
								<time
									v-tooltip="`${key.lastUsedIp} at ${format(key.lastUsedAt, 'yyyy-MM-dd hh:mm:ss')}`"
									:datetime="key.lastUsedAt.toISOString()"
								>{{ formatDistanceToNowStrict(key.lastUsedAt) }} 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: {{ user.id }}<br>
					API-Key: YourSecurelyStoredApiKey12345678
				</code>
			</div>
		</div>
	</div>
</template>

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

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

const pageContext = inject('pageContext');
const user = pageContext.user;
const keys = ref(pageContext.pageProps.keys);
const newKey = ref(null);

async function createKey() {
	const key = await post('/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-restricted-globals, 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-restricted-globals, 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>

<style scoped>
.page {
	display: flex;
	flex-grow: 1;
	justify-content: center;
}

.manager {
	width: 1200px;
	max-width: 100%;
	box-sizing: border-box;
	padding: 1rem;
}

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

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

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

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

		&:hover {
			fill: var(--error);
			cursor: pointer;
		}
	}
}

.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);
	font-size: .9rem;
}

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

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

	.icon {
		width: .9rem;
		height: .9rem;
		fill: var(--glass-strong-10);
	}
}

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

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

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

.key-actions .icon {
	padding: 0 .5rem .5rem .5rem;
}

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

	.input {
		width: 24rem;
		padding: .25rem .75rem;
		font-weight: bold;
	}
}

.key-info {
	margin: 0 0 .5rem 0;
}

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

.info-heading {
	margin: 0;
}

@media(--small-20) {
	.keys {
		grid-template-columns: 1fr;
	}
}
</style>
