<script lang="ts">
	import { api } from '$lib/api';
	import { onMount } from 'svelte';
	import type { Veranstaltungsort, OrtAusfall } from '$lib/types';

	let orte     = $state<Veranstaltungsort[]>([]);
	let ausfaelle = $state<OrtAusfall[]>([]);
	let loading  = $state(true);

	// Ort-Formular
	let showOrtForm = $state(false);
	let editOrtId   = $state<string | null>(null);
	let fName       = $state('');
	let fAdresse    = $state('');
	let fTyp        = $state<Veranstaltungsort['typ']>('halle');
	let fAktiv      = $state(true);
	let ortSaving   = $state(false);
	let ortError    = $state('');

	// Ausfall-Formular
	let showAusfallForm = $state(false);
	let aOrtId          = $state('');
	let aVon            = $state('');
	let aBis            = $state('');
	let aGrund          = $state('');
	let ausfallSaving   = $state(false);
	let ausfallError    = $state('');

	const typLabel: Record<string, string> = {
		halle: 'Halle', platz: 'Platz', gebaeude: 'Gebäude', sonstiges: 'Sonstiges',
	};

	onMount(async () => {
		[orte, ausfaelle] = await Promise.all([
			api.get<Veranstaltungsort[]>('/orte', { sort: 'name' }),
			api.get<OrtAusfall[]>('/ort-ausfaelle', { sort: 'von' }),
		]);
		loading = false;
	});

	function neuerOrt() {
		editOrtId = null; fName = ''; fAdresse = ''; fTyp = 'halle'; fAktiv = true;
		ortError = ''; showOrtForm = true;
	}

	function bearbeitenOrt(o: Veranstaltungsort) {
		editOrtId = o.id; fName = o.name; fAdresse = o.adresse ?? '';
		fTyp = o.typ ?? 'halle'; fAktiv = o.aktiv;
		ortError = ''; showOrtForm = true;
	}

	async function ortSpeichern() {
		if (!fName.trim()) { ortError = 'Name ist Pflichtfeld.'; return; }
		ortError = ''; ortSaving = true;
		try {
			const data = { name: fName.trim(), adresse: fAdresse.trim() || null, typ: fTyp, aktiv: fAktiv };
			if (editOrtId) {
				const u = await api.put<Veranstaltungsort>('/orte/' + editOrtId, data);
				orte = orte.map(o => o.id === editOrtId ? u : o);
			} else {
				const n = await api.post<Veranstaltungsort>('/orte', data);
				orte = [...orte, n].sort((a, b) => a.name.localeCompare(b.name));
			}
			showOrtForm = false;
		} catch (e: unknown) {
			ortError = e instanceof Error ? e.message : 'Fehler.';
		} finally {
			ortSaving = false;
		}
	}

	async function ortLoeschen(id: string) {
		if (!confirm('Ort wirklich löschen? Alle verknüpften Termine verlieren die Ortzuordnung.')) return;
		await api.del('/orte/' + id);
		orte = orte.filter(o => o.id !== id);
		ausfaelle = ausfaelle.filter(a => a.ort_id !== id);
	}

	function ausfallErstellen(ortId: string) {
		aOrtId = ortId; aVon = ''; aBis = ''; aGrund = '';
		ausfallError = ''; showAusfallForm = true;
	}

	async function ausfallSpeichern() {
		if (!aVon || !aBis) { ausfallError = 'Von und Bis sind Pflichtfelder.'; return; }
		if (aVon > aBis)    { ausfallError = 'Bis muss nach Von liegen.'; return; }
		ausfallError = ''; ausfallSaving = true;
		try {
			const n = await api.post<OrtAusfall>('/ort-ausfaelle', {
				ort_id: aOrtId, von: aVon, bis: aBis, grund: aGrund.trim() || null,
			});
			ausfaelle = [...ausfaelle, n].sort((a, b) => a.von.localeCompare(b.von));
			showAusfallForm = false;
		} catch (e: unknown) {
			ausfallError = e instanceof Error ? e.message : 'Fehler.';
		} finally {
			ausfallSaving = false;
		}
	}

	async function ausfallLoeschen(id: string) {
		await api.del('/ort-ausfaelle/' + id);
		ausfaelle = ausfaelle.filter(a => a.id !== id);
	}

	function ortName(id: string) {
		return orte.find(o => o.id === id)?.name ?? '—';
	}

	function formatDatum(iso: string) {
		return new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' });
	}

	// Ort ist aktuell gesperrt?
	function istGesperrt(o: Veranstaltungsort): OrtAusfall | undefined {
		const heute = new Date().toISOString().slice(0, 10);
		return ausfaelle.find(a => a.ort_id === o.id && a.von <= heute && a.bis >= heute);
	}
</script>

<svelte:head><title>Veranstaltungsorte — vereins.haus</title></svelte:head>

<div class="top">
	<div>
		<a class="back" href="/termine">← Termine</a>
		<h1>Veranstaltungsorte</h1>
	</div>
	<button class="btn-primary" onclick={neuerOrt}>+ Ort</button>
</div>

{#if loading}
	<p class="hint">Laden…</p>
{:else if orte.length === 0}
	<p class="hint">Noch keine Orte angelegt.</p>
{:else}
	<ul class="liste">
		{#each orte as o (o.id)}
			{@const gesperrt = istGesperrt(o)}
			<li class="karte" class:inaktiv={!o.aktiv}>
				<div class="ort-info">
					<div class="ort-name-zeile">
						<span class="ort-name">{o.name}</span>
						{#if !o.aktiv}
							<span class="badge grau">Inaktiv</span>
						{:else if gesperrt}
							<span class="badge rot">Gesperrt</span>
						{:else}
							<span class="badge gruen">Verfügbar</span>
						{/if}
					</div>
					{#if o.adresse}<span class="ort-meta">{o.adresse}</span>{/if}
					{#if o.typ}<span class="ort-meta">{typLabel[o.typ]}</span>{/if}
					{#if gesperrt}
						<span class="gesperrt-hinweis">
							Gesperrt bis {formatDatum(gesperrt.bis)}{gesperrt.grund ? ' · ' + gesperrt.grund : ''}
						</span>
					{/if}
				</div>
				<div class="ort-aktionen">
					<button class="btn-ausfall" onclick={() => ausfallErstellen(o.id)} title="Ausfall eintragen">Ausfall</button>
					<button class="btn-icon" onclick={() => bearbeitenOrt(o)}>✎</button>
					<button class="btn-icon btn-icon-red" onclick={() => ortLoeschen(o.id)}>✕</button>
				</div>
			</li>
		{/each}
	</ul>
{/if}

<!-- Ausfälle -->
{#if ausfaelle.length > 0}
	<h2 class="section-title">Geplante Ausfälle</h2>
	<ul class="liste">
		{#each ausfaelle as a (a.id)}
			<li class="ausfall-karte">
				<div class="ausfall-info">
					<span class="ausfall-ort">{ortName(a.ort_id)}</span>
					<span class="ausfall-zeitraum">{formatDatum(a.von)} – {formatDatum(a.bis)}</span>
					{#if a.grund}<span class="ausfall-grund">{a.grund}</span>{/if}
				</div>
				<button class="btn-icon btn-icon-red" onclick={() => ausfallLoeschen(a.id)}>✕</button>
			</li>
		{/each}
	</ul>
{/if}

<!-- Ort-Formular -->
{#if showOrtForm}
	<div class="overlay" role="dialog" aria-modal="true">
		<div class="sheet">
			<h2>{editOrtId ? 'Ort bearbeiten' : 'Neuer Ort'}</h2>
			<form onsubmit={(e) => { e.preventDefault(); ortSpeichern(); }}>
				<div class="field">
					<label for="fname">Name *</label>
					<input id="fname" type="text" bind:value={fName} placeholder="z. B. Turnhalle Schillerschule" required />
				</div>
				<div class="field">
					<label for="fadresse">Adresse</label>
					<input id="fadresse" type="text" bind:value={fAdresse} placeholder="Musterstraße 1, 12345 Stadt" />
				</div>
				<div class="row">
					<div class="field">
						<label for="ftyp">Typ</label>
						<select id="ftyp" bind:value={fTyp}>
							<option value="halle">Halle</option>
							<option value="platz">Platz</option>
							<option value="gebaeude">Gebäude</option>
							<option value="sonstiges">Sonstiges</option>
						</select>
					</div>
					<div class="field" style="justify-content:flex-end;padding-bottom:0.85rem">
						<label class="toggle-label">
							<input type="checkbox" bind:checked={fAktiv} />
							Aktiv
						</label>
					</div>
				</div>
				{#if ortError}<p class="error">{ortError}</p>{/if}
				<div class="actions">
					<button type="button" class="btn-ghost" onclick={() => showOrtForm = false}>Abbrechen</button>
					<button type="submit" class="btn-primary" disabled={ortSaving}>{ortSaving ? 'Speichern…' : 'Speichern'}</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- Ausfall-Formular -->
{#if showAusfallForm}
	<div class="overlay" role="dialog" aria-modal="true">
		<div class="sheet">
			<h2>Ausfall eintragen</h2>
			<p class="sheet-sub">{ortName(aOrtId)}</p>
			<form onsubmit={(e) => { e.preventDefault(); ausfallSpeichern(); }}>
				<div class="row">
					<div class="field">
						<label for="avon">Von *</label>
						<input id="avon" type="date" bind:value={aVon} required />
					</div>
					<div class="field">
						<label for="abis">Bis *</label>
						<input id="abis" type="date" bind:value={aBis} required />
					</div>
				</div>
				<div class="field">
					<label for="agrund">Grund</label>
					<input id="agrund" type="text" bind:value={aGrund} placeholder="z. B. Schulveranstaltung, Wartung" />
				</div>
				{#if ausfallError}<p class="error">{ausfallError}</p>{/if}
				<div class="actions">
					<button type="button" class="btn-ghost" onclick={() => showAusfallForm = false}>Abbrechen</button>
					<button type="submit" class="btn-primary" disabled={ausfallSaving}>{ausfallSaving ? 'Speichern…' : 'Speichern'}</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<style>
	.top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 1.25rem; }
	.top .btn-primary { flex: none; padding: 0.45rem 0.9rem; font-size: 0.875rem; }
	.back { font-size: 0.85rem; color: #1e40af; text-decoration: none; display: block; margin-bottom: 0.25rem; }
	h1 { font-size: 1.4rem; font-weight: 700; color: #1e293b; }
	.hint { color: #94a3b8; font-size: 0.95rem; text-align: center; margin-top: 3rem; }
	.section-title { font-size: 0.72rem; font-weight: 700; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.06em; margin: 1.25rem 0 0.5rem; }

	.liste { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }

	.karte {
		display: flex; align-items: flex-start; gap: 0.75rem;
		padding: 0.85rem 1rem; background: #fff;
		border: 1px solid #e2e8f0; border-radius: 10px;
	}
	.karte.inaktiv { opacity: 0.55; }

	.ort-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.2rem; }
	.ort-name-zeile { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
	.ort-name { font-weight: 600; font-size: 0.95rem; color: #1e293b; }
	.ort-meta { font-size: 0.78rem; color: #64748b; }
	.gesperrt-hinweis { font-size: 0.75rem; color: #dc2626; font-weight: 500; }

	.badge { font-size: 0.7rem; font-weight: 700; padding: 0.1rem 0.45rem; border-radius: 20px; }
	.badge.gruen { background: #dcfce7; color: #16a34a; }
	.badge.rot   { background: #fee2e2; color: #dc2626; }
	.badge.grau  { background: #f1f5f9; color: #64748b; }

	.ort-aktionen { display: flex; gap: 0.35rem; flex-shrink: 0; align-items: flex-start; }

	.btn-ausfall {
		padding: 0.3rem 0.6rem; background: #fef9c3; border: 1px solid #fde047;
		border-radius: 6px; font-size: 0.75rem; font-weight: 600; color: #854d0e; cursor: pointer;
	}

	.ausfall-karte {
		display: flex; align-items: center; gap: 0.75rem;
		padding: 0.7rem 1rem; background: #fff;
		border: 1px solid #fca5a5; border-radius: 8px;
	}
	.ausfall-info { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; }
	.ausfall-ort { font-weight: 600; font-size: 0.88rem; color: #1e293b; }
	.ausfall-zeitraum { font-size: 0.78rem; color: #dc2626; }
	.ausfall-grund { font-size: 0.75rem; color: #94a3b8; }

	.btn-icon {
		width: 1.9rem; height: 1.9rem; display: flex; align-items: center;
		justify-content: center; background: none; border: 1px solid #e2e8f0;
		border-radius: 6px; color: #64748b; font-size: 0.85rem; cursor: pointer;
	}
	.btn-icon:hover { border-color: #94a3b8; color: #1e293b; }
	.btn-icon-red:hover { border-color: #fca5a5; color: #dc2626; }

	.overlay {
		position: fixed; inset: 0; background: rgba(0,0,0,0.4);
		display: flex; align-items: flex-end; justify-content: center;
		z-index: 100; padding: 1rem; padding-bottom: calc(1rem + env(safe-area-inset-bottom));
	}
	.sheet {
		background: #fff; border-radius: 16px; padding: 1.5rem;
		width: 100%; max-width: 480px; max-height: 90dvh; overflow-y: auto;
	}
	h2 { font-size: 1.1rem; font-weight: 700; color: #1e293b; margin-bottom: 0.25rem; }
	.sheet-sub { font-size: 0.85rem; color: #64748b; margin-bottom: 1rem; }
	.row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
	.field { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.85rem; }
	label { font-size: 0.875rem; font-weight: 500; color: #475569; }
	.toggle-label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.9rem; cursor: pointer; }
	input, select {
		padding: 0.65rem 0.85rem; border: 1.5px solid #e2e8f0; border-radius: 8px;
		font-size: 1rem; background: #fff; width: 100%; box-sizing: border-box;
		transition: border-color 0.15s;
	}
	input:focus, select:focus { outline: none; border-color: #1e40af; }
	.error { color: #dc2626; font-size: 0.875rem; margin-bottom: 0.75rem; }
	.actions { display: flex; gap: 0.75rem; margin-top: 0.5rem; }
	.btn-primary {
		flex: 1; padding: 0.75rem; background: #1e40af; color: #fff;
		border: none; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer;
	}
	.btn-primary:hover:not(:disabled) { background: #1d3a9e; }
	.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }
	.btn-ghost {
		padding: 0.75rem 1rem; background: none;
		border: 1.5px solid #e2e8f0; border-radius: 8px;
		font-size: 1rem; color: #64748b; cursor: pointer;
	}
</style>
