<script lang="ts">
	import { goto } from '$app/navigation';
	import { getToken, getRole } from '$lib/auth';
	import { api } from '$lib/api';
	import { onMount } from 'svelte';

	interface UserSummary {
		id: string;
		display_name: string;
		role: string;
		is_banned: boolean;
		uploads_hidden: boolean;
		upload_count: number;
		total_upload_bytes: number;
		created_at: string;
	}

	interface EventStatus {
		name: string;
		is_active: boolean;
		uploads_locked: boolean;
		export_released: boolean;
	}

	let event = $state<EventStatus | null>(null);
	let users = $state<UserSummary[]>([]);
	let loading = $state(true);
	let error = $state<string | null>(null);

	// Collapsible section state
	let statsOpen = $state(true);
	let settingsOpen = $state(true);
	let usersOpen = $state(true);

	// User search
	let userSearch = $state('');
	let filteredUsers = $derived(
		userSearch.trim()
			? users.filter((u) => u.display_name.toLowerCase().includes(userSearch.toLowerCase()))
			: users
	);

	// Ban modal state
	let banTarget = $state<UserSummary | null>(null);
	let banHideUploads = $state(false);
	let banSubmitting = $state(false);

	let toast = $state<string | null>(null);

	const myRole = getRole();

	onMount(async () => {
		const token = getToken();
		const role = getRole();
		if (!token || (role !== 'host' && role !== 'admin')) {
			goto('/join');
			return;
		}
		await reload();
	});

	async function reload() {
		loading = true;
		error = null;
		try {
			[event, users] = await Promise.all([
				api.get<EventStatus>('/host/event'),
				api.get<UserSummary[]>('/host/users')
			]);
		} catch (e: unknown) {
			error = e instanceof Error ? e.message : 'Fehler beim Laden.';
		} finally {
			loading = false;
		}
	}

	function showToast(msg: string) {
		toast = msg;
		setTimeout(() => (toast = null), 3000);
	}

	async function toggleEventLock() {
		if (!event) return;
		try {
			if (event.uploads_locked) {
				await api.post('/host/event/open');
				showToast('Uploads wurden wieder geöffnet.');
			} else {
				await api.post('/host/event/close');
				showToast('Uploads wurden gesperrt.');
			}
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		}
	}

	async function releaseGallery() {
		try {
			await api.post('/host/gallery/release');
			showToast('Galerie wurde freigegeben. Export wird vorbereitet…');
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		}
	}

	function openBanModal(user: UserSummary) {
		banTarget = user;
		banHideUploads = false;
	}

	async function confirmBan() {
		if (!banTarget) return;
		banSubmitting = true;
		try {
			await api.post(`/host/users/${banTarget.id}/ban`, { hide_uploads: banHideUploads });
			showToast(`${banTarget.display_name} wurde gesperrt.`);
			banTarget = null;
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		} finally {
			banSubmitting = false;
		}
	}

	async function unban(user: UserSummary) {
		try {
			await api.post(`/host/users/${user.id}/unban`);
			showToast(`Sperre für ${user.display_name} aufgehoben.`);
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		}
	}

	async function promoteToHost(user: UserSummary) {
		try {
			await api.patch(`/host/users/${user.id}/role`, { role: 'host' });
			showToast(`${user.display_name} ist jetzt Host.`);
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		}
	}

	async function demoteToGuest(user: UserSummary) {
		try {
			await api.patch(`/host/users/${user.id}/role`, { role: 'guest' });
			showToast(`${user.display_name} ist jetzt Gast.`);
			await reload();
		} catch (e: unknown) {
			showToast(e instanceof Error ? e.message : 'Fehler.');
		}
	}

	function formatBytes(bytes: number): string {
		if (bytes < 1024) return `${bytes} B`;
		if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
		return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
	}
</script>

<!-- Ban modal -->
{#if banTarget}
	<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
		<div class="w-full max-w-sm rounded-2xl bg-white p-6 shadow-xl">
			<h2 class="mb-1 text-lg font-bold text-gray-900">Benutzer sperren</h2>
			<p class="mb-4 text-sm text-gray-600">
				Was soll mit den Uploads von <strong>{banTarget.display_name}</strong> passieren?
			</p>
			<label class="mb-4 flex cursor-pointer items-center gap-3 rounded-lg border border-gray-200 p-3">
				<input
					type="checkbox"
					bind:checked={banHideUploads}
					class="h-4 w-4 rounded border-gray-300 text-red-600 focus:ring-red-500"
				/>
				<span class="text-sm text-gray-700">Uploads aus der Galerie ausblenden</span>
			</label>
			<div class="flex gap-2">
				<button
					onclick={() => (banTarget = null)}
					class="flex-1 rounded-lg border border-gray-300 py-2 text-sm text-gray-700 hover:bg-gray-50"
				>
					Abbrechen
				</button>
				<button
					onclick={confirmBan}
					disabled={banSubmitting}
					class="flex-1 rounded-lg bg-red-600 py-2 text-sm font-medium text-white hover:bg-red-700 disabled:opacity-50"
				>
					{banSubmitting ? 'Wird gesperrt…' : 'Sperren'}
				</button>
			</div>
		</div>
	</div>
{/if}

<!-- Toast -->
{#if toast}
	<div class="fixed bottom-24 left-1/2 z-50 -translate-x-1/2 rounded-full bg-gray-900 px-5 py-2.5 text-sm text-white shadow-lg">
		{toast}
	</div>
{/if}

<div class="min-h-screen bg-gray-50 pb-24">
	<!-- Header -->
	<div class="border-b border-gray-200 bg-white">
		<div class="mx-auto flex max-w-3xl items-center gap-3 px-4 py-4">
			<button
				onclick={() => goto('/account')}
				class="flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-gray-500 transition hover:bg-gray-100"
				aria-label="Zurück"
			>
				<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
					<path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
				</svg>
			</button>
			<div class="min-w-0">
				<h1 class="text-xl font-bold text-gray-900">Host-Dashboard</h1>
				{#if event}
					<p class="truncate text-sm text-gray-500">{event.name}</p>
				{/if}
			</div>
		</div>
	</div>

	<div class="mx-auto max-w-3xl space-y-3 p-4">
		{#if loading}
			<div class="py-16 text-center text-gray-400">Laden…</div>
		{:else if error}
			<div class="rounded-lg bg-red-50 p-4 text-sm text-red-700">{error}</div>
		{:else if event}

			<!-- ── Statistiken ─────────────────────────────────────────────── -->
			<div class="overflow-hidden rounded-xl border border-gray-200 bg-white">
				<button
					onclick={() => (statsOpen = !statsOpen)}
					class="flex w-full items-center justify-between px-5 py-4"
				>
					<h2 class="font-semibold text-gray-900">Statistiken</h2>
					<svg
						class="h-5 w-5 text-gray-400 transition-transform duration-200 {statsOpen ? 'rotate-180' : ''}"
						fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"
					>
						<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
					</svg>
				</button>
				<div class="overflow-hidden transition-[max-height] duration-200 {statsOpen ? 'max-h-[500px]' : 'max-h-0'}">
					<div class="grid grid-cols-2 gap-3 border-t border-gray-100 p-4 sm:grid-cols-4">
						<div class="rounded-xl bg-gray-50 p-4 text-center">
							<p class="text-2xl font-bold text-gray-900">{users.length}</p>
							<p class="mt-0.5 text-xs text-gray-500">Gäste</p>
						</div>
						<div class="rounded-xl bg-gray-50 p-4 text-center">
							<p class="text-2xl font-bold text-gray-900">{users.reduce((s, u) => s + u.upload_count, 0)}</p>
							<p class="mt-0.5 text-xs text-gray-500">Uploads</p>
						</div>
						<div class="rounded-xl bg-gray-50 p-4 text-center">
							<p class="text-2xl font-bold {event.uploads_locked ? 'text-red-600' : 'text-green-600'}">
								{event.uploads_locked ? 'Gesperrt' : 'Offen'}
							</p>
							<p class="mt-0.5 text-xs text-gray-500">Uploads</p>
						</div>
						<div class="rounded-xl bg-gray-50 p-4 text-center">
							<p class="text-2xl font-bold {event.export_released ? 'text-blue-600' : 'text-gray-400'}">
								{event.export_released ? 'Ja' : 'Nein'}
							</p>
							<p class="mt-0.5 text-xs text-gray-500">Freigegeben</p>
						</div>
					</div>
				</div>
			</div>

			<!-- ── Event-Einstellungen ─────────────────────────────────────── -->
			<div class="overflow-hidden rounded-xl border border-gray-200 bg-white">
				<button
					onclick={() => (settingsOpen = !settingsOpen)}
					class="flex w-full items-center justify-between px-5 py-4"
				>
					<h2 class="font-semibold text-gray-900">Event-Einstellungen</h2>
					<svg
						class="h-5 w-5 text-gray-400 transition-transform duration-200 {settingsOpen ? 'rotate-180' : ''}"
						fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"
					>
						<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
					</svg>
				</button>
				<div class="overflow-hidden transition-[max-height] duration-200 {settingsOpen ? 'max-h-[500px]' : 'max-h-0'}">
					<div class="flex flex-wrap gap-3 border-t border-gray-100 p-5">
						<button
							onclick={toggleEventLock}
							class="rounded-lg px-4 py-2 text-sm font-medium transition
								{event.uploads_locked ? 'bg-green-600 text-white hover:bg-green-700' : 'bg-amber-500 text-white hover:bg-amber-600'}"
						>
							{event.uploads_locked ? 'Uploads wieder öffnen' : 'Uploads sperren'}
						</button>
						<button
							onclick={releaseGallery}
							disabled={event.export_released}
							class="rounded-lg px-4 py-2 text-sm font-medium transition
								{event.export_released ? 'cursor-default bg-gray-100 text-gray-400' : 'bg-blue-600 text-white hover:bg-blue-700'}"
						>
							{event.export_released ? 'Galerie bereits freigegeben' : 'Galerie freigeben'}
						</button>
					</div>
				</div>
			</div>

			<!-- ── Nutzerverwaltung ───────────────────────────────────────── -->
			<div class="overflow-hidden rounded-xl border border-gray-200 bg-white">
				<button
					onclick={() => (usersOpen = !usersOpen)}
					class="flex w-full items-center justify-between px-5 py-4"
				>
					<h2 class="font-semibold text-gray-900">Nutzerverwaltung</h2>
					<svg
						class="h-5 w-5 text-gray-400 transition-transform duration-200 {usersOpen ? 'rotate-180' : ''}"
						fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"
					>
						<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
					</svg>
				</button>
				<div class="overflow-hidden transition-[max-height] duration-300 {usersOpen ? 'max-h-[9999px]' : 'max-h-0'}">
					<div class="border-t border-gray-100">
						<!-- Search -->
						<div class="px-4 py-3">
							<div class="flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2">
								<svg class="h-4 w-4 shrink-0 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
									<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
								</svg>
								<input
									type="search"
									placeholder="Nutzer suchen…"
									bind:value={userSearch}
									class="min-w-0 flex-1 bg-transparent text-sm text-gray-900 placeholder-gray-400 outline-none"
								/>
							</div>
						</div>
						{#if filteredUsers.length === 0}
							<p class="px-5 py-8 text-center text-sm text-gray-400">Keine Treffer.</p>
						{:else}
							<div class="divide-y divide-gray-100">
								{#each filteredUsers as user}
									<div class="flex items-center gap-3 px-5 py-3">
										<div class="min-w-0 flex-1">
											<div class="flex flex-wrap items-center gap-1.5">
												<span class="font-medium text-gray-900">{user.display_name}</span>
												{#if user.role === 'host'}
													<span class="rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700">Host</span>
												{:else if user.role === 'admin'}
													<span class="rounded-full bg-purple-100 px-2 py-0.5 text-xs font-medium text-purple-700">Admin</span>
												{/if}
												{#if user.is_banned}
													<span class="rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700">Gesperrt</span>
												{/if}
											</div>
											<p class="text-xs text-gray-400">
												{user.upload_count} Upload{user.upload_count !== 1 ? 's' : ''} · {formatBytes(user.total_upload_bytes)}
											</p>
										</div>
										<div class="flex shrink-0 gap-1.5">
											{#if user.role !== 'admin'}
												{#if user.is_banned}
													<button
														onclick={() => unban(user)}
														class="rounded-lg bg-gray-100 px-3 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-200"
													>
														Entsperren
													</button>
												{:else}
													{#if user.role === 'guest' && (myRole === 'host' || myRole === 'admin')}
														<button
															onclick={() => promoteToHost(user)}
															class="rounded-lg bg-blue-50 px-3 py-1.5 text-xs font-medium text-blue-700 hover:bg-blue-100"
														>
															Host
														</button>
													{/if}
													{#if user.role === 'host' && myRole === 'admin'}
														<button
															onclick={() => demoteToGuest(user)}
															class="rounded-lg bg-gray-100 px-3 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-200"
														>
															Degradieren
														</button>
													{/if}
													<button
														onclick={() => openBanModal(user)}
														class="rounded-lg bg-red-50 px-3 py-1.5 text-xs font-medium text-red-700 hover:bg-red-100"
													>
														Sperren
													</button>
												{/if}
											{/if}
										</div>
									</div>
								{/each}
							</div>
						{/if}
					</div>
				</div>
			</div>
		{/if}
	</div>
</div>
