import { Link } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { Badge } from "~/shared/components/ui/badge";
import { api } from "~/shared/lib/api";
import type { PipelineJobItem } from "~/shared/lib/types";
import { ColumnShell } from "./ColumnShell";

interface ProcessingColumnProps {
	items: PipelineJobItem[];
	progress?: { id: number; seconds: number; total: number } | null;
	queueStatus?: { status: string; until?: string; seconds?: number } | null;
	onMutate: () => void;
}

export function ProcessingColumn({ items, progress, queueStatus, onMutate }: ProcessingColumnProps) {
	const job = items[0]; // at most one running job

	// Wall-clock elapsed since the job started — re-renders every second.
	const [now, setNow] = useState(() => Date.now());
	useEffect(() => {
		if (!job) return;
		const t = setInterval(() => setNow(Date.now()), 1000);
		return () => clearInterval(t);
	}, [job]);

	// Only trust progress if it belongs to the current job — stale events from
	// a previous job would otherwise show wrong numbers until the new job emits.
	const liveProgress = job && progress && progress.id === job.id ? progress : null;
	const startedAt = job?.started_at ? new Date(`${job.started_at}Z`).getTime() : null;
	const elapsedMs = startedAt ? Math.max(0, now - startedAt) : 0;
	const percent = liveProgress && liveProgress.total > 0 ? (liveProgress.seconds / liveProgress.total) * 100 : null;
	// ETA = elapsed × (1 - p) / p — only meaningful once we have a few percent
	// of progress and the rate has stabilised.
	const etaMs = percent != null && percent >= 1 && elapsedMs > 0 ? (elapsedMs * (100 - percent)) / percent : null;

	const formatDuration = (ms: number) => {
		const total = Math.floor(ms / 1000);
		const h = Math.floor(total / 3600);
		const m = Math.floor((total % 3600) / 60);
		const s = total % 60;
		if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
		return `${m}:${String(s).padStart(2, "0")}`;
	};

	const stop = async () => {
		if (!confirm(`Stop the running job "${job?.name}"? It will be marked as error.`)) return;
		await api.post("/api/execute/stop");
		onMutate();
	};

	return (
		<ColumnShell
			title="Processing"
			count={job ? 1 : 0}
			actions={job ? [{ label: "Stop", onClick: stop, danger: true }] : undefined}
		>
			{queueStatus && queueStatus.status !== "running" && (
				<div className="mb-2 text-xs text-gray-500 bg-white rounded border p-2">
					{queueStatus.status === "paused" && <>Paused until {queueStatus.until}</>}
					{queueStatus.status === "sleeping" && <>Sleeping {queueStatus.seconds}s between jobs</>}
					{queueStatus.status === "idle" && <>Idle</>}
				</div>
			)}

			{job ? (
				<div className="rounded border bg-white p-3">
					<div className="flex items-start justify-between gap-2">
						<Link
							to="/review/audio/$id"
							params={{ id: String(job.item_id) }}
							className="text-sm font-medium truncate flex-1 hover:text-blue-600 hover:underline"
						>
							{job.name}
						</Link>
						<button
							type="button"
							onClick={stop}
							className="text-xs px-2 py-0.5 rounded border border-red-200 text-red-700 hover:bg-red-50 shrink-0"
						>
							Stop
						</button>
					</div>
					<div className="flex items-center gap-2 mt-1">
						<Badge variant="running">running</Badge>
						<Badge variant={job.job_type === "transcode" ? "manual" : "noop"}>{job.job_type}</Badge>
					</div>

					<div className="mt-3">
						<div className="flex justify-between text-xs text-gray-500 mb-1 tabular-nums">
							<span>elapsed {formatDuration(elapsedMs)}</span>
							<span>{percent != null ? `${Math.round(percent)}%` : "starting…"}</span>
							<span>{etaMs != null ? `~${formatDuration(etaMs)} left` : "—"}</span>
						</div>
						<div className="h-2 bg-gray-200 rounded-full overflow-hidden">
							<div
								className="h-full bg-blue-500 rounded-full transition-all"
								style={{ width: `${percent != null ? Math.min(100, percent) : 0}%` }}
							/>
						</div>
					</div>
				</div>
			) : (
				<p className="text-sm text-gray-400 text-center py-8">No active job</p>
			)}
		</ColumnShell>
	);
}
