import { useId, useState, type FormEvent } from "react";
import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import {
	forwardZoneCreateMutation,
	forwardZoneDeleteMutation,
	forwardZoneUpdateMutation,
	forwardZonesQuery,
} from "@/lib/queries";
import type { ForwardZone, ForwardZoneInput } from "@/lib/types";
import InlineError from "@/lib/InlineError";

const inputClass =
	"mt-1 w-full rounded border border-zinc-300 bg-white px-3 py-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 dark:border-zinc-700 dark:bg-zinc-900";
const primaryButtonClass =
	"rounded bg-blue-600 px-3 py-2 font-medium text-white disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600";
const secondaryButtonClass =
	"rounded border border-zinc-300 px-3 py-2 font-medium focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 dark:border-zinc-700";
const rowButtonClass =
	"rounded px-2 py-1 text-sm text-blue-600 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 dark:text-blue-400";

type FormState = { mode: "create" } | { mode: "edit"; zone: ForwardZone };

function ZoneForm({
	initial,
	busy,
	error,
	onSubmit,
	onCancel,
}: {
	initial?: ForwardZone;
	busy: boolean;
	error: unknown;
	onSubmit: (input: ForwardZoneInput) => void;
	onCancel: () => void;
}) {
	const id = useId();
	const [zone, setZone] = useState(initial?.zone ?? "");
	const [resolver, setResolver] = useState(initial?.resolver ?? "");

	function submit(event: FormEvent<HTMLFormElement>) {
		event.preventDefault();
		onSubmit({ zone: zone.trim(), resolver: resolver.trim() });
	}

	return (
		<form
			onSubmit={submit}
			className="mt-4 max-w-lg space-y-3 rounded border border-zinc-200 p-4 dark:border-zinc-800"
		>
			<h3 className="font-medium">{initial === undefined ? "New forward zone" : `Edit ${initial.zone}`}</h3>
			<div>
				<label htmlFor={`${id}-zone`} className="block text-sm font-medium">
					Zone
				</label>
				<input
					id={`${id}-zone`}
					required
					value={zone}
					onChange={(event) => setZone(event.target.value)}
					placeholder="lan.home"
					className={inputClass}
				/>
			</div>
			<div>
				<label htmlFor={`${id}-resolver`} className="block text-sm font-medium">
					Resolver
				</label>
				<input
					id={`${id}-resolver`}
					required
					value={resolver}
					onChange={(event) => setResolver(event.target.value)}
					placeholder="udp://192.168.1.1:53"
					className={inputClass}
				/>
			</div>
			<div className="flex gap-2">
				<button type="submit" disabled={busy} className={primaryButtonClass}>
					{busy ? "Saving…" : "Save"}
				</button>
				<button type="button" onClick={onCancel} className={secondaryButtonClass}>
					Cancel
				</button>
			</div>
			<InlineError error={error} />
		</form>
	);
}

export default function ZonesTab() {
	const zones = useSuspenseQuery(forwardZonesQuery()).data;
	const queryClient = useQueryClient();
	const create = useMutation(forwardZoneCreateMutation(queryClient));
	const update = useMutation(forwardZoneUpdateMutation(queryClient));
	const remove = useMutation(forwardZoneDeleteMutation(queryClient));
	const [form, setForm] = useState<FormState | null>(null);

	function openForm(next: FormState) {
		create.reset();
		update.reset();
		setForm(next);
	}

	function onSubmit(input: ForwardZoneInput) {
		if (form === null) return;
		if (form.mode === "create") {
			create.mutate(input, { onSuccess: () => setForm(null) });
		} else {
			update.mutate({ id: form.zone.id, input }, { onSuccess: () => setForm(null) });
		}
	}

	function onDelete(zone: ForwardZone) {
		if (!window.confirm(`Delete forward zone "${zone.zone}"?`)) return;
		remove.mutate(zone.id);
	}

	return (
		<div>
			<div className="mt-4 flex items-center justify-between">
				<p className="text-sm text-zinc-500">
					Names under these zones go to their own resolver. Changes apply live.
				</p>
				<button type="button" onClick={() => openForm({ mode: "create" })} className={primaryButtonClass}>
					Add zone
				</button>
			</div>
			<InlineError error={remove.error} />
			{form?.mode === "create" && (
				<ZoneForm
					busy={create.isPending}
					error={create.error}
					onSubmit={onSubmit}
					onCancel={() => setForm(null)}
				/>
			)}
			<div className="mt-4 overflow-x-auto">
				<table className="w-full text-left text-sm">
					<thead>
						<tr className="border-b border-zinc-200 text-zinc-500 dark:border-zinc-800">
							<th scope="col" className="py-2 pr-4 font-medium">
								Zone
							</th>
							<th scope="col" className="py-2 pr-4 font-medium">
								Resolver
							</th>
							<th scope="col" className="py-2">
								<span className="sr-only">Actions</span>
							</th>
						</tr>
					</thead>
					<tbody>
						{zones.length === 0 && (
							<tr>
								<td colSpan={3} className="py-4 text-zinc-500">
									No forward zones yet.
								</td>
							</tr>
						)}
						{zones.map((zone) => (
							<tr key={zone.id} className="border-b border-zinc-100 dark:border-zinc-900">
								{form?.mode === "edit" && form.zone.id === zone.id ? (
									<td colSpan={3}>
										<ZoneForm
											initial={zone}
											busy={update.isPending}
											error={update.error}
											onSubmit={onSubmit}
											onCancel={() => setForm(null)}
										/>
									</td>
								) : (
									<>
										<td className="py-2 pr-4 font-mono">{zone.zone}</td>
										<td className="py-2 pr-4 font-mono">{zone.resolver}</td>
										<td className="py-2 text-right whitespace-nowrap">
											<button
												type="button"
												onClick={() => openForm({ mode: "edit", zone })}
												className={rowButtonClass}
											>
												Edit
											</button>
											<button
												type="button"
												onClick={() => onDelete(zone)}
												disabled={remove.isPending}
												className={`${rowButtonClass} text-red-600 dark:text-red-400`}
											>
												Delete
											</button>
										</td>
									</>
								)}
							</tr>
						))}
					</tbody>
				</table>
			</div>
		</div>
	);
}
