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

import AlertDialog from '#/components/alerts/create.vue';

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

const pageContext = inject('pageContext');

const alerts = ref(pageContext.pageProps.alerts);
const showAlertDialog = ref(false);
const done = ref(true);

const query = ref('');
const filterActors = ref(false);
const filterEntities = ref(false);
const filterTags = ref(false);
const filterExpressions = ref(false);
const filterScenes = ref(false);
const filterCombined = ref(null);

const filteredAlerts = computed(() => {
	const queryRegex = new RegExp(query.value, 'i');

	return alerts.value.filter((alert) => {
		if (filterActors.value && alert.actors.length === 0) {
			return false;
		}

		if (filterEntities.value && alert.entities.length === 0) {
			return false;
		}

		if (filterTags.value && alert.tags.length === 0) {
			return false;
		}

		if (filterExpressions.value && alert.matches.length === 0) {
			return false;
		}

		if (filterScenes.value && alert.scenes.length === 0) {
			return false;
		}

		if (filterCombined.value === false && [...alert.actors, ...alert.entities, ...alert.tags, ...alert.matches, ...alert.scenes].length > 1) {
			return false;
		}

		if (filterCombined.value === true && [...alert.actors, ...alert.entities, ...alert.tags, ...alert.matches, ...alert.scenes].length === 1) {
			return false;
		}

		if (queryRegex.test(alert.id)) {
			return true;
		}

		if (alert.actors.some((actor) => queryRegex.test(actor.name))) {
			return true;
		}

		if (alert.tags.some((tag) => queryRegex.test(tag.name))) {
			return true;
		}

		if (alert.entities.some((entity) => queryRegex.test(entity.name))) {
			return true;
		}

		if (alert.matches.some((match) => queryRegex.test(match.expression))) {
			return true;
		}

		if (alert.scenes.some((scene) => queryRegex.test(scene.title))) {
			return true;
		}

		return false;
	});
});

async function reloadAlerts() {
	alerts.value = await get('/alerts');
}

async function removeAlert(alert) {
	if (done.value === false) {
		return;
	}

	if (!confirm(`Are you sure you want to remove alert #${alert.id}?`)) { // eslint-disable-line no-alert
		return;
	}

	done.value = false;

	const alertLabel = [
		...alert.actors.map((actor) => actor.name),
		...alert.tags.map((tag) => tag.name),
		...alert.entities.map((entity) => entity.name),
		...alert.matches.map((match) => match.expression),
	].filter(Boolean).join(', ');

	try {
		await del(`/alerts/${alert.id}`, {
			undoFeedback: `Removed alert for '${alertLabel}'`,
			errorFeedback: `Failed to remove alert for '${alertLabel}'`,
			appendErrorMessage: true,
		});

		await reloadAlerts();
	}
	finally {
		done.value = true;
	}
}

const filterCombinedStates = [null, true, false];

function toggleFilterCombined() {
	const index = filterCombinedStates.indexOf(filterCombined.value);

	filterCombined.value = filterCombinedStates[(index + 1) % filterCombinedStates.length];
}
</script>

<template>
	<section class="profile-section">
		<div class="section-header">
			<button
				class="button"
				@click="showAlertDialog = true"
			>
				<Icon icon="alarm-add" />
				<span class="button-label">New alert</span>
			</button>
		</div>

		<div class="filters">
			<input
				v-model="query"
				type="search"
				class="input filters-search"
				placeholder="Search alerts"
			>

			<div class="filters-section">
				<Icon
					v-tooltip="'Only show actor alerts'"
					icon="star"
					class="noselect"
					:class="{ active: filterActors }"
					@click="filterActors = !filterActors"
				/>

				<Icon
					v-tooltip="'Only show tag alerts'"
					icon="price-tags"
					class="noselect"
					:class="{ active: filterTags }"
					@click="filterTags = !filterTags"
				/>

				<Icon
					v-tooltip="'Only show channel alerts'"
					icon="device_hub"
					class="noselect"
					:class="{ active: filterEntities }"
					@click="filterEntities = !filterEntities"
				/>

				<Icon
					v-tooltip="'Only show expression alerts'"
					icon="regexp"
					class="noselect"
					:class="{ active: filterExpressions }"
					@click="filterExpressions = !filterExpressions"
				/>

				<Icon
					v-tooltip="'Only show scene release date alerts'"
					icon="clapboard-play"
					class="noselect"
					:class="{ active: filterScenes }"
					@click="filterScenes = !filterScenes"
				/>

				<Icon
					v-if="filterCombined === false"
					icon="target3"
					title="Only show uncombined alerts"
					class="noselect active filters-uncombined"
					@click="toggleFilterCombined"
				/>

				<Icon
					v-else
					icon="make-group"
					title="Only show combined alerts"
					class="noselect filters-uncombined"
					:class="{ active: filterCombined }"
					@click="toggleFilterCombined"
				/>
			</div>
		</div>

		<ul class="alerts nolist">
			<li
				v-for="alert in filteredAlerts"
				:key="`alert-${alert.id}`"
				class="alert"
			>
				<div
					class="alert-details"
					:class="{ and: alert.and.fields, or: !alert.and.fields }"
				>
					<span
						v-if="alert.tags.length > 0"
						class="alert-detail alert-tags"
						:class="{ and: alert.and.tags, or: !alert.and.tags }"
					>
						<span class="alert-values">
							<span
								v-for="tag in alert.tags"
								:key="`tag-${alert.id}-${tag.id}`"
								class="alert-key"
							>
								<a
									:href="`/tag/${tag.slug}`"
									class="alert-value link"
								>{{ tag.name }}</a>
							</span>
						</span>
					</span>

					<span
						v-if="alert.actors.length > 0"
						class="alert-detail alert-actors"
						:class="{ and: alert.and.actors, or: !alert.and.actors }"
					>
						<span class="alert-values">with
							<span
								v-for="actor in alert.actors"
								:key="`actor-${alert.id}-${actor.id}`"
								class="alert-key"
							>
								<a
									:href="`/actor/${actor.id}/${actor.slug}`"
									class="alert-value link"
								>{{ actor.name }}</a>
							</span>
						</span>
					</span>

					<span
						v-if="alert.entities.length > 0"
						class="alert-detail alert-entities or"
					>
						<span class="alert-values">for
							<span
								v-for="entity in alert.entities"
								:key="`entity-${alert.id}-${entity.id}`"
								class="alert-key"
							>
								<a
									:href="`/${entity.type}/${entity.slug}`"
									class="alert-value link"
								>
									<Icon
										v-if="entity.type === 'network'"
										icon="device_hub"
									/>{{ entity.name }}
								</a>
							</span>
						</span>
					</span>

					<span
						v-if="alert.matches.length > 0"
						class="alert-detail alert-matches"
						:class="{ and: alert.and.matches, or: !alert.and.matches }"
					>
						<span class="alert-values">matching
							<span
								v-for="match in alert.matches"
								:key="`match-${alert.id}-${match.id}`"
								class="alert-key"
							>
								<span class="alert-value">{{ match.property }}:
									<span
										class="alert-regex"
										title="If your original expression was not a /regular expression/, it was converted, and new characters may have been added for syntactical purposes. These characters do not alter the function of the expression; they ensure it."
									>{{ match.expression }}</span>
								</span>
							</span>
						</span>
					</span>

					<span
						v-for="scene in alert.scenes"
						:key="`alert-${alert.id}-${scene.id}`"
						class="alert-scene"
					>
						<time
							:datetime="scene.date.toISOString()"
							class="alert-date"
						>{{ format(scene.date, 'yyyy-MM-dd') }}</time>

						<a
							:href="`/scene/${scene.id}/${scene.slug}`"
							class="alert-value alert-title ellipsis link"
						>{{ scene.title }}</a>
					</span>
				</div>

				<div class="alert-meta">
					<div class="alert-triggers">
						<Icon
							v-if="alert.notify && alert.isFromPreset"
							v-tooltip="{ content: alert.notify ? 'Notify in traxxx, added as quick alert' : undefined, ariaId: `alert-notify-preset-${alert.id}` }"
							icon="bell-plus"
							class="trigger"
						/>

						<Icon
							v-else
							v-tooltip="{ content: alert.notify ? 'Notify in traxxx' : undefined, ariaId: `alert-notify-${alert.id}` }"
							icon="bell2"
							:class="{ trigger: alert.notify }"
						/>

						<Icon
							v-tooltip="'E-mail me'"
							icon="envelop5"
							:class="{ trigger: alert.email }"
						/>

						<Icon
							v-if="alert.stashes.some((stash) => !stash.isPrimary)"
							v-tooltip="{ content: `Add to ${alert.stashes.map((stash) => stash.name).join(', ')}`, ariaId: `alert-stashes-${alert.id}` }"
							icon="folder-heart"
							class="trigger"
						/>

						<Icon
							v-else
							v-tooltip="alert.stashes.length > 0 ? { content: 'Add to Favorites', ariaId: `alert-favorites-${alert.id}` } : undefined"
							icon="heart7"
							:class="{ trigger: alert.stashes.length > 0 }"
						/>
					</div>

					<div class="alert-actions">
						<span
							v-tooltip="{ content: format(alert.createdAt, 'yyyy-MM-dd hh:mm'), ariaId: `alert-created-${alert.id}` }"
							class="alert-id"
							title="Alert ID"
						>#{{ alert.id }}</span>

						<Icon
							icon="bin"
							@click="removeAlert(alert)"
						/>
					</div>
				</div>
			</li>
		</ul>

		<AlertDialog
			v-if="showAlertDialog"
			@close="showAlertDialog = false; reloadAlerts();"
		/>
	</section>
</template>

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

.alerts {
	width: 100%;
	margin-bottom: 1rem;
}

.filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem;
	box-sizing: border-box;
	padding: 0 .5rem;
	margin: .5rem 0 .75rem 0;
	overflow: hidden;

	.input {
		margin-right: 1rem;
	}

	.icon {
		width: 1.25rem;
		height: 1.25rem;
		padding: .25rem .5rem;
		fill: var(--glass);

		&:hover {
			fill: var(--glass-strong-10);
			cursor: pointer;
		}

		&.active {
			fill: var(--primary);
		}

		&.success {
			fill: var(--success);
		}

		&.error {
			fill: var(--error);
		}
	}
}

.filters-uncombined.icon {
	padding-left: .75rem;
	border-left: solid 1px var(--glass-weak-30);
	margin-left: .5rem;
}

.alert {
	padding: 0 0 0 .5rem;
	display: flex;
	align-items: stretch;
	border-bottom: solid 1px var(--glass-weak-40);

	&:hover {
		border-color: var(--glass-weak-30);
	}
}

.alert-triggers  {
	display: flex;
	align-items: center;
	gap: .5rem;
	margin-right: .75rem;

	.icon {
		fill: var(--glass-weak-40);
	}

	.icon.trigger {
		fill: var(--glass-weak-10);
	}
}

.alert-details {
	padding: .25rem 0;
	flex-grow: 1;
	line-height: 2.5;
	color: var(--glass);

	&.and .alert-detail:not(:last-child):after {
		content: ' and ';
	}

	&.or .alert-detail:not(:last-child):after {
		content: ' or ';
	}
}

.alert-value {
	color: var(--text);

	.icon {
		margin-right: .25rem;
		fill: var(--glass);
		transform: translateY(2px);
	}
}

.alert-values {
	padding: .5rem .5rem;
	border-bottom: solid 1px var(--primary-light-20);
	border-radius: .3rem;
}

.alert-detail {
	&.and .alert-key:not(:last-child):after {
		content: ' and ';
	}

	&.or .alert-key:not(:last-child):after {
		content: ' or ';
	}
}

.alert-regex {
	&:before,
	&:after {
		content: '╱';
		padding: 0 .1rem;
		color: var(--primary-light-20);
	}
}

.alert-meta {
	display: flex;
}

.alert-scene {
	display: flex;
	gap: .5rem;
	padding: 0 .5rem;
}

.alert-date {
	flex-shrink: 0;
}

.alert-actions {
	display: flex;
	align-items: center;
	font-size: .9rem;
	color: var(--glass-weak-10);

	.icon {
		height: 100%;
		padding: 0 .75rem;
		fill: var(--glass);

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

@media(--compact) {
	.profile-header {
		border-radius: 0;
	}

	.section-header {
		padding: .5rem 1rem .5rem 1rem;
	}

	.stashes {
		padding: 0 1rem 1rem 1rem;
	}

	.alert {
		padding: 0 .5rem;
	}

	.filters {
		justify-content: space-between;
	}
}

@media(--small-20) {
	.alert {
		flex-direction: column;
		padding-right: 0;
	}

	.alert-meta {
		padding: .5rem 0 .5rem 0;
		justify-content: space-between;
	}
}

@media(--small-30) {
	.filters {
		flex-direction: column;
		justify-content: center;

		.input {
			width: 100%;
		}
	}
}
</style>
