<template>
	<NcSettingsSection
		name="Deck Workflow-Automatisierung"
		description="Verschiebt überfällige Karten aus einem Deck-Stapel automatisch in einen anderen Stapel. Ein Hintergrundjob prüft die Regeln alle paar Minuten.">
		<NcNoteCard v-if="loadError" type="error">
			{{ loadError }}
		</NcNoteCard>

		<div v-if="loading" class="wfda-loading">
			<NcLoadingIcon :size="32" />
		</div>

		<template v-else>
			<table v-if="workflows.length" class="wfda-table">
				<thead>
					<tr>
						<th>Titel</th>
						<th>Von Stapel</th>
						<th>Nach Stapel</th>
						<th>Filter</th>
						<th>E-Mail</th>
						<th>Aktiv</th>
						<th />
					</tr>
				</thead>
				<tbody>
					<tr v-for="workflow in workflows" :key="workflow.id">
						<td>{{ workflow.title }}</td>
						<td>{{ stackLabel(workflow.boardId, workflow.sourceStackId) }}</td>
						<td>{{ stackLabel(workflow.boardId, workflow.targetStackId) }}</td>
						<td>
							<span v-if="!workflow.filterUserIds.length && !workflow.filterLabelIds.length">–</span>
							<span v-else>
								<span v-if="workflow.filterUserIds.length">{{ workflow.filterUserIds.length }} Benutzer</span>
								<span v-if="workflow.filterUserIds.length && workflow.filterLabelIds.length">, </span>
								<span v-if="workflow.filterLabelIds.length">{{ workflow.filterLabelIds.length }} Label</span>
							</span>
						</td>
						<td>{{ workflow.notifyEmail ? 'Ja' : 'Nein' }}</td>
						<td>{{ workflow.enabled ? 'Ja' : 'Nein' }}</td>
						<td class="wfda-actions">
							<NcButton type="tertiary" @click="editWorkflow(workflow)">
								Bearbeiten
							</NcButton>
							<NcButton type="tertiary" @click="removeWorkflow(workflow)">
								Löschen
							</NcButton>
						</td>
					</tr>
				</tbody>
			</table>
			<p v-else class="wfda-empty">
				Noch keine Workflows angelegt.
			</p>

			<NcButton v-if="!showForm" type="primary" class="wfda-add-button" @click="startCreate">
				Workflow hinzufügen
			</NcButton>

			<form v-if="showForm" class="wfda-form" @submit.prevent="save">
				<NcTextField
					:value.sync="form.title"
					label="Titel"
					required />

				<NcSelect
					v-model="form.boardId"
					label="Board"
					:options="boardOptions"
					:reduce="option => option.value"
					placeholder="Board wählen"
					@update:model-value="onBoardChange" />

				<NcSelect
					v-model="form.sourceStackId"
					label="Quell-Stapel"
					:options="stackOptions"
					:reduce="option => option.value"
					:disabled="!form.boardId"
					placeholder="Quell-Stapel wählen" />

				<NcSelect
					v-model="form.targetStackId"
					label="Ziel-Stapel"
					:options="stackOptions"
					:reduce="option => option.value"
					:disabled="!form.boardId"
					placeholder="Ziel-Stapel wählen" />

				<NcSelect
					v-model="form.filterUserIds"
					label="Nur für zugewiesene Benutzer (optional)"
					:options="participantOptions"
					:reduce="option => option.value"
					:disabled="!form.boardId"
					multiple
					placeholder="Alle Benutzer" />

				<NcSelect
					v-model="form.filterLabelIds"
					label="Nur mit Label (optional)"
					:options="labelOptions"
					:reduce="option => option.value"
					:disabled="!form.boardId"
					multiple
					placeholder="Alle Labels" />

				<NcCheckboxRadioSwitch :checked.sync="form.notifyEmail">
					Benachrichtigungs-E-Mail an mich senden
				</NcCheckboxRadioSwitch>

				<NcCheckboxRadioSwitch :checked.sync="form.enabled">
					Workflow aktiv
				</NcCheckboxRadioSwitch>

				<NcNoteCard v-if="formError" type="error">
					{{ formError }}
				</NcNoteCard>

				<div class="wfda-form-actions">
					<NcButton type="primary" native-type="submit" :disabled="saving">
						Speichern
					</NcButton>
					<NcButton type="tertiary" :disabled="saving" @click="cancelForm">
						Abbrechen
					</NcButton>
				</div>
			</form>
		</template>
	</NcSettingsSection>
</template>

<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcTextField from '@nextcloud/vue/components/NcTextField'
import NcSelect from '@nextcloud/vue/components/NcSelect'
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
import {
	createWorkflow,
	deleteWorkflow,
	fetchBoards,
	fetchLabels,
	fetchParticipants,
	fetchStacks,
	fetchWorkflows,
	updateWorkflow,
} from './api.js'

const loading = ref(true)
const loadError = ref('')
const workflows = ref([])
const boards = ref([])
const stacksByBoard = reactive({})

const showForm = ref(false)
const saving = ref(false)
const formError = ref('')
const editingId = ref(null)

const stackOptions = ref([])
const labelOptions = ref([])
const participantOptions = ref([])

const boardOptions = computed(() => boards.value.map((board) => ({ value: board.id, label: board.title })))

const form = reactive(emptyForm())

function emptyForm() {
	return {
		title: '',
		boardId: null,
		sourceStackId: null,
		targetStackId: null,
		filterUserIds: [],
		filterLabelIds: [],
		notifyEmail: false,
		enabled: true,
	}
}

function stackLabel(boardId, stackId) {
	const stacks = stacksByBoard[boardId]
	if (!stacks) {
		return `#${stackId}`
	}
	const stack = stacks.find((entry) => entry.id === stackId)
	return stack ? stack.title : `#${stackId}`
}

async function loadStacksFor(boardId) {
	if (!boardId || stacksByBoard[boardId]) {
		return
	}
	try {
		stacksByBoard[boardId] = await fetchStacks(boardId)
	} catch (e) {
		stacksByBoard[boardId] = []
	}
}

async function loadAll() {
	loading.value = true
	loadError.value = ''
	try {
		const [loadedWorkflows, loadedBoards] = await Promise.all([fetchWorkflows(), fetchBoards()])
		workflows.value = loadedWorkflows
		boards.value = loadedBoards
		await Promise.all(loadedWorkflows.map((workflow) => loadStacksFor(workflow.boardId)))
	} catch (e) {
		loadError.value = 'Konnte Workflows oder Deck-Boards nicht laden. Ist die Deck-App aktiviert?'
	} finally {
		loading.value = false
	}
}

async function onBoardChange(boardId) {
	form.sourceStackId = null
	form.targetStackId = null
	form.filterUserIds = []
	form.filterLabelIds = []
	stackOptions.value = []
	labelOptions.value = []
	participantOptions.value = []

	if (!boardId) {
		return
	}

	const [stacks, labels, participants] = await Promise.all([
		fetchStacks(boardId),
		fetchLabels(boardId),
		fetchParticipants(boardId),
	])

	stacksByBoard[boardId] = stacks
	stackOptions.value = stacks.map((stack) => ({ value: stack.id, label: stack.title }))
	labelOptions.value = labels.map((label) => ({ value: label.id, label: label.title }))
	participantOptions.value = participants.map((participant) => ({ value: participant.uid, label: participant.displayName }))
}

function startCreate() {
	Object.assign(form, emptyForm())
	editingId.value = null
	formError.value = ''
	stackOptions.value = []
	labelOptions.value = []
	participantOptions.value = []
	showForm.value = true
}

async function editWorkflow(workflow) {
	Object.assign(form, {
		title: workflow.title,
		boardId: workflow.boardId,
		sourceStackId: workflow.sourceStackId,
		targetStackId: workflow.targetStackId,
		filterUserIds: [...workflow.filterUserIds],
		filterLabelIds: [...workflow.filterLabelIds],
		notifyEmail: workflow.notifyEmail,
		enabled: workflow.enabled,
	})
	editingId.value = workflow.id
	formError.value = ''
	showForm.value = true
	await onBoardChange(workflow.boardId)
}

function cancelForm() {
	showForm.value = false
	formError.value = ''
}

async function save() {
	formError.value = ''
	if (!form.title.trim()) {
		formError.value = 'Bitte einen Titel angeben.'
		return
	}
	if (!form.boardId || !form.sourceStackId || !form.targetStackId) {
		formError.value = 'Bitte Board, Quell- und Ziel-Stapel wählen.'
		return
	}
	if (form.sourceStackId === form.targetStackId) {
		formError.value = 'Quell- und Ziel-Stapel müssen sich unterscheiden.'
		return
	}

	saving.value = true
	try {
		if (editingId.value) {
			await updateWorkflow(editingId.value, form)
		} else {
			await createWorkflow(form)
		}
		showForm.value = false
		await loadAll()
	} catch (e) {
		formError.value = e?.response?.data?.ocs?.meta?.message || 'Speichern fehlgeschlagen.'
	} finally {
		saving.value = false
	}
}

async function removeWorkflow(workflow) {
	// eslint-disable-next-line no-alert
	if (!window.confirm(`Workflow "${workflow.title}" wirklich löschen?`)) {
		return
	}
	await deleteWorkflow(workflow.id)
	await loadAll()
}

onMounted(loadAll)
</script>

<style scoped>
.wfda-loading {
	display: flex;
	justify-content: center;
	padding: 20px;
}

.wfda-table {
	width: 100%;
	border-collapse: collapse;
	margin-bottom: 16px;
}

.wfda-table th,
.wfda-table td {
	text-align: left;
	padding: 8px 12px;
	border-bottom: 1px solid var(--color-border);
}

.wfda-actions {
	display: flex;
	gap: 4px;
	justify-content: flex-end;
}

.wfda-empty {
	color: var(--color-text-maxcontrast);
	margin-bottom: 16px;
}

.wfda-add-button {
	margin-bottom: 16px;
}

.wfda-form {
	display: flex;
	flex-direction: column;
	gap: 12px;
	max-width: 480px;
	padding: 16px;
	border: 1px solid var(--color-border);
	border-radius: var(--border-radius-large);
}

.wfda-form-actions {
	display: flex;
	gap: 8px;
}
</style>
