<script lang="ts">
	import { untrack } from 'svelte';
	import { invalidateAll } from '$app/navigation';
	import { enhance } from '$app/forms';
	import type { PageData, ActionData } from './$types';
	import type { TranslationJob } from '$lib/server/pocketbase';

	let { data, form }: { data: PageData; form: ActionData } = $props();

	let jobs = $state<TranslationJob[]>(untrack(() => data.jobs));

	// Keep in sync on server reloads
	$effect(() => {
		jobs = data.jobs;
	});

	// ── Live-poll while any job is in-flight ─────────────────────────────────────
	let hasInFlight = $derived(jobs.some((j) => j.status === 'pending' || j.status === 'running'));

	$effect(() => {
		if (!hasInFlight) return;
		const id = setInterval(() => {
			invalidateAll();
		}, 3000);
		return () => clearInterval(id);
	});

	// ── Tabs ─────────────────────────────────────────────────────────────────────
	type Tab = 'enqueue' | 'jobs';
	let activeTab = $state<Tab>('enqueue');

	// ── Bulk enqueue form ─────────────────────────────────────────────────────────
	let slugInput = $state('');
	let langInput = $state('ru');
	let fromInput = $state(1);
	let toInput = $state(1);
	let submitting = $state(false);

	const langs = [
		{ value: 'ru', label: 'Russian (ru)' },
		{ value: 'id', label: 'Indonesian (id)' },
		{ value: 'pt', label: 'Portuguese (pt)' },
		{ value: 'fr', label: 'French (fr)' }
	];

	// ── Jobs helpers ──────────────────────────────────────────────────────────────
	function jobStatusColor(status: string) {
		if (status === 'done') return 'text-green-400';
		if (status === 'running') return 'text-(--color-brand) animate-pulse';
		if (status === 'pending') return 'text-sky-400 animate-pulse';
		if (status === 'failed') return 'text-(--color-danger)';
		return 'text-(--color-text)';
	}

	function fmtDate(s: string) {
		if (!s || s.startsWith('0001')) return '—';
		return new Date(s).toLocaleString(undefined, {
			month: 'short',
			day: 'numeric',
			hour: '2-digit',
			minute: '2-digit'
		});
	}

	function duration(started: string, finished: string) {
		if (!started || !finished || started.startsWith('0001') || finished.startsWith('0001'))
			return '—';
		const ms = new Date(finished).getTime() - new Date(started).getTime();
		if (ms < 0) return '—';
		const s = Math.floor(ms / 1000);
		if (s < 60) return `${s}s`;
		const m = Math.floor(s / 60);
		return `${m}m ${s % 60}s`;
	}

	let jobsQ = $state('');
	let filteredJobs = $derived(
		jobsQ.trim()
			? jobs.filter(
					(j) =>
						j.slug.toLowerCase().includes(jobsQ.toLowerCase().trim()) ||
						j.lang.toLowerCase().includes(jobsQ.toLowerCase().trim()) ||
						j.status.toLowerCase().includes(jobsQ.toLowerCase().trim())
				)
			: jobs
	);

	let stats = $derived({
		total: jobs.length,
		done: jobs.filter((j) => j.status === 'done').length,
		failed: jobs.filter((j) => j.status === 'failed').length,
		inFlight: jobs.filter((j) => j.status === 'pending' || j.status === 'running').length
	});
</script>

<svelte:head>
	<title>Translation — Admin</title>
</svelte:head>

<div class="space-y-6">
	<!-- Header -->
	<div>
		<h1 class="text-2xl font-bold text-(--color-text)">Machine Translation</h1>
		<p class="text-(--color-muted) text-sm mt-1">
			{stats.total} job{stats.total !== 1 ? 's' : ''} &middot;
			<span class="text-green-400">{stats.done} done</span>
			{#if stats.failed > 0}
				&middot; <span class="text-(--color-danger)">{stats.failed} failed</span>
			{/if}
			{#if stats.inFlight > 0}
				&middot; <span class="text-(--color-brand) animate-pulse">{stats.inFlight} in-flight</span>
			{/if}
		</p>
	</div>

	<!-- Tabs -->
	<div class="flex gap-1 bg-(--color-surface-2) rounded-lg p-1 w-fit border border-(--color-border)">
		<button
			onclick={() => (activeTab = 'enqueue')}
			class="px-4 py-1.5 rounded-md text-sm font-medium transition-colors
				{activeTab === 'enqueue' ? 'bg-(--color-surface-3) text-(--color-text)' : 'text-(--color-muted) hover:text-(--color-text)'}"
		>
			Enqueue
		</button>
		<button
			onclick={() => (activeTab = 'jobs')}
			class="px-4 py-1.5 rounded-md text-sm font-medium transition-colors
				{activeTab === 'jobs' ? 'bg-(--color-surface-3) text-(--color-text)' : 'text-(--color-muted) hover:text-(--color-text)'}"
		>
			Jobs
			{#if stats.inFlight > 0}
				<span
					class="ml-1.5 inline-flex items-center justify-center w-4 h-4 rounded-full bg-(--color-brand) text-(--color-surface) text-[10px] font-bold"
				>
					{stats.inFlight}
				</span>
			{/if}
		</button>
	</div>

	<!-- ── Enqueue tab ─────────────────────────────────────────────────────────── -->
	{#if activeTab === 'enqueue'}
		<div class="max-w-lg space-y-5">
			<!-- Result banner -->
			{#if form?.success}
				<div class="rounded-lg border border-green-500/40 bg-green-500/10 px-4 py-3 text-sm text-green-400">
					Enqueued {form.enqueued} translation job{form.enqueued !== 1 ? 's' : ''} successfully.
				</div>
			{:else if form?.error}
				<div class="rounded-lg border border-(--color-danger)/40 bg-(--color-danger)/10 px-4 py-3 text-sm text-(--color-danger)">
					{form.error}
				</div>
			{/if}

			<form
				method="POST"
				action="?/bulk"
				use:enhance={() => {
					submitting = true;
					return async ({ update }) => {
						await update();
						submitting = false;
						activeTab = 'jobs';
					};
				}}
				class="space-y-4"
			>
				<!-- Book slug -->
				<div class="space-y-1">
					<label for="slug" class="block text-sm font-medium text-(--color-text)">Book slug</label>
					<input
						id="slug"
						name="slug"
						type="text"
						required
						list="book-slugs"
						bind:value={slugInput}
						placeholder="e.g. the-beginning-after-the-end"
						class="w-full bg-(--color-surface-2) border border-(--color-border) rounded-lg px-3 py-2 text-(--color-text) text-sm placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-(--color-brand)"
					/>
					<datalist id="book-slugs">
						{#each data.books as book}
							<option value={book.slug}>{book.title}</option>
						{/each}
					</datalist>
				</div>

				<!-- Language -->
				<div class="space-y-1">
					<label for="lang" class="block text-sm font-medium text-(--color-text)">Target language</label>
					<select
						id="lang"
						name="lang"
						bind:value={langInput}
						class="w-full bg-(--color-surface-2) border border-(--color-border) rounded-lg px-3 py-2 text-(--color-text) text-sm focus:outline-none focus:ring-2 focus:ring-(--color-brand)"
					>
						{#each langs as l}
							<option value={l.value}>{l.label}</option>
						{/each}
					</select>
				</div>

				<!-- Chapter range -->
				<div class="grid grid-cols-2 gap-3">
					<div class="space-y-1">
						<label for="from" class="block text-sm font-medium text-(--color-text)">From chapter</label>
						<input
							id="from"
							name="from"
							type="number"
							min="1"
							required
							bind:value={fromInput}
							class="w-full bg-(--color-surface-2) border border-(--color-border) rounded-lg px-3 py-2 text-(--color-text) text-sm focus:outline-none focus:ring-2 focus:ring-(--color-brand)"
						/>
					</div>
					<div class="space-y-1">
						<label for="to" class="block text-sm font-medium text-(--color-text)">To chapter</label>
						<input
							id="to"
							name="to"
							type="number"
							min="1"
							required
							bind:value={toInput}
							class="w-full bg-(--color-surface-2) border border-(--color-border) rounded-lg px-3 py-2 text-(--color-text) text-sm focus:outline-none focus:ring-2 focus:ring-(--color-brand)"
						/>
					</div>
				</div>

				<p class="text-xs text-(--color-muted)">
					Enqueues {Math.max(0, toInput - fromInput + 1)} task{toInput - fromInput + 1 !== 1 ? 's' : ''} — one per chapter. Max 1000 at a time.
				</p>

				<button
					type="submit"
					disabled={submitting}
					class="w-full sm:w-auto px-6 py-2 rounded-lg bg-(--color-brand) text-(--color-surface) text-sm font-semibold hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed"
				>
					{submitting ? 'Enqueueing…' : 'Enqueue translations'}
				</button>
			</form>
		</div>
	{/if}

	<!-- ── Jobs tab ───────────────────────────────────────────────────────────── -->
	{#if activeTab === 'jobs'}
		<input
			type="search"
			bind:value={jobsQ}
			placeholder="Filter by slug, lang, or status…"
			class="w-full max-w-sm bg-(--color-surface-2) border border-(--color-border) rounded-lg px-3 py-2 text-(--color-text) text-sm placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-(--color-brand)"
		/>

		{#if filteredJobs.length === 0}
			<p class="text-(--color-muted) text-sm py-8 text-center">
				{jobsQ.trim() ? 'No matching jobs.' : 'No translation jobs yet.'}
			</p>
		{:else}
			<!-- Desktop table -->
			<div class="hidden sm:block overflow-x-auto rounded-xl border border-(--color-border)">
				<table class="w-full text-sm">
					<thead class="bg-(--color-surface-2) text-(--color-muted) text-xs uppercase tracking-wide">
						<tr>
							<th class="px-4 py-3 text-left">Book</th>
							<th class="px-4 py-3 text-right">Ch.</th>
							<th class="px-4 py-3 text-left">Lang</th>
							<th class="px-4 py-3 text-left">Status</th>
							<th class="px-4 py-3 text-left">Started</th>
							<th class="px-4 py-3 text-left">Duration</th>
						</tr>
					</thead>
					<tbody class="divide-y divide-(--color-border)/50">
						{#each filteredJobs as job}
							<tr class="bg-(--color-surface) hover:bg-(--color-surface-2)/50 transition-colors">
								<td class="px-4 py-3 text-(--color-text) font-medium">
									<a href="/books/{job.slug}" class="hover:text-(--color-brand) transition-colors"
										>{job.slug}</a
									>
								</td>
								<td class="px-4 py-3 text-right text-(--color-muted)">{job.chapter}</td>
								<td class="px-4 py-3 text-(--color-muted) font-mono text-xs uppercase">{job.lang}</td>
								<td class="px-4 py-3">
									<span class="font-medium {jobStatusColor(job.status)}">{job.status}</span>
								</td>
								<td class="px-4 py-3 text-(--color-muted) whitespace-nowrap">{fmtDate(job.started)}</td>
								<td class="px-4 py-3 text-(--color-muted) whitespace-nowrap"
									>{duration(job.started, job.finished)}</td
								>
							</tr>
							{#if job.error_message}
								<tr class="bg-(--color-danger)/10">
									<td colspan="6" class="px-4 py-2 text-xs text-(--color-danger) font-mono"
										>{job.error_message}</td
									>
								</tr>
							{/if}
						{/each}
					</tbody>
				</table>
			</div>

			<!-- Mobile cards -->
			<div class="sm:hidden space-y-3">
				{#each filteredJobs as job}
					<div class="bg-(--color-surface) rounded-xl border border-(--color-border) p-4 space-y-2">
						<div class="flex items-start justify-between gap-2">
							<a
								href="/books/{job.slug}"
								class="text-(--color-text) font-medium hover:text-(--color-brand) transition-colors truncate"
							>
								{job.slug}
							</a>
							<span class="shrink-0 text-xs font-semibold {jobStatusColor(job.status)}"
								>{job.status}</span
							>
						</div>
						<div class="grid grid-cols-2 gap-1 text-xs">
							<span class="text-(--color-muted)">Chapter</span><span
								class="text-(--color-muted) text-right">{job.chapter}</span
							>
							<span class="text-(--color-muted)">Lang</span><span
								class="text-(--color-muted) font-mono text-right uppercase">{job.lang}</span
							>
							<span class="text-(--color-muted)">Started</span><span
								class="text-(--color-muted) text-right">{fmtDate(job.started)}</span
							>
							<span class="text-(--color-muted)">Duration</span><span
								class="text-(--color-muted) text-right">{duration(job.started, job.finished)}</span
							>
						</div>
						{#if job.error_message}
							<p class="text-xs text-(--color-danger) font-mono break-all">{job.error_message}</p>
						{/if}
					</div>
				{/each}
			</div>
		{/if}
	{/if}
</div>
