<script lang="ts">
	import { Check, NoSymbol, PencilSquare, Plus, Trash } from 'svelte-heros-v2';
	import Input from '$lib/components/Input/Input.svelte';
	import Select from '$lib/components/Input/Select.svelte';
	import { env } from '$env/dynamic/public';
	import type { User } from '$lib/server/database';
	import { buttonTriggeredRequest } from '$lib/components/utils';
	import { browser } from '$app/environment';
	import HeaderBar from './HeaderBar.svelte';
	import SortableTr from '$lib/components/Table/SortableTr.svelte';
	import SortableTh from '$lib/components/Table/SortableTh.svelte';
	import NewUserModal from './NewUserModal.svelte';
	import PaginationTableBody from '$lib/components/PaginationTable/PaginationTableBody.svelte';
	import { getPopupModalShowFn } from '$lib/context';

	let showPopupModal = getPopupModalShowFn();

	let users: (typeof User.prototype.dataValues)[] = $state([]);
	let usersPerRequest = 25;
	let userFilter: { [k: string]: any } = $state({ name: null, playertype: null });

	let userTableContainerElement: HTMLDivElement;
	let newUserModal: HTMLDialogElement;

	async function fetchUsers(extendedFilter?: {
		limit?: number;
		from?: number;
	}): Promise<typeof users> {
		if (!browser) return [];

		if (userTableContainerElement) userTableContainerElement.scrollTop = 0;

		const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
			method: 'POST',
			body: JSON.stringify({
				...userFilter,
				limit: extendedFilter?.limit ?? usersPerRequest,
				from: extendedFilter?.from ?? users.length
			})
		});

		return await response.json();
	}

	async function updateUser(user: typeof User.prototype.dataValues) {
		await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
			method: 'PATCH',
			body: JSON.stringify(user)
		});
	}

	async function deleteUser(id: number) {
		const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
			method: 'DELETE',
			body: JSON.stringify({
				id: id
			})
		});
		if (response.ok) {
			users.splice(
				users.findIndex((v) => v.id == id),
				1
			);
			users = users;
		}
	}

	let userFilterEffectAlreadyRan = false;
	$effect(() => {
		// eslint-disable-next-line @typescript-eslint/no-unused-expressions
		userFilter;

		if (!userFilterEffectAlreadyRan) {
			userFilterEffectAlreadyRan = true;
			return;
		}
		fetchUsers({ from: 0 }).then((u) => (users = u));
	});
</script>

<div class="h-full flex flex-col overflow-hidden">
	<div class="grid grid-cols-[10fr_1fr_10fr_1fr_10fr]">
		<div></div>
		<div></div>
		<HeaderBar bind:userFilter onUpdate={() => (userFilter = $state.snapshot(userFilter))} />
		<div class="divider divider-horizontal my-auto h-3/4"></div>
		<div class="flex items-center">
			<button class="btn" onclick={() => newUserModal.show()}>
				<Plus />
				<span>Neuer Spieler</span>
			</button>
		</div>
	</div>
	<hr class="divider my-1 mx-8 border-none" />
	<div class="h-full overflow-scroll" bind:this={userTableContainerElement}>
		<table class="table table-auto">
			<thead>
				<!-- prettier-ignore -->
				<SortableTr class="[&>th]:bg-base-100 [&>th]:z-[1] [&>th]:sticky [&>th]:top-0">
					<th></th>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'firstname', asc: e.asc}}}>Vorname</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'lastname', asc: e.asc}}}>Nachname</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'birthday', asc: e.asc}}}>Geburtstag</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'telephone', asc: e.asc}}}>Telefon</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'username', asc: e.asc}}}>Username</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'playertype', asc: e.asc}}}>Minecraft Edition</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'password', asc: e.asc}}}>Passwort</SortableTh>
					<SortableTh onSort={(e) => userFilter = {...userFilter, sort: {key: 'uuid', asc: e.asc}}}>UUID</SortableTh>
					<th></th>
				</SortableTr>
			</thead>
			<PaginationTableBody
				onUpdate={async () => {
					await fetchUsers().then((u) => (users = [...users, ...u]));
				}}
			>
				{#each users as user, i}
					<tr>
						<td>{i + 1}</td>
						<td>
							<Input type="text" bind:value={user.firstname} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<Input type="text" bind:value={user.lastname} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<Input
								type="date"
								value={new Date(user.birthday).toISOString().split('T')[0]}
								oninput={(e) => (user.birthday = e.currentTarget.valueAsDate.toISOString())}
								disabled={!user.edit}
								size="sm"
							/>
						</td>
						<td>
							<Input type="tel" bind:value={user.telephone} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<Input type="text" bind:value={user.username} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<Select id="edition" bind:value={user.playertype} disabled={!user.edit} size="sm">
								<option value="java">Java Edition</option>
								<option value="bedrock">Bedrock Edition</option>
								<option value="noauth">Java noauth</option>
							</Select>
						</td>
						<td>
							<Input type="text" bind:value={user.password} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<Input id="uuid" type="text" bind:value={user.uuid} disabled={!user.edit} size="sm" />
						</td>
						<td>
							<div class="flex gap-1">
								{#if user.edit}
									<button
										class="btn btn-sm btn-square"
										onclick={async (e) => {
											showPopupModal({
												title: 'Speichern',
												text: `Sollen die Änderungen für den Nutzer '${user.username}' gespeichert werden?`,
												actions: [
													{
														text: 'Speichern',
														action: async () => {
															await buttonTriggeredRequest(e, updateUser(user));
															user.edit = false;
														}
													},
													{ text: 'Abbrechen' }
												]
											});
										}}
									>
										<Check size="18" />
									</button>
									<button
										class="btn btn-sm btn-square"
										onclick={() => {
											if (
												user.firstname === user.before.firstname &&
												user.lastname === user.before.lastname &&
												user.birthday === user.before.birthday &&
												user.telephone === user.before.telephone &&
												user.username === user.before.username &&
												user.playertype === user.before.playertype &&
												user.password === user.before.password &&
												user.uuid === user.before.uuid
											) {
												user.edit = false;
												return;
											}

											showPopupModal({
												title: 'Abbrechen',
												text: 'Soll die Nutzerbearbeitung abgebrochen werden?',
												actions: [
													{
														text: 'Abbrechen',
														action: () => {
															user.edit = false;
															users[i] = user.before;
														}
													},
													{ text: 'Schließen' }
												]
											});
										}}
									>
										<NoSymbol size="18" />
									</button>
								{:else}
									<button
										class="btn btn-sm btn-square"
										onclick={() => {
											user.before = $state.snapshot(user);
											user.edit = true;
										}}
									>
										<PencilSquare size="18" />
									</button>
									<button
										class="btn btn-sm btn-square"
										onclick={(e) => {
											showPopupModal({
												title: 'Nutzer löschen',
												text: `Soll der Nutzer '${user.username}' wirklich gelöscht werden?`,
												actions: [
													{
														text: 'Löschen',
														action: () => buttonTriggeredRequest(e, deleteUser(user.id))
													},
													{ text: 'Abbrechen' }
												]
											});
										}}
									>
										<Trash size="18" />
									</button>
								{/if}
							</div>
						</td>
					</tr>
				{/each}
			</PaginationTableBody>
		</table>
	</div>
</div>

<dialog class="modal" bind:this={newUserModal}>
	<NewUserModal
		onSubmit={(e) => {
			users = [...users, e];
			newUserModal.close();
		}}
	/>
</dialog>
