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

import Dialog from '#/components/dialog/dialog.vue';
import Checkbox from '#/components/form/checkbox.vue';

import { get, post } from '#/src/api.js';
import getPath from '#/src/get-path.js';

const props = defineProps({
	presetActors: {
		type: Array,
		default: () => [],
	},
	presetEntities: {
		type: Array,
		default: () => [],
	},
	presetTags: {
		type: Array,
		default: () => [],
	},
	presetScenes: {
		type: Array,
		default: () => [],
	},
});

const emit = defineEmits(['alert', 'close']);

const {
	assets,
	user,
	env,
} = inject('pageContext');

const actors = ref(props.presetActors);
const actorResults = ref([]);
const actorQuery = ref('');

const entities = ref(props.presetEntities);
const entityResults = ref([]);
const entityQuery = ref('');

const tags = ref(props.presetTags);
const tagResults = ref([]);
const tagQuery = ref('');

const scenes = ref(props.presetScenes);

const matches = ref([]);
const matchProperty = ref('title');
const matchExpression = ref('');

const fieldsAnd = ref(true);
const actorAnd = ref(true);
const tagAnd = ref(true);
const matchAnd = ref(true);

const inputs = {};

const fieldsLogicTooltipId = useId();
const addActorDropdownId = useId();
const addTagDropdownId = useId();
const addEntityDropdownId = useId();
const addMatchDropdownId = useId();
const addStashDropdownId = useId();

const notify = ref(JSON.parse(localStorage.getItem('alert_notify')) ?? true);
const email = ref(JSON.parse(localStorage.getItem('alert_email')) ?? false);

const stashes = ref([]);

async function createAlert() {
	const alertLabel = [
		...actors.value.map((actor) => actor.name),
		...tags.value.map((tag) => tag.name),
		...entities.value.map((entity) => entity.name),
		...matches.value.map((match) => match.expression),
		...scenes.value.map((scene) => scene.title),
	].filter(Boolean).join(', ');

	const newAlert = await post('/alerts', {
		all: fieldsAnd.value,
		allActors: actorAnd.value,
		allTags: tagAnd.value,
		allMatches: matchAnd.value,
		actors: actors.value.map((actor) => actor.id),
		tagIds: tags.value.map((tag) => tag.id),
		sceneIds: scenes.value.map((scene) => scene.id),
		matches: matches.value,
		entityIds: entities.value.map((entity) => entity.id),
		notify: notify.value,
		email: email.value,
		stashes: stashes.value.map((stash) => stash.id),
	}, {
		successFeedback: `Alert for '${alertLabel}' set`,
		errorFeedback: `Failed to set alert for '${alertLabel}'`,
		appendErrorMessage: true,
	});

	emit('alert', newAlert);
	emit('close', true);
}

async function searchActors() {
	const res = await get('/actors', {
		q: `${actorQuery.value}*`, // return partial matches
		limit: 10,
	});

	actorResults.value = res.actors;
}

async function searchEntities() {
	const res = await get('/entities', {
		query: entityQuery.value,
		limit: 10,
	});

	entityResults.value = res;
}

async function searchTags() {
	const res = await get('/tags', {
		query: tagQuery.value,
		limit: 10,
	});

	tagResults.value = res;
}

function focusInput(target) {
	setTimeout(() => {
		inputs[target]?.focus();
	}, 100);
}

function selectActor(actor) {
	actors.value.push(actor);
	actorQuery.value = '';
	actorResults.value = [];
}

function selectEntity(entity) {
	entities.value.push(entity);
	entityQuery.value = '';
	entityResults.value = [];
}

function selectTag(tag) {
	tags.value.push(tag);
	tagQuery.value = '';
	tagResults.value = [];
}

function addMatch() {
	matches.value.push({
		property: matchProperty.value,
		expression: matchExpression.value,
	});

	matchProperty.value = 'title';
	matchExpression.value = '';
}

function selectStash(selectedStash) {
	if (!stashes.value.some((stash) => stash.id === selectedStash.id)) {
		stashes.value.push(selectedStash);
	}
}

function rememberThen(domain, checked) {
	localStorage.setItem(`alert_${domain}`, checked);
}
</script>

<template>
	<Dialog
		title="New alert"
		@close="emit('close')"
	>
		<form
			class="dialog-body"
			@submit.prevent="createAlert"
		>
			<div
				v-if="scenes.length > 0"
				class="dialog-section"
			>
				<div class="section-header">
					<h3 class="heading">WHEN RELEASED</h3>
				</div>

				<div
					v-for="scene in scenes"
					:key="`alert-scene-${scene.id}`"
					class="scene"
				>
					<span class="scene-title">{{ scene.title }}</span>

					<span class="scene-details">
						<strong class="scene-date"><time :datetime="scene.date.toISOString()">{{ format(scene.date, 'yyyy-MM-dd') }}</time></strong> on

						<span class="scene-channel">{{ scene.channel?.name || scene.network?.name }}</span>
					</span>
				</div>
			</div>

			<div
				v-else
				class="dialog-section"
			>
				<div class="section-header">
					<h3 class="heading">IF</h3>
				</div>

				<div class="field actors">
					<span
						v-tooltip="{ content: fieldsAnd ? 'The alert is triggered if all fields are matched.' : 'The alert is triggered if any of the fields are matched.', ariaId: fieldsLogicTooltipId }"
						class="field-logic fields-logic noselect"
						@click="fieldsAnd = !fieldsAnd"
					>
						<Icon
							v-show="fieldsAnd"
							icon="link3"
						/>

						<Icon
							v-show="!fieldsAnd"
							icon="unlink3"
						/>
					</span>

					<ul
						class="field-items nolist noselect"
						:class="{ and: actorAnd, or: !actorAnd }"
					>
						<li
							v-for="(actor, index) in actors"
							:key="`actor-${actor.id}`"
							class="field-item actor"
						>
							<div
								v-if="index > 0"
								class="field-logic item-logic"
								@click="actorAnd = !actorAnd"
							>{{ actorAnd ? 'AND' : 'OR' }}</div>

							<div class="field-tile">
								<div class="field-label">{{ actor.name }}</div>
							</div>

							<Icon
								icon="cross2"
								class="field-remove"
								@click="actors = actors.filter((selectedActor) => selectedActor.id !== actor.id)"
							/>
						</li>

						<li class="field-add">
							<VDropdown
								:aria-id="addActorDropdownId"
								placement="auto"
								@show="focusInput('actor')"
							>
								<button
									class="button"
									type="button"
								><Icon icon="plus3" />Add actor</button>

								<template #popper>
									<input
										:ref="(el) => inputs.actor = el"
										v-model="actorQuery"
										class="input"
										@input="searchActors"
									>

									<ul class="nolist">
										<li
											v-for="actor in actorResults"
											:key="`actor-result-${actor.id}`"
											v-close-popper
											class="result-item"
											@click="selectActor(actor)"
										>
											<img
												v-if="actor.avatar"
												class="field-avatar"
												:src="getPath(actor.avatar, 'lazy')"
											>

											<span
												v-else
												class="field-avatar"
											/>

											<div class="result-label">
												{{ actor.name }}
												<template v-if="actor.ageFromBirth || actor.origin?.country">({{ [actor.ageFromBirth, actor.origin?.country?.alpha2].filter(Boolean).join(', ') }})</template>
											</div>
										</li>
									</ul>
								</template>
							</VDropdown>
						</li>
					</ul>
				</div>

				<div class="field tags">
					<span
						class="field-logic noselect"
					>{{ fieldsAnd ? 'AND' : 'OR' }}</span>

					<ul
						class="field-items nolist noselect"
						:class="{ and: actorAnd, or: !actorAnd }"
					>
						<li
							v-for="(tag, index) in tags"
							:key="`tag-${tag.id}`"
							class="field-item tag"
						>
							<div
								v-if="index > 0"
								class="field-logic item-logic"
								@click="tagAnd = !tagAnd"
							>{{ tagAnd ? 'AND' : 'OR' }}</div>

							<div class="field-tile field-label">{{ tag.name }}</div>

							<Icon
								icon="cross2"
								class="field-remove"
								@click="tags = tags.filter((selectedTag) => selectedTag.id !== tag.id)"
							/>
						</li>

						<li class="field-add">
							<VDropdown
								placement="auto"
								:aria-id="addTagDropdownId"
								@show="focusInput('tag')"
							>
								<button
									type="button"
									class="button"
								><Icon icon="plus3" />Add tag</button>

								<template #popper>
									<input
										:ref="(el) => inputs.tag = el"
										v-model="tagQuery"
										class="input"
										@input="searchTags"
									>

									<ul class="nolist">
										<li
											v-for="tag in tagResults"
											:key="`tag-result-${tag.id}`"
											v-close-popper
											class="result-item result-label"
											@click="selectTag(tag)"
										>{{ tag.name }}</li>
									</ul>
								</template>
							</VDropdown>
						</li>
					</ul>
				</div>

				<div class="field entities">
					<span
						class="field-logic noselect"
					>{{ fieldsAnd ? 'AND' : 'OR' }}</span>

					<ul class="field-items nolist noselect">
						<li
							v-for="(entity, index) in entities"
							:key="`entity-${entity.id}`"
							class="field-item entity"
						>
							<div
								v-if="index > 0"
								v-tooltip.click="{
									content: 'Scenes are only associated to one channel, \'AND\' would never match.',
									triggers: ['click'],
									autoHide: true,
									ariaId: `entity-and-tooltip-${entity.id}`,
								}"
								class="field-logic"
							>OR</div>

							<div class="field-tile field-label">
								<Icon :icon="entity.type === 'network' ? 'device_hub' : 'tv'" />
								{{ entity.name }}
							</div>

							<Icon
								icon="cross2"
								class="field-remove"
								@click="entities = entities.filter((selectedEntity) => selectedEntity.id !== entity.id)"
							/>
						</li>

						<li class="field-add">
							<VDropdown
								placement="auto"
								:aria-id="addEntityDropdownId"
								@show="focusInput('entity')"
							>
								<button
									type="button"
									class="button"
								><Icon icon="plus3" />Add channel</button>

								<template #popper>
									<input
										:ref="(el) => inputs.entity = el"
										v-model="entityQuery"
										class="input"
										@input="searchEntities"
									>

									<ul class="nolist">
										<li
											v-for="entity in entityResults"
											:key="`entity-result-${entity.id}`"
											v-close-popper
											class="result-item result-label"
											@click="selectEntity(entity)"
										>
											<Icon :icon="entity.type === 'network' ? 'device_hub' : 'tv'" />

											{{ entity.name }}
										</li>
									</ul>
								</template>
							</VDropdown>
						</li>
					</ul>
				</div>

				<div class="field matches">
					<span
						class="field-logic noselect"
					>{{ fieldsAnd ? 'AND' : 'OR' }}</span>

					<ul class="field-items nolist noselect">
						<li
							v-for="(match, index) in matches"
							:key="`match-${match.property}-${match.expression}`"
							class="field-item match"
						>
							<div
								v-if="index > 0"
								class="field-logic item-logic"
								@click="matchAnd = !matchAnd"
							>{{ matchAnd ? 'AND' : 'OR' }}</div>

							<div class="field-tile field-label">
								<strong>{{ match.property }}:</strong>&nbsp;{{ match.expression }}
							</div>

							<Icon
								icon="cross2"
								class="field-remove"
								@click="matches = matches.filter((selectedEntity, selectedIndex) => selectedIndex !== index)"
							/>
						</li>

						<li class="field-add">
							<VDropdown
								:aria-id="addMatchDropdownId"
								@show="focusInput('expression')"
							>
								<button
									type="button"
									class="button"
								><Icon icon="plus3" />Add expression</button>

								<template #popper>
									<form @submit.prevent="addMatch">
										<select
											v-model="matchProperty"
											class="input"
										>
											<option value="title">Title</option>
											<option value="description">Description</option>
										</select>

										<input
											:ref="(el) => inputs.expression = el"
											v-model="matchExpression"
											placeholder="Expression, // for regex"
											class="input"
										>
									</form>
								</template>
							</VDropdown>
						</li>
					</ul>
				</div>
			</div>

			<div class="dialog-section then">
				<h3 class="heading">THEN</h3>

				<label class="field notify">
					<span>Notify me in traxxx</span>
					<Checkbox
						:checked="notify"
						@change="(checked) => { notify = checked; rememberThen('notify', checked); }"
					/>
				</label>

				<label
					v-if="env.emailEnabled && user.email"
					class="field email"
				>
					<span>E-mail me</span>

					<Checkbox
						:checked="email"
						@change="(checked) => { email = checked; rememberThen('email', checked); }"
					/>
				</label>

				<div
					v-if="scenes.length === 0"
					class="stash"
				>
					<ul class="field-items nolist noselect">
						<li
							v-for="stash in stashes"
							:key="`stash-${stash.id}`"
							class="field-item tag"
						>
							<div class="field-tile field-label stash">
								<Icon
									v-if="stash.isPrimary"
									class="favorites"
									icon="heart7"
								/>{{ stash.name }}
							</div>

							<Icon
								icon="cross2"
								class="field-remove"
								@click="stashes = stashes.filter((selectedStash) => selectedStash.id !== stash.id)"
							/>
						</li>

						<template v-if="stashes.length < assets.stashes.length">
							<li class="field-add">
								<button
									v-if="stashes.length === 0"
									type="button"
									class="button favorites"
									@click="selectStash(assets.primaryStash)"
								><Icon icon="heart7" />Add to favorites</button>
							</li>

							<li class="field-add">
								<VDropdown :aria-id="addStashDropdownId">
									<button
										type="button"
										class="button field-add"
									><Icon icon="folder-heart" />Add to stash</button>

									<template #popper>
										<ul class="nolist">
											<li
												v-for="stash in assets.stashes.filter((stash) => !stashes.some((selectedStash) => selectedStash.id === stash.id))"
												:key="`stash-result-${stash.id}`"
												v-close-popper
												class="result-item result-stash result-label"
												@click="selectStash(stash)"
											>
												{{ stash.name }}
											</li>
										</ul>
									</template>
								</VDropdown>
							</li>
						</template>
					</ul>
				</div>
			</div>

			<div class="dialog-section dialog-actions">
				<button
					class="button button-submit"
				>Set alert</button>
			</div>
		</form>
	</Dialog>
</template>

<style scoped>
.dialog-body {
	width: 30rem;
	max-width: 100%;
	overflow-y: auto;
}

.dialog-section {
	margin-bottom: .5rem;
}

.section-header {
	display: flex;
	justify-content: space-between;
	align-items: stretch;
}

.heading {
	width: 100%;
	color: var(--primary);
	box-sizing: border-box;
	padding: .5rem 1rem;
	margin: 0;
}

.dialog-actions {
	display: flex;
	justify-content: center;
	padding: 1rem;
}

.scene {
	padding: 0 1rem;
}

.scene-title {
	display: block;
	line-height: 1.5;
	margin-bottom: .5rem;
}

.scene-date {
	color: var(--primary);
}

.field {
	display: flex;
	align-items: stretch;
	padding: 0 1rem 0 0;
}

.field-add .button {
	font-weight: normal;
}

.field-add:not(:first-child) {
	margin-left: .75rem;
}

.fields-logic:hover,
.item-logic:hover {
	cursor: pointer;
	color: var(--primary);

	.icon {
		fill: var(--primary);
	}
}

.field-logic {
	display: flex;
	justify-content: center;
	align-items: center;
	flex-shrink: 0;
	width: 3.5rem;
	font-size: .9rem;
	color: var(--glass);

	&.item-logic {
		width: 2.75rem;
	}

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

.field-items {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	flex-grow: 1;
	gap: .5rem 0;
	padding: .5rem 0;
	border-bottom: solid 1px var(--glass-weak-40);

	&.or .field-item::before,
	&.and .field-item::before {
		color: var(--glass);
		padding: 0 .5rem;
	}

	/*
	&.or .field-item:not(:first-child)::before {
		content: 'OR';
	}

	&.and .field-item:not(:first-child)::before {
		content: 'AND';
	}
	*/
}

.field-item {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	position: relative;
	font-size: .9rem;
}

.field-remove {
	width: .75rem;
	height: .75rem;
	position: absolute;
	top: -.5rem;
	right: -.5rem;
	padding: .2rem;
	border-radius: 1rem;
	fill: var(--glass);
	background: var(--background);
	box-shadow: 0 0 3px var(--shadow-weak-20);

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

.field-tile {
	display: flex;
	align-items: center;
	flex-shrink: 0;
	box-shadow: 0 0 3px var(--shadow-weak-30);
}

.field-label {
	padding: .5rem .5rem;
	font-weight: bold;
}

.field-avatar {
	display: inline-block;
	width: 1.5rem;
	height: 2rem;
	object-fit: cover;
	object-position: center 0;
	margin-right: .5rem;
}

.result-item {
	display: flex;
	align-items: center;

	.field-avatar {
		margin: 0;
	}

	.icon {
		margin-right: .5rem;
		transform: translateY(-1px);
	}

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

.result-label {
	padding: .25rem .5rem;
}

.then {
	.field {
		display: flex;
		justify-content: space-between;
		padding: .5rem 1rem;
		border-bottom: solid 1px var(--glass-weak-40);
	}

	.field-items {
		padding: .5rem 1rem;
		gap: .5rem;
	}

	.field-add {
		margin-left: 0;
	}
}

.result-stash {
	padding: .3rem .5rem .3rem .5rem;

	&:first-child {
		padding-top: .5rem;
	}
}

.field-tile .icon {
	margin-right: .5rem;
}

.field-tile.stash {
	font-weight: bold;
}

.field.notify,
.field.email {
	cursor: pointer;
}
</style>
