<script lang="ts" setup>
import {ref, watch} from 'vue'

import type {IWebhook} from '@/modelTypes/IWebhook'
import WebhookModel from '@/models/webhook'
import BaseButton from '@/components/base/BaseButton.vue'
import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import FormField from '@/components/input/FormField.vue'
import Expandable from '@/components/base/Expandable.vue'
import User from '@/components/misc/User.vue'
import {formatDateShort} from '@/helpers/time/formatDate'
import {isValidHttpUrl} from '@/helpers/isValidHttpUrl'

const props = defineProps<{
	webhooks: IWebhook[]
	availableEvents: string[]
	loading?: boolean
}>()

const emit = defineEmits<{
	create: [webhook: IWebhook]
	delete: [webhookId: number]
}>()

defineOptions({name: 'WebhookManager'})

const showNewForm = ref(false)
const showBasicAuth = ref(false)
const newWebhook = ref(new WebhookModel())
const newWebhookEvents = ref<Record<string, boolean>>({})

function initEvents(events: string[]) {
	newWebhookEvents.value = Object.fromEntries(
		events.map(event => [event, false]),
	)
}

watch(() => props.availableEvents, (events) => {
	if (events) initEvents(events)
}, {immediate: true})

const webhookTargetUrlValid = ref(true)
const selectedEventsValid = ref(true)
const showDeleteModal = ref(false)
const webhookIdToDelete = ref<number>()

function validateTargetUrl() {
	webhookTargetUrlValid.value = isValidHttpUrl(newWebhook.value.targetUrl)
}

function getSelectedEventsArray() {
	return Object.entries(newWebhookEvents.value)
		.filter(([, use]) => use)
		.map(([event]) => event)
}

function validateSelectedEvents() {
	const events = getSelectedEventsArray()
	selectedEventsValid.value = events.length > 0
}

function create() {
	validateTargetUrl()
	if (!webhookTargetUrlValid.value) {
		return
	}

	const selectedEvents = getSelectedEventsArray()
	newWebhook.value.events = selectedEvents

	validateSelectedEvents()
	if (!selectedEventsValid.value) {
		return
	}

	emit('create', newWebhook.value)
	newWebhook.value = new WebhookModel()
	initEvents(props.availableEvents)
	showNewForm.value = false
}

function confirmDelete(webhookId: number) {
	webhookIdToDelete.value = webhookId
	showDeleteModal.value = true
}

function doDelete() {
	if (webhookIdToDelete.value) {
		emit('delete', webhookIdToDelete.value)
	}
	showDeleteModal.value = false
}
</script>

<template>
	<div>
		<XButton
			v-if="!(webhooks?.length === 0 || showNewForm)"
			icon="plus"
			class="mbe-4"
			@click="showNewForm = true"
		>
			{{ $t('project.webhooks.create') }}
		</XButton>

		<div
			v-if="webhooks?.length === 0 || showNewForm"
			class="p-4"
		>
			<FormField
				id="targetUrl"
				v-model="newWebhook.targetUrl"
				:label="$t('project.webhooks.targetUrl')"
				required
				:placeholder="$t('project.webhooks.targetUrl')"
				:error="webhookTargetUrlValid ? null : $t('project.webhooks.targetUrlInvalid')"
				@focusout="validateTargetUrl"
			/>
			<div class="field">
				<label
					class="label"
					for="secret"
				>
					{{ $t('project.webhooks.secret') }}
				</label>
				<div class="control">
					<input
						id="secret"
						v-model="newWebhook.secret"
						class="input"
					>
				</div>
				<p class="help">
					{{ $t('project.webhooks.secretHint') }}
					<BaseButton href="https://vikunja.io/docs/webhooks/">
						{{ $t('project.webhooks.secretDocs') }}
					</BaseButton>
				</p>
			</div>
			<BaseButton
				class="mbe-2 has-text-primary"
				@click="showBasicAuth = !showBasicAuth"
			>
				{{ $t('project.webhooks.basicauthlink') }}
			</BaseButton>
			<Expandable
				:open="showBasicAuth"
				class="content"
			>
				<div class="field">
					<label
						class="label"
						for="basicauthuser"
					>
						{{ $t('project.webhooks.basicauthuser') }}
					</label>
					<div class="control">
						<input
							id="basicauthuser"
							v-model="newWebhook.basicauthuser"
							class="input"
						>
					</div>
				</div>
				<div class="field">
					<label
						class="label"
						for="basicauthpassword"
					>
						{{ $t('project.webhooks.basicauthpassword') }}
					</label>
					<div class="control">
						<input
							id="basicauthpassword"
							v-model="newWebhook.basicauthpassword"
							class="input"
						>
					</div>
				</div>
			</Expandable>
			<div class="field">
				<label
					class="label"
					for="events"
				>
					{{ $t('project.webhooks.events') }}
				</label>
				<p class="help">
					{{ $t('project.webhooks.eventsHint') }}
				</p>
				<div class="control">
					<FancyCheckbox
						v-for="event in availableEvents"
						:key="event"
						v-model="newWebhookEvents[event]"
						class="available-events-check"
						@update:modelValue="validateSelectedEvents"
					>
						{{ event }}
					</FancyCheckbox>
				</div>
				<p
					v-if="!selectedEventsValid"
					class="help is-danger"
				>
					{{ $t('project.webhooks.mustSelectEvents') }}
				</p>
			</div>
			<XButton
				icon="plus"
				@click="create"
			>
				{{ $t('project.webhooks.create') }}
			</XButton>
		</div>

		<table
			v-if="webhooks?.length > 0"
			class="table has-actions is-striped is-hoverable is-fullwidth"
		>
			<thead>
				<tr>
					<th>{{ $t('project.webhooks.targetUrl') }}</th>
					<th>{{ $t('project.webhooks.events') }}</th>
					<th>{{ $t('misc.created') }}</th>
					<th>{{ $t('misc.createdBy') }}</th>
					<th />
				</tr>
			</thead>
			<tbody>
				<tr
					v-for="w in webhooks"
					:key="w.id"
				>
					<td>{{ w.targetUrl }}</td>
					<td>{{ w.events.join(', ') }}</td>
					<td>{{ formatDateShort(w.created) }}</td>
					<td>
						<User
							:avatar-size="25"
							:user="w.createdBy"
						/>
					</td>

					<td class="actions">
						<XButton
							danger
							icon="trash-alt"
							@click="() => confirmDelete(w.id)"
						/>
					</td>
				</tr>
			</tbody>
		</table>

		<Modal
			:enabled="showDeleteModal"
			@close="showDeleteModal = false"
			@submit="doDelete()"
		>
			<template #header>
				<span>{{ $t('project.webhooks.delete') }}</span>
			</template>

			<template #text>
				<p>{{ $t('project.webhooks.deleteText') }}</p>
			</template>
		</Modal>
	</div>
</template>

<style lang="scss" scoped>
.available-events-check {
	margin-inline-end: .5rem;
	inline-size: 12.5rem;
}
</style>
