<script lang="ts">
	import { fly } from 'svelte/transition';
	import type { PageData } from './$types';
	import type { Report } from '$lib/server/database';
	import { browser } from '$app/environment';
	import { env } from '$env/dynamic/public';
	import Select from '$lib/components/Input/Select.svelte';
	import Input from '$lib/components/Input/Input.svelte';
	import Textarea from '$lib/components/Input/Textarea.svelte';
	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	import { reportCount } from '$lib/stores';
	import HeaderBar from './HeaderBar.svelte';
	import { MagnifyingGlass, Plus, Share } from 'svelte-heros-v2';
	import NewReportModal from './NewReportModal.svelte';
	import { onDestroy, onMount } from 'svelte';
	import { goto } from '$app/navigation';
	import Search from '$lib/components/Input/Search.svelte';
	import { usernameSuggestions } from '$lib/utils';

	export let data: PageData;

	let currentPageReports: (typeof Report.prototype.dataValues)[] = [];
	let currentPageTotal = 0;
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	let currentPageReportsRequest: Promise<any> = Promise.resolve();
	let reportsPerPage = 50;
	let reportPage = 0;
	let reportFilter = { draft: false, status: null, reporter: null, reported: null };
	let activeReport: typeof Report.prototype.dataValues | null = null;

	async function fetchPageReports(
		page: number,
		filter: typeof reportFilter | { hash: string }
	): Promise<{ reports: typeof currentPageReports; count: number }> {
		if (!browser) return { reports: [], count: 0 };

		const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/reports`, {
			method: 'POST',
			body: JSON.stringify({
				...filter,
				limit: reportsPerPage,
				from: reportsPerPage * page
			})
		});

		if (activeReport) {
			activeReport = null;
			await goto(window.location.href.split('#')[0], { replaceState: true });
		}

		return await response.json();
	}

	$: currentPageReportsRequest = fetchPageReports(reportPage, reportFilter).then((r) => {
		currentPageReports = r.reports;
		currentPageTotal = r.count;
	});

	async function openHashReport() {
		if (!window.location.hash) return;

		const requestedHash = window.location.hash.substring(1);
		let report = currentPageReports.find((r) => r.url_hash === requestedHash);
		if (!report) {
			const hashReport = (await fetchPageReports(0, { hash: requestedHash })).reports[0];
			if (hashReport) {
				currentPageReports = [hashReport, ...currentPageReports];
				report = hashReport;
			} else {
				await goto(window.location.href.split('#')[0], { replaceState: true });
				return;
			}
		}

		activeReport = report;
		activeReport.originalStatus = report;
	}
	onMount(async () => {
		await currentPageReportsRequest;
		await openHashReport();

		if (browser) window.addEventListener('hashchange', openHashReport);
	});
	onDestroy(() => {
		if (browser) window.removeEventListener('hashchange', openHashReport);
	});

	async function updateActiveReport() {
		await fetch(`${env.PUBLIC_BASE_PATH}/admin/reports`, {
			method: 'PATCH',
			body: JSON.stringify({
				id: activeReport.id,
				auditor: data.self?.id ?? -1,
				notice: activeReport.notice ?? '',
				statement: activeReport.statement ?? '',
				status: activeReport.status,
				reported: activeReport.reported?.uuid ?? null,
				strike_reason: activeReport.strike_reason_id ?? null
			})
		});
	}

	let saveActiveReportChangesModal: HTMLDialogElement;
	let newReportModal: HTMLDialogElement;
</script>

<div class="h-full flex flex-row">
	<div class="w-full flex flex-col overflow-scroll">
		<HeaderBar bind:reportFilter />
		<hr class="divider my-1 mx-8 border-none" />
		<table class="table table-fixed h-fit">
			<colgroup>
				<col style="width: 20%" />
				<col style="width: 15%" />
				<col style="width: 15%" />
				<col style="width: 20%" />
				<col style="width: 15%" />
				<col style="width: 15%" />
			</colgroup>
			<thead>
				<tr>
					<th>Grund</th>
					<th>Ersteller</th>
					<th>Reporteter User</th>
					<th>Datum</th>
					<th>Bearbeitungsstatus</th>
					<th>Reportstatus</th>
				</tr>
			</thead>
			<tbody>
				{#each currentPageReports as report}
					<tr
						class="hover [&>*]:text-sm cursor-pointer"
						class:bg-base-200={activeReport?.url_hash === report.url_hash}
						on:click={() => {
							goto(`${window.location.href.split('#')[0]}#${report.url_hash}`, {
								replaceState: true
							});
							activeReport = report;
							activeReport.originalStatus = report.status;
						}}
					>
						<td title={report.subject}><div class="overflow-scroll">{report.subject}</div></td>
						<td class="flex">
							{report.reporter.username}
							<button
								class="pl-1"
								title="Nach Ersteller filtern"
								on:click|stopPropagation={() => (reportFilter.reporter = report.reporter.username)}
							>
								<MagnifyingGlass size="14" />
							</button>
						</td>
						<td>
							{report.reported?.username || ''}
							{#if report.reported?.id}
								<button
									class="pl-1"
									title="Nach Reportetem Spieler filtern"
									on:click|stopPropagation={() =>
										(reportFilter.reported = report.reported.username)}
								>
									<MagnifyingGlass size="14" />
								</button>
							{/if}
						</td>
						<td
							>{new Intl.DateTimeFormat('de-DE', {
								year: 'numeric',
								month: '2-digit',
								day: '2-digit',
								hour: '2-digit',
								minute: '2-digit'
							}).format(new Date(report.createdAt))} Uhr</td
						>
						<td>
							{report.status === 'none'
								? 'Unbearbeitet'
								: report.status === 'review'
								  ? 'In Bearbeitung'
								  : report.status === 'reviewed'
								    ? 'Bearbeitet'
								    : ''}
						</td>
						<td>{report.draft ? 'Entwurf' : 'Erstellt'}</td>
					</tr>
				{/each}
				<tr>
					<td colspan="100">
						<div class="flex justify-center items-center">
							<button class="btn btn-sm" on:click={() => newReportModal.show()}>
								<Plus />
								<span>Neuer Report</span>
							</button>
						</div>
					</td>
				</tr>
			</tbody>
		</table>
		<div class="flex justify-center items-center mb-2 mt-4 w-full">
			<div class="join">
				<!-- eslint-disable-next-line @typescript-eslint/no-unused-vars -->
				{#each Array(currentPageReports.length === reportsPerPage || reportPage > 0 ? Math.ceil(currentPageTotal / reportsPerPage) || 1 : 1) as _, i}
					<button
						class="join-item btn"
						class:btn-active={i === reportPage}
						on:click={() => {
							reportPage = i;
						}}>{i + 1}</button
					>
				{/each}
			</div>
		</div>
	</div>
	{#if activeReport}
		<div
			class="relative flex flex-col w-2/5 h-[calc(100vh-3rem)] bg-base-200/50 px-4 py-6 overflow-scroll"
			transition:fly={{ x: 200, duration: 200 }}
		>
			<div class="absolute right-2 top-2 flex justify-center">
				<form class="dropdown dropdown-end">
					<!-- svelte-ignore a11y-no-noninteractive-tabindex a11y-label-has-associated-control -->
					<label tabindex="0" class="btn btn-sm btn-circle btn-ghost text-center">
						<Share size="1rem" />
					</label>
					<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
					<ul
						tabindex="0"
						class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-max"
					>
						<li>
							<button
								on:click={() => {
									navigator.clipboard.writeText(
										`${window.location.protocol}//${window.location.host}${env.PUBLIC_BASE_PATH}/admin/reports#${activeReport.url_hash}`
									);
								}}
							>
								Internen Link kopieren
							</button>
							<button
								on:click={() =>
									navigator.clipboard.writeText(
										`${window.location.protocol}//${window.location.host}${env.PUBLIC_BASE_PATH}/report/${activeReport.url_hash}`
									)}>Öffentlichen Link kopieren</button
							>
						</li>
					</ul>
				</form>
				<button
					class="btn btn-sm btn-circle btn-ghost"
					on:click={() => {
						activeReport = null;
						goto(window.location.href.split('#')[0], { replaceState: true });
					}}>✕</button
				>
			</div>
			<h3 class="font-roboto font-semibold text-2xl mb-2">Report</h3>
			<div class="w-full">
				<Input readonly={true} size="sm" value={activeReport.reporter.username} pickyWidth={false}>
					<span slot="label">Reporter</span>
				</Input>
				<Search
					size="sm"
					suggestionRequired={true}
					emptyAllowed={true}
					searchSuggestionFunc={usernameSuggestions}
					invalidMessage="Es können nur registrierte Spieler reportet werden"
					label="Reporteter User"
					inputValue={activeReport.reported?.username || ''}
					on:submit={(e) =>
						(activeReport.reported = {
							...activeReport.reported,
							username: e.detail.input,
							uuid: e.detail.value
						})}
				/>
				<Textarea readonly={true} rows={1} label="Report Grund" value={activeReport.subject} />
				<Textarea readonly={true} rows={4} label="Report Details" value={activeReport.body} />
			</div>
			<div class="divider mx-4" />
			<div>
				<div
					class="w-full"
					title={activeReport.status === 'none'
						? 'Zum Bearbeiten den Bearbeitungsstatus ändern'
						: ''}
				>
					<Textarea
						label="Interne Notizen"
						readonly={activeReport.status === 'none'}
						rows={1}
						bind:value={activeReport.notice}
					/>
				</div>
				<div
					class="w-full"
					title={activeReport.status === 'none'
						? 'Zum Bearbeiten den Bearbeitungsstatus ändern'
						: ''}
				>
					<Textarea
						label="(Öffentliche) Report Antwort"
						readonly={activeReport.status === 'none'}
						rows={3}
						bind:value={activeReport.statement}
					/>
				</div>
				<Select label="Bearbeitungsstatus" size="sm" bind:value={activeReport.status}>
					<option
						value="none"
						disabled={activeReport.auditor != null || activeReport.notice || activeReport.statement}
						>Unbearbeitet</option
					>
					<option value="review">In Bearbeitung</option>
					<option value="reviewed">Bearbeitet</option>
				</Select>
				<div>
					<Select
						label="Vergehen"
						size="sm"
						disabled={activeReport.status === 'none' || !activeReport.reported}
						bind:value={activeReport.strike_reason_id}
					>
						<option value={-1}>Keins</option>
						{#each data.strike_reasons as strike_reason}
							<option value={strike_reason.id}>{strike_reason.name} ({strike_reason.weight})</option
							>
						{/each}
					</Select>
				</div>
			</div>
			<div class="self-end mt-auto pt-6 w-full flex justify-center">
				<Input
					type="submit"
					value="Speichern"
					on:click={() => saveActiveReportChangesModal.show()}
				/>
			</div>
		</div>
	{/if}
</div>

<dialog class="modal" bind:this={saveActiveReportChangesModal}>
	<form method="dialog" class="modal-box">
		<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
		<h3 class="font-roboto text-xl">Änderungen Speichern?</h3>
		<div class="flex flex-row space-x-2 mt-6">
			<Input
				type="submit"
				value="Speichern"
				on:click={async () => {
					await updateActiveReport();
					if (activeReport.reported?.username) {
						if (activeReport.reported?.id === undefined) {
							activeReport.reported.id = -1;
						}
					} else {
						activeReport.reported = undefined;
					}
					currentPageReports = [...currentPageReports];
					if (activeReport.originalStatus !== 'reviewed' && activeReport.status === 'reviewed') {
						$reportCount -= 1;
					} else if (
						activeReport.originalStatus === 'reviewed' &&
						activeReport.status !== 'reviewed'
					) {
						$reportCount += 1;
					}
				}}
			/>
			<Input type="submit" value="Abbrechen" />
		</div>
	</form>
	<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
		<button>close</button>
	</form>
</dialog>

<dialog class="modal" bind:this={newReportModal}>
	<NewReportModal
		on:submit={(e) => {
			if (!e.detail.draft) $reportCount += 1;
			currentPageReports = [e.detail, ...currentPageReports];
			activeReport = currentPageReports[0];
			newReportModal.close();
		}}
	/>
</dialog>
