<template>
	<div class="query-view">
		<div class="query-view__header">
			<h2>Abfrage-Builder</h2>
		</div>

		<div class="query-view__layout">
			<!-- Sidebar: Saved queries -->
			<div class="query-view__sidebar">
				<h3>Gespeicherte Abfragen</h3>
				<NcLoadingIcon v-if="store.loading && store.savedQueries.length === 0" :size="32" />
				<div v-else-if="store.savedQueries.length === 0" class="query-view__sidebar-empty">
					Noch keine gespeicherten Abfragen.
				</div>
				<div v-else class="query-view__saved-list">
					<button v-for="sq in store.savedQueries"
						:key="sq.id"
						:class="['query-view__saved-item', { 'query-view__saved-item--active': activeSavedId === sq.id }]"
						@click="loadSavedQuery(sq)">
						<span class="query-view__saved-name">{{ sq.name }}</span>
						<NcButton type="error"
							class="query-view__saved-delete"
							@click.stop="deleteSavedQuery(sq.id)">
							<template #icon>
								<Delete :size="16" />
							</template>
						</NcButton>
					</button>
				</div>
			</div>

			<!-- Main content -->
			<div class="query-view__main">
				<!-- Query builder component -->
				<QueryBuilderComponent v-model="queryAst"
					:fields="store.fields" />

				<!-- Action bar -->
				<div class="query-view__actions">
					<NcButton type="primary"
						:disabled="store.loading"
						@click="executeQuery">
						<template #icon>
							<Play :size="20" />
						</template>
						Abfrage ausführen
					</NcButton>
					<NcButton @click="showSaveDialog = true">
						<template #icon>
							<ContentSave :size="20" />
						</template>
						Speichern
					</NcButton>
					<NcButton type="tertiary" @click="resetQuery">
						Zurücksetzen
					</NcButton>
				</div>

				<!-- Save dialog -->
				<div v-if="showSaveDialog" class="query-view__save-dialog">
					<input v-model="saveName"
						type="text"
						class="query-view__save-input"
						placeholder="Name der Abfrage..."
						@keyup.enter="saveQuery">
					<NcButton type="primary" :disabled="!saveName.trim()" @click="saveQuery">
						Speichern
					</NcButton>
					<NcButton @click="showSaveDialog = false">
						Abbrechen
					</NcButton>
				</div>

				<!-- Error -->
				<div v-if="store.error" class="query-view__error">
					{{ store.error }}
				</div>

				<!-- Results -->
				<div v-if="store.results.length > 0 || hasExecuted" class="query-view__results">
					<h3>Ergebnisse ({{ store.total }})</h3>

					<NcEmptyContent v-if="store.results.length === 0 && hasExecuted"
						name="Keine Ergebnisse"
						description="Die Abfrage hat keine Mitglieder gefunden." />

					<template v-else>
						<div class="query-view__results-actions">
							<ColumnPicker :columns="resultColumns"
								:model-value="visibleKeys"
								@update:model-value="setVisibleKeys" />
						</div>
						<table class="query-view__table">
						<thead>
							<tr>
								<th v-for="col in visibleResultColumns" :key="col.key">{{ col.label }}</th>
							</tr>
						</thead>
						<tbody>
							<tr v-for="member in store.results"
								:key="member.id"
								class="query-view__result-row"
								@click="openMember(member.id)">
								<td v-for="col in visibleResultColumns" :key="col.key">
									<span v-if="col.key === 'status'"
										:class="'query-view__status query-view__status--' + member.status">
										{{ col.render(member) }}
									</span>
									<template v-else>{{ col.render(member) }}</template>
								</td>
							</tr>
						</tbody>
					</table>
					</template>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { NcButton, NcEmptyContent, NcLoadingIcon } from '@nextcloud/vue'
import { useQueriesStore } from '../stores/queries.js'
import { useColumnVisibility } from '../utils/useColumnVisibility.js'
import ColumnPicker from '../components/ColumnPicker.vue'
import QueryBuilderComponent from '../components/QueryBuilder.vue'
import Delete from 'vue-material-design-icons/Delete.vue'
import Play from 'vue-material-design-icons/Play.vue'
import ContentSave from 'vue-material-design-icons/ContentSave.vue'
import { formatDate } from '../utils/dateFormat.js'

const router = useRouter()
const store = useQueriesStore()

const queryAst = ref({ and: [] })
const activeSavedId = ref(null)
const showSaveDialog = ref(false)
const saveName = ref('')
const hasExecuted = ref(false)

const rolleMap = { mitglied: 'Mitglied', erziehungsberechtigter: 'Erziehungsberechtigter' }
const statusMap = { aktiv: 'Aktiv', inaktiv: 'Inaktiv', geloescht: 'Gelöscht' }

const resultColumns = [
	{ key: 'nachname', label: 'Nachname', alwaysVisible: true, render: m => m.nachname },
	{ key: 'vorname', label: 'Vorname', render: m => m.vorname },
	{ key: 'geburtsdatum', label: 'Geburtsdatum', render: m => formatDate(m.geburtsdatum) },
	{ key: 'rolle', label: 'Rolle', render: m => rolleMap[m.rolle] || m.rolle },
	{ key: 'status', label: 'Status', render: m => statusMap[m.status] || m.status },
	{ key: 'eintritt', label: 'Eintritt', render: m => formatDate(m.eintritt) },
	{ key: 'austritt', label: 'Austritt', render: m => formatDate(m.austritt) },
]

const { visibleKeys, visibleColumns: visibleResultColumns, setVisibleKeys } = useColumnVisibility(
	'mv_query_columns',
	resultColumns,
	['nachname', 'vorname', 'geburtsdatum', 'rolle', 'status', 'eintritt'],
)

onMounted(async () => {
	await Promise.all([
		store.fetchFields(),
		store.fetchSavedQueries(),
	])
})

async function executeQuery() {
	hasExecuted.value = true
	await store.executeAdHoc(queryAst.value)
}

function loadSavedQuery(sq) {
	activeSavedId.value = sq.id
	queryAst.value = sq.queryJson || { and: [] }
	hasExecuted.value = false
	store.clearResults()
}

async function saveQuery() {
	if (!saveName.value.trim()) return

	try {
		if (activeSavedId.value) {
			await store.updateQuery(activeSavedId.value, {
				name: saveName.value.trim(),
				queryJson: queryAst.value,
			})
		} else {
			const saved = await store.saveQuery(saveName.value.trim(), queryAst.value)
			activeSavedId.value = saved.id
		}
		showSaveDialog.value = false
		saveName.value = ''
	} catch {
		// Error shown in store
	}
}

async function deleteSavedQuery(id) {
	if (confirm('Abfrage wirklich löschen?')) {
		await store.deleteQuery(id)
		if (activeSavedId.value === id) {
			activeSavedId.value = null
			queryAst.value = { and: [] }
			store.clearResults()
		}
	}
}

function resetQuery() {
	queryAst.value = { and: [] }
	activeSavedId.value = null
	hasExecuted.value = false
	store.clearResults()
}

// formatDate imported from utils/dateFormat.js

function openMember(id) {
	router.push({ name: 'member-detail', params: { id } })
}
</script>

<style scoped>
.query-view {
	padding: 20px;
}

.query-view__header h2 {
	margin: 0 0 20px 0;
}

.query-view__layout {
	display: flex;
	gap: 24px;
}

.query-view__sidebar {
	width: 250px;
	flex-shrink: 0;
}

.query-view__sidebar h3 {
	margin: 0 0 12px 0;
	font-size: 0.95em;
}

.query-view__sidebar-empty {
	color: var(--color-text-lighter);
	font-size: 0.9em;
}

.query-view__saved-list {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.query-view__saved-item {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 8px 12px;
	border: 1px solid var(--color-border);
	border-radius: var(--border-radius);
	background: none;
	cursor: pointer;
	text-align: left;
	transition: background-color 0.15s ease;
}

.query-view__saved-item:hover {
	background: var(--color-background-hover);
}

.query-view__saved-item--active {
	background: var(--color-primary-light);
	border-color: var(--color-primary);
}

.query-view__saved-name {
	font-size: 0.9em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.query-view__saved-delete {
	flex-shrink: 0;
	opacity: 0;
	transition: opacity 0.15s;
}

.query-view__saved-item:hover .query-view__saved-delete {
	opacity: 1;
}

.query-view__main {
	flex: 1;
	min-width: 0;
}

.query-view__actions {
	display: flex;
	gap: 12px;
	margin-top: 16px;
	flex-wrap: wrap;
}

.query-view__save-dialog {
	display: flex;
	gap: 8px;
	align-items: center;
	margin-top: 12px;
	padding: 12px;
	background: var(--color-background-dark);
	border-radius: var(--border-radius);
}

.query-view__save-input {
	padding: 6px 10px;
	border: 1px solid var(--color-border);
	border-radius: var(--border-radius);
	flex: 1;
	font-size: 0.9em;
}

.query-view__error {
	margin-top: 12px;
	padding: 10px 14px;
	background: var(--color-error);
	color: white;
	border-radius: var(--border-radius);
	font-size: 0.9em;
}

.query-view__results {
	margin-top: 24px;
}

.query-view__results h3 {
	margin: 0 0 12px 0;
}

.query-view__results-actions {
	display: flex;
	justify-content: flex-end;
	margin-bottom: 8px;
}

.query-view__table {
	width: 100%;
	border-collapse: collapse;
}

.query-view__table th {
	text-align: left;
	padding: 8px 12px;
	font-weight: 600;
	font-size: 0.85em;
	color: var(--color-text-lighter);
	border-bottom: 2px solid var(--color-border);
}

.query-view__result-row {
	cursor: pointer;
	transition: background-color 0.15s ease;
}

.query-view__result-row:hover {
	background: var(--color-background-hover);
}

.query-view__result-row td {
	padding: 8px 12px;
	border-bottom: 1px solid var(--color-border);
	font-size: 0.9em;
}

.query-view__status {
	display: inline-block;
	padding: 2px 8px;
	border-radius: var(--border-radius-pill);
	font-size: 0.85em;
	font-weight: 500;
}

.query-view__status--aktiv {
	background-color: var(--color-success);
	color: white;
}

.query-view__status--inaktiv {
	background-color: var(--color-warning);
	color: white;
}
</style>
