<script lang="ts">
	import { pb } from '$lib/pb';
	import { goto } from '$app/navigation';
	import { onMount } from 'svelte';
	import { generatePain008, downloadXml, minEinzugsdatum, type SepaPosition } from '$lib/sepa';
	import type { Beitrag, Mitglied, Verein } from '$lib/types';

	// --- Daten ---
	let beitraege  = $state<Beitrag[]>([]);
	let verein     = $state<Verein | null>(null);
	let loading    = $state(true);

	// --- Beitragsart-Formular ---
	let showForm   = $state(false);
	let editId     = $state<string | null>(null);
	let fName      = $state('');
	let fBetrag    = $state('');
	let fRhythmus  = $state<Beitrag['rhythmus']>('jaehrlich');
	let fBeschr    = $state('');
	let saving     = $state(false);
	let formError  = $state('');

	// --- SEPA-Export ---
	let sepaFor    = $state<Beitrag | null>(null);
	let einzugsdatum = $state(minEinzugsdatum());
	let sepaLoading  = $state(false);
	let sepaError    = $state('');
	let sepaPreview  = $state<{ mitglieder: Mitglied[]; ohne: number } | null>(null);

	const rhythmusLabel: Record<Beitrag['rhythmus'], string> = {
		monatlich:     'monatlich',
		quartalsweise: 'quartalsweise',
		halbjaehrlich: 'halbjährlich',
		jaehrlich:     'jährlich',
		einmalig:      'einmalig',
	};

	onMount(async () => {
		if (pb.authStore.record?.rolle === 'trainer') { goto('/'); return; }
		const vid = pb.authStore.record?.verein_id as string;
		[beitraege, verein] = await Promise.all([
			pb.collection('beitraege').getFullList<Beitrag>({ sort: 'name' }),
			pb.collection('vereine').getOne<Verein>(vid).catch(() => null),
		]);
		loading = false;
	});

	// --- Beitragsart speichern ---
	function neuerBeitrag() {
		editId = null; fName = ''; fBetrag = ''; fRhythmus = 'jaehrlich'; fBeschr = '';
		formError = ''; showForm = true;
	}

	function bearbeiten(b: Beitrag) {
		editId = b.id; fName = b.name; fBetrag = String(b.betrag);
		fRhythmus = b.rhythmus; fBeschr = b.beschreibung ?? '';
		formError = ''; showForm = true;
	}

	async function speichern() {
		formError = '';
		const betrag = parseFloat(fBetrag.replace(',', '.'));
		if (!fName.trim() || isNaN(betrag) || betrag <= 0) {
			formError = 'Name und gültiger Betrag sind Pflichtfelder.';
			return;
		}
		saving = true;
		try {
			const vid = pb.authStore.record?.verein_id as string;
			const data = { verein_id: vid, name: fName.trim(), betrag, rhythmus: fRhythmus, beschreibung: fBeschr.trim() };
			if (editId) {
				await pb.collection('beitraege').update(editId, data);
				beitraege = beitraege.map(b => b.id === editId ? { ...b, ...data } as Beitrag : b);
			} else {
				const neu = await pb.collection('beitraege').create<Beitrag>(data);
				beitraege = [...beitraege, neu].sort((a, b) => a.name.localeCompare(b.name));
			}
			showForm = false;
		} catch (e: unknown) {
			formError = e instanceof Error ? e.message : 'Fehler beim Speichern.';
		} finally {
			saving = false;
		}
	}

	async function loeschen(b: Beitrag) {
		if (!confirm(`"${b.name}" wirklich löschen?`)) return;
		await pb.collection('beitraege').delete(b.id);
		beitraege = beitraege.filter(x => x.id !== b.id);
	}

	// --- SEPA-Export ---
	async function sepaOeffnen(b: Beitrag) {
		sepaFor = b;
		sepaError = '';
		sepaPreview = null;
		einzugsdatum = minEinzugsdatum();
		sepaLoading = true;
		try {
			const alle = await pb.collection('mitglieder').getFullList<Mitglied>({
				filter: 'status = "aktiv"', sort: 'nachname,vorname',
			});
			const mit  = alle.filter(m => m.iban?.trim());
			const ohne = alle.length - mit.length;
			sepaPreview = { mitglieder: mit, ohne };
		} catch (e: unknown) {
			sepaError = e instanceof Error ? e.message : 'Fehler beim Laden der Mitglieder.';
		} finally {
			sepaLoading = false;
		}
	}

	function sepaSchliessen() {
		sepaFor = null; sepaPreview = null; sepaError = '';
	}

	async function sepaExportieren() {
		if (!sepaFor || !sepaPreview || !verein) return;

		if (!verein.glaeubigerid || !verein.iban || !verein.bic) {
			sepaError = 'Bitte zuerst Gläubiger-ID, IBAN und BIC des Vereins in den Einstellungen hinterlegen.';
			return;
		}

		sepaError = '';
		sepaLoading = true;

		try {
			const today = new Date().toISOString().slice(0, 10);
			const positionen: SepaPosition[] = sepaPreview.mitglieder.map((m, i) => ({
				endToEndId: `VH-${sepaFor!.id.slice(0, 6)}-${String(i + 1).padStart(4, '0')}`,
				betrag: sepaFor!.betrag,
				mandatsreferenz: m.mandatsreferenz || `MANDAT-${m.id.slice(0, 8).toUpperCase()}`,
				mandatsdatum:    m.mandatsdatum   || today,
				debitorName:     `${m.vorname} ${m.nachname}`,
				debitorIban:     m.iban!,
				debitorBic:      m.bic ?? '',
				verwendungszweck: `${sepaFor!.name} (${rhythmusLabel[sepaFor!.rhythmus]})`,
			}));

			const xml = generatePain008(
				{
					glaeubigerid: verein.glaeubigerid,
					vereinIban:   verein.iban,
					vereinBic:    verein.bic,
					vereinName:   verein.name,
					einzugsdatum,
				},
				positionen,
			);

			downloadXml(xml, `sepa-einzug-${einzugsdatum}.xml`);

			// Einzüge als "ausstehend" anlegen
			const vid = pb.authStore.record?.verein_id as string;
			await Promise.all(
				sepaPreview.mitglieder.map((m) =>
					pb.collection('einzuege').create({
						mitglied_id: m.id,
						beitrag_id:  sepaFor!.id,
						betrag:      sepaFor!.betrag,
						faellig_am:  einzugsdatum,
						status:      'ausstehend',
					}),
				),
			);

			sepaSchliessen();
		} catch (e: unknown) {
			sepaError = e instanceof Error ? e.message : 'Fehler beim Export.';
		} finally {
			sepaLoading = false;
		}
	}

	const gesamtbetrag = $derived(
		sepaPreview ? sepaPreview.mitglieder.length * (sepaFor?.betrag ?? 0) : 0,
	);

	const sepaFehlt = $derived(
		verein ? !verein.glaeubigerid || !verein.iban || !verein.bic : true,
	);
</script>

<svelte:head><title>Beiträge — vereins.haus</title></svelte:head>

<div class="top">
	<h1>Beiträge</h1>
	<button class="btn-primary" onclick={neuerBeitrag}>+ Beitragsart</button>
</div>

{#if sepaFehlt && !loading}
	<div class="hinweis">
		SEPA-Einzug nicht möglich: Gläubiger-ID, IBAN und BIC des Vereins fehlen noch in den Einstellungen.
	</div>
{/if}

{#if loading}
	<p class="hint">Laden…</p>
{:else if beitraege.length === 0}
	<p class="hint">Noch keine Beitragsarten — lege die erste an!</p>
{:else}
	<ul class="liste">
		{#each beitraege as b (b.id)}
			<li class="karte">
				<div class="karte-info">
					<span class="karte-name">{b.name}</span>
					{#if b.beschreibung}
						<span class="karte-beschr">{b.beschreibung}</span>
					{/if}
					<span class="karte-meta">
						{b.betrag.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })}
						· {rhythmusLabel[b.rhythmus]}
					</span>
				</div>
				<div class="karte-aktionen">
					<button class="btn-sepa" onclick={() => sepaOeffnen(b)} disabled={sepaFehlt}>
						SEPA
					</button>
					<button class="btn-icon" onclick={() => bearbeiten(b)} title="Bearbeiten">✎</button>
					<button class="btn-icon btn-icon-red" onclick={() => loeschen(b)} title="Löschen">✕</button>
				</div>
			</li>
		{/each}
	</ul>
{/if}

<!-- Beitragsart-Formular -->
{#if showForm}
	<div class="overlay" role="dialog" aria-modal="true">
		<div class="sheet">
			<h2>{editId ? 'Beitragsart bearbeiten' : 'Neue Beitragsart'}</h2>

			<form onsubmit={(e) => { e.preventDefault(); speichern(); }}>
				<div class="field">
					<label for="fname">Name *</label>
					<input id="fname" type="text" bind:value={fName} placeholder="z. B. Jahresbeitrag" required />
				</div>

				<div class="row">
					<div class="field">
						<label for="fbetrag">Betrag (€) *</label>
						<input id="fbetrag" type="text" inputmode="decimal" bind:value={fBetrag} placeholder="48,00" required />
					</div>
					<div class="field">
						<label for="frhythmus">Rhythmus</label>
						<select id="frhythmus" bind:value={fRhythmus}>
							<option value="monatlich">Monatlich</option>
							<option value="quartalsweise">Quartalsweise</option>
							<option value="halbjaehrlich">Halbjährlich</option>
							<option value="jaehrlich">Jährlich</option>
							<option value="einmalig">Einmalig</option>
						</select>
					</div>
				</div>

				<div class="field">
					<label for="fbeschr">Beschreibung</label>
					<input id="fbeschr" type="text" bind:value={fBeschr} placeholder="Optional" />
				</div>

				{#if formError}
					<p class="error">{formError}</p>
				{/if}

				<div class="actions">
					<button type="button" class="btn-ghost" onclick={() => showForm = false}>Abbrechen</button>
					<button type="submit" class="btn-primary" disabled={saving}>
						{saving ? 'Speichern…' : 'Speichern'}
					</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- SEPA-Export -->
{#if sepaFor}
	<div class="overlay" role="dialog" aria-modal="true">
		<div class="sheet">
			<h2>SEPA-Einzug</h2>
			<p class="sepa-sub">{sepaFor.name} · {sepaFor.betrag.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })} · {rhythmusLabel[sepaFor.rhythmus]}</p>

			<div class="field">
				<label for="einzugsdatum">Einzugsdatum *</label>
				<input
					id="einzugsdatum"
					type="date"
					bind:value={einzugsdatum}
					min={minEinzugsdatum()}
				/>
				<span class="field-hint">SEPA CORE: mind. 2 Bankarbeitstage Vorlauf</span>
			</div>

			{#if sepaLoading}
				<p class="hint">Laden…</p>
			{:else if sepaPreview}
				<div class="sepa-summary">
					<div class="sepa-row">
						<span>Mitglieder mit IBAN</span>
						<strong>{sepaPreview.mitglieder.length}</strong>
					</div>
					{#if sepaPreview.ohne > 0}
						<div class="sepa-row sepa-warn">
							<span>Ohne IBAN (übersprungen)</span>
							<strong>{sepaPreview.ohne}</strong>
						</div>
					{/if}
					<div class="sepa-row sepa-total">
						<span>Gesamtsumme</span>
						<strong>{gesamtbetrag.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })}</strong>
					</div>
				</div>

				{#if sepaPreview.mitglieder.length === 0}
					<p class="error">Keine aktiven Mitglieder mit IBAN vorhanden.</p>
				{/if}
			{/if}

			{#if sepaError}
				<p class="error">{sepaError}</p>
			{/if}

			<div class="actions">
				<button type="button" class="btn-ghost" onclick={sepaSchliessen}>Abbrechen</button>
				<button
					class="btn-primary"
					disabled={sepaLoading || !sepaPreview || sepaPreview.mitglieder.length === 0}
					onclick={sepaExportieren}
				>
					XML herunterladen
				</button>
			</div>
		</div>
	</div>
{/if}

<style>
	.top {
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-bottom: 1.25rem;
	}
	h1 { font-size: 1.4rem; font-weight: 700; color: #1e293b; }

	.hinweis {
		background: #fef9c3;
		border: 1px solid #fde047;
		border-radius: 8px;
		padding: 0.75rem 1rem;
		font-size: 0.875rem;
		color: #713f12;
		margin-bottom: 1rem;
	}

	.hint { color: #94a3b8; font-size: 0.95rem; text-align: center; margin-top: 3rem; }

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

	.karte {
		display: flex;
		align-items: center;
		gap: 0.75rem;
		padding: 0.9rem 1rem;
		background: #fff;
		border: 1px solid #e2e8f0;
		border-radius: 10px;
	}

	.karte-info {
		flex: 1;
		min-width: 0;
		display: flex;
		flex-direction: column;
		gap: 0.1rem;
	}
	.karte-name { font-weight: 600; font-size: 0.95rem; color: #1e293b; }
	.karte-beschr { font-size: 0.78rem; color: #94a3b8; }
	.karte-meta { font-size: 0.82rem; color: #475569; }

	.karte-aktionen {
		display: flex;
		align-items: center;
		gap: 0.4rem;
		flex-shrink: 0;
	}

	.btn-sepa {
		padding: 0.35rem 0.7rem;
		background: #e0e7ff;
		color: #1e40af;
		border: none;
		border-radius: 6px;
		font-size: 0.78rem;
		font-weight: 700;
		cursor: pointer;
		transition: background 0.15s;
	}
	.btn-sepa:hover:not(:disabled) { background: #c7d2fe; }
	.btn-sepa:disabled { opacity: 0.4; cursor: not-allowed; }

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

	/* Overlay & Sheet */
	.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; }
	.sepa-sub { font-size: 0.85rem; color: #64748b; margin-bottom: 1.25rem; }

	.row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
	.field { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.9rem; }
	label { font-size: 0.875rem; font-weight: 500; color: #475569; }
	.field-hint { font-size: 0.75rem; color: #94a3b8; }

	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; }

	.sepa-summary {
		background: #f8fafc;
		border: 1px solid #e2e8f0;
		border-radius: 8px;
		margin-bottom: 1rem;
		overflow: hidden;
	}
	.sepa-row {
		display: flex;
		justify-content: space-between;
		padding: 0.65rem 1rem;
		font-size: 0.9rem;
		color: #1e293b;
		border-bottom: 1px solid #e2e8f0;
	}
	.sepa-row:last-child { border-bottom: none; }
	.sepa-warn { color: #92400e; background: #fffbeb; }
	.sepa-total { font-weight: 700; background: #f0f9ff; }

	.error { color: #dc2626; font-size: 0.875rem; margin-bottom: 0.75rem; }

	.actions { display: flex; gap: 0.75rem; margin-top: 1.25rem; }

	.btn-primary {
		flex: 1;
		padding: 0.75rem;
		background: #1e40af;
		color: #fff;
		border: none;
		border-radius: 8px;
		font-size: 1rem;
		font-weight: 600;
		cursor: pointer;
		transition: background 0.15s;
	}
	.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>
