import { useState } from "react";
import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import InlineError from "@/lib/InlineError";
import { upstreamCreateMutation, upstreamDeleteMutation, upstreamUpdateMutation, upstreamsQuery } from "@/lib/queries";
import type { Upstream, UpstreamInput } from "@/lib/types";
import { raiseRestartBanner } from "../settings/restartBanner";
import UpstreamForm from "./UpstreamForm";
import { dangerLinkButtonClass, focusRing, linkButtonClass, tableWrapClass, tdClass, thClass } from "@/ui/classes";

export default function UpstreamsPage() {
	const queryClient = useQueryClient();
	const { data: upstreams } = useSuspenseQuery(upstreamsQuery());
	const [editing, setEditing] = useState<Upstream | null>(null);

	const create = useMutation(upstreamCreateMutation(queryClient));
	const save = useMutation(upstreamUpdateMutation(queryClient));
	const toggle = useMutation(upstreamUpdateMutation(queryClient));
	const remove = useMutation(upstreamDeleteMutation(queryClient));

	async function submitForm(input: UpstreamInput) {
		if (editing === null) {
			await create.mutateAsync(input);
		} else {
			await save.mutateAsync({ id: editing.id, input });
			setEditing(null);
		}
		raiseRestartBanner();
	}

	function toggleEnabled(u: Upstream) {
		toggle.mutate(
			{
				id: u.id,
				input: { url: u.url, priority: u.priority, enabled: !u.enabled, tls_name: u.tls_name },
			},
			{ onSuccess: () => raiseRestartBanner() },
		);
	}

	function deleteUpstream(u: Upstream) {
		if (window.confirm(`Delete upstream "${u.url}"? Queries stop being forwarded to it.`)) {
			remove.mutate(u.id, { onSuccess: () => raiseRestartBanner() });
		}
	}

	const formError = editing === null ? create.error : save.error;
	const tableError = remove.error ?? toggle.error;

	return (
		<section>
			<h1 className="text-2xl font-semibold">Upstreams</h1>
			<p className="mt-2 max-w-2xl text-sm text-zinc-500">
				The pool builds its clients at startup, so an edit here takes effect at the next restart. The upstream
				health table on the Dashboard reflects the running pool, not this list.
			</p>

			{upstreams.length === 0 ? (
				<p className="mt-4 text-zinc-500">No upstreams yet. Add one below.</p>
			) : (
				<div className={tableWrapClass}>
					<table className="w-full min-w-max border-collapse text-sm">
						<thead>
							<tr>
								<th className={thClass}>URL</th>
								<th className={thClass}>Priority</th>
								<th className={thClass}>Enabled</th>
								<th className={thClass}>TLS name</th>
								<th className={thClass}>
									<span className="sr-only">Actions</span>
								</th>
							</tr>
						</thead>
						<tbody>
							{upstreams.map((u) => (
								<tr key={u.id}>
									<td className={tdClass}>
										<span className="block max-w-72 truncate font-medium" title={u.url}>
											{u.url}
										</span>
									</td>
									<td className={`${tdClass} tabular-nums`}>{u.priority}</td>
									<td className={tdClass}>
										<input
											type="checkbox"
											aria-label={`${u.url} enabled`}
											checked={u.enabled}
											disabled={toggle.isPending}
											onChange={() => toggleEnabled(u)}
											className={focusRing}
										/>
									</td>
									<td className={tdClass}>{u.tls_name === "" ? "—" : u.tls_name}</td>
									<td className={tdClass}>
										<div className="flex gap-3">
											<button
												type="button"
												onClick={() => setEditing(u)}
												className={linkButtonClass}
											>
												Edit
											</button>
											<button
												type="button"
												onClick={() => deleteUpstream(u)}
												disabled={remove.isPending}
												className={dangerLinkButtonClass}
											>
												Delete
											</button>
										</div>
									</td>
								</tr>
							))}
						</tbody>
					</table>
				</div>
			)}
			<InlineError error={tableError} />

			<UpstreamForm
				key={editing?.id ?? "add"}
				initial={editing ?? undefined}
				busy={editing === null ? create.isPending : save.isPending}
				error={formError}
				onSubmit={submitForm}
				onCancel={editing === null ? undefined : () => setEditing(null)}
			/>
		</section>
	);
}
