<script lang="ts">
	/**
	 * Admin — Jobbkø-oversikt (oppgave 15.3)
	 *
	 * Viser aktive, ventende og feilede jobber med filtrering
	 * på type, samling og status. Støtter manuell retry og avbryt.
	 */
	import { page } from '$app/stores';
	import {
		fetchJobs,
		retryJob,
		cancelJob,
		type ListJobsResponse,
		type JobDetail
	} from '$lib/api';

	const session = $derived($page.data.session as Record<string, unknown> | undefined);
	const accessToken = $derived(session?.accessToken as string | undefined);

	let data = $state<ListJobsResponse | null>(null);
	let loading = $state(false);
	let error = $state<string | null>(null);
	let actionLoading = $state<string | null>(null);

	// Filtre
	let statusFilter = $state('');
	let typeFilter = $state('');
	let currentOffset = $state(0);
	const PAGE_SIZE = 50;

	// Poll hvert 5. sekund
	$effect(() => {
		if (!accessToken) return;
		loadJobs();
		const interval = setInterval(loadJobs, 5000);
		return () => clearInterval(interval);
	});

	// Reset offset ved filterendring
	$effect(() => {
		// Avhenger av statusFilter og typeFilter
		void statusFilter;
		void typeFilter;
		currentOffset = 0;
	});

	async function loadJobs() {
		if (!accessToken) return;
		try {
			data = await fetchJobs(accessToken, {
				status: statusFilter || undefined,
				type: typeFilter || undefined,
				limit: PAGE_SIZE,
				offset: currentOffset
			});
			error = null;
		} catch (e) {
			error = String(e);
		}
	}

	async function handleRetry(jobId: string) {
		if (!accessToken || actionLoading) return;
		actionLoading = jobId;
		try {
			await retryJob(accessToken, jobId);
			await loadJobs();
		} catch (e) {
			error = String(e);
		} finally {
			actionLoading = null;
		}
	}

	async function handleCancel(jobId: string) {
		if (!accessToken || actionLoading) return;
		actionLoading = jobId;
		try {
			await cancelJob(accessToken, jobId);
			await loadJobs();
		} catch (e) {
			error = String(e);
		} finally {
			actionLoading = null;
		}
	}

	function statusColor(status: string): string {
		switch (status) {
			case 'running': return 'bg-blue-100 text-blue-700';
			case 'pending': return 'bg-yellow-100 text-yellow-700';
			case 'completed': return 'bg-green-100 text-green-700';
			case 'error': return 'bg-red-100 text-red-700';
			case 'retry': return 'bg-amber-100 text-amber-700';
			default: return 'bg-gray-100 text-gray-700';
		}
	}

	function statusDot(status: string): string {
		switch (status) {
			case 'running': return 'bg-blue-500';
			case 'pending': return 'bg-yellow-500';
			case 'completed': return 'bg-green-500';
			case 'error': return 'bg-red-500';
			case 'retry': return 'bg-amber-500';
			default: return 'bg-gray-500';
		}
	}

	function formatTime(iso: string | null): string {
		if (!iso) return '-';
		return new Date(iso).toLocaleString('nb-NO', {
			day: '2-digit', month: '2-digit',
			hour: '2-digit', minute: '2-digit', second: '2-digit'
		});
	}

	function getCount(status: string): number {
		if (!data) return 0;
		const entry = data.counts.find(c => c.status === status);
		return entry ? entry.count : 0;
	}

	function totalCount(): number {
		if (!data) return 0;
		return data.counts.reduce((sum, c) => sum + c.count, 0);
	}

	function canRetry(job: JobDetail): boolean {
		return job.status === 'error' || job.status === 'retry';
	}

	function canCancel(job: JobDetail): boolean {
		return job.status === 'pending' || job.status === 'retry';
	}
</script>

<div class="min-h-screen bg-gray-50">
	<header class="border-b border-gray-200 bg-white">
		<div class="mx-auto flex max-w-5xl items-center justify-between px-4 py-3">
			<div class="flex items-center gap-3">
				<a href="/admin" class="text-sm text-gray-500 hover:text-gray-700">Admin</a>
				<span class="text-gray-300">/</span>
				<h1 class="text-lg font-semibold text-gray-900">Jobbkø</h1>
			</div>
		</div>
	</header>

	<main class="mx-auto max-w-5xl px-4 py-6">
		{#if !accessToken}
			<p class="text-sm text-gray-400">Logg inn for tilgang.</p>
		{:else if !data}
			<p class="text-sm text-gray-400">Laster jobber...</p>
		{:else}
			<!-- Feilmelding -->
			{#if error}
				<div class="mb-4 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700">
					{error}
				</div>
			{/if}

			<!-- Statusoppsummering -->
			<section class="mb-6 grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-6">
				<button
					onclick={() => { statusFilter = ''; }}
					class="rounded-lg border border-gray-200 bg-white p-3 text-center shadow-sm hover:border-gray-300 transition-colors"
					class:ring-2={statusFilter === ''}
					class:ring-gray-400={statusFilter === ''}
				>
					<div class="text-2xl font-bold text-gray-900">{totalCount()}</div>
					<div class="text-xs text-gray-500">Totalt</div>
				</button>
				{#each ['running', 'pending', 'retry', 'error', 'completed'] as s}
					<button
						onclick={() => { statusFilter = statusFilter === s ? '' : s; }}
						class="rounded-lg border border-gray-200 bg-white p-3 text-center shadow-sm hover:border-gray-300 transition-colors"
						class:ring-2={statusFilter === s}
						class:ring-gray-400={statusFilter === s}
					>
						<div class="text-2xl font-bold text-gray-900">{getCount(s)}</div>
						<div class="flex items-center justify-center gap-1 text-xs text-gray-500">
							<span class="h-1.5 w-1.5 rounded-full {statusDot(s)}"></span>
							{s}
						</div>
					</button>
				{/each}
			</section>

			<!-- Filtre -->
			<section class="mb-4 flex flex-wrap items-center gap-3">
				<div>
					<label for="type-filter" class="mr-1 text-xs font-medium text-gray-600">Type:</label>
					<select
						id="type-filter"
						bind:value={typeFilter}
						class="rounded border border-gray-300 px-2 py-1 text-sm"
					>
						<option value="">Alle</option>
						{#each data.job_types as jt}
							<option value={jt}>{jt}</option>
						{/each}
					</select>
				</div>
				<button
					onclick={() => { statusFilter = ''; typeFilter = ''; currentOffset = 0; }}
					class="text-xs text-gray-500 hover:text-gray-700 underline"
				>
					Nullstill filtre
				</button>
			</section>

			<!-- Jobbtabell -->
			<section class="overflow-x-auto rounded-lg border border-gray-200 bg-white shadow-sm">
				<table class="w-full text-sm">
					<thead>
						<tr class="border-b border-gray-100 bg-gray-50 text-left text-xs font-medium text-gray-500">
							<th class="px-3 py-2">Status</th>
							<th class="px-3 py-2">ID</th>
							<th class="px-3 py-2">Type</th>
							<th class="px-3 py-2">Forsøk</th>
							<th class="px-3 py-2">Opprettet</th>
							<th class="px-3 py-2">Startet</th>
							<th class="px-3 py-2">Feil</th>
							<th class="px-3 py-2">Handlinger</th>
						</tr>
					</thead>
					<tbody>
						{#each data.jobs as job (job.id)}
							<tr class="border-b border-gray-50 hover:bg-gray-50">
								<td class="px-3 py-2">
									<span class="inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium {statusColor(job.status)}">
										<span class="h-1.5 w-1.5 rounded-full {statusDot(job.status)}"></span>
										{job.status}
									</span>
								</td>
								<td class="px-3 py-2 font-mono text-xs text-gray-500" title={job.id}>
									{job.id.slice(0, 8)}
								</td>
								<td class="px-3 py-2 font-medium text-gray-700">{job.job_type}</td>
								<td class="px-3 py-2 text-gray-500">
									{job.attempts}/{job.max_attempts}
								</td>
								<td class="px-3 py-2 text-xs text-gray-400">{formatTime(job.created_at)}</td>
								<td class="px-3 py-2 text-xs text-gray-400">{formatTime(job.started_at)}</td>
								<td class="max-w-[200px] truncate px-3 py-2 text-xs text-red-600" title={job.error_msg ?? ''}>
									{job.error_msg ?? ''}
								</td>
								<td class="px-3 py-2">
									<div class="flex gap-1">
										{#if canRetry(job)}
											<button
												onclick={() => handleRetry(job.id)}
												disabled={actionLoading === job.id}
												class="rounded bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 hover:bg-blue-100 disabled:opacity-50"
											>
												Retry
											</button>
										{/if}
										{#if canCancel(job)}
											<button
												onclick={() => handleCancel(job.id)}
												disabled={actionLoading === job.id}
												class="rounded bg-red-50 px-2 py-1 text-xs font-medium text-red-700 hover:bg-red-100 disabled:opacity-50"
											>
												Avbryt
											</button>
										{/if}
									</div>
								</td>
							</tr>
						{:else}
							<tr>
								<td colspan="8" class="px-3 py-8 text-center text-sm text-gray-400">
									Ingen jobber funnet.
								</td>
							</tr>
						{/each}
					</tbody>
				</table>
			</section>

			<!-- Paginering -->
			{#if data.jobs.length >= PAGE_SIZE || currentOffset > 0}
				<div class="mt-4 flex items-center justify-between">
					<button
						onclick={() => { currentOffset = Math.max(0, currentOffset - PAGE_SIZE); loadJobs(); }}
						disabled={currentOffset === 0}
						class="rounded border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-50 disabled:opacity-30"
					>
						Forrige
					</button>
					<span class="text-xs text-gray-400">
						Viser {currentOffset + 1}–{currentOffset + data.jobs.length}
					</span>
					<button
						onclick={() => { currentOffset += PAGE_SIZE; loadJobs(); }}
						disabled={data.jobs.length < PAGE_SIZE}
						class="rounded border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-50 disabled:opacity-30"
					>
						Neste
					</button>
				</div>
			{/if}
		{/if}
	</main>
</div>
