import { useId, useState, type FormEvent } from "react";
import { useSuspenseQuery } from "@tanstack/react-query";
import {
	localRecordCreateMutation,
	localRecordDeleteMutation,
	localRecordUpdateMutation,
	localRecordsQuery,
} from "@/lib/queries";
import type { LocalRecord, LocalRecordInput, LocalRecordType } from "@/lib/types";
import InlineError from "@/lib/InlineError";
import { useCrudForm } from "@/ui/useCrudForm";
import {
	formCardClass,
	inputClass,
	largeButtonClass,
	largePrimaryButtonClass,
	rowButtonClass,
	tableWrapClass,
} from "@/ui/classes";

const RTYPES: readonly LocalRecordType[] = ["A", "AAAA", "CNAME"];

function RecordForm({
	initial,
	busy,
	error,
	onSubmit,
	onCancel,
}: {
	initial?: LocalRecord;
	busy: boolean;
	error: unknown;
	onSubmit: (input: LocalRecordInput) => void;
	onCancel: () => void;
}) {
	const id = useId();
	const [name, setName] = useState(initial?.name ?? "");
	const [rtype, setRtype] = useState<LocalRecordType>(initial?.rtype ?? "A");
	const [value, setValue] = useState(initial?.value ?? "");
	const [ttl, setTtl] = useState(initial === undefined ? "" : String(initial.ttl));

	function submit(event: FormEvent<HTMLFormElement>) {
		event.preventDefault();
		const input: LocalRecordInput = { name: name.trim(), rtype, value: value.trim() };
		if (ttl.trim() !== "") input.ttl = Number(ttl);
		onSubmit(input);
	}

	return (
		<form onSubmit={submit} className={formCardClass}>
			<h3 className="font-medium">{initial === undefined ? "New record" : `Edit ${initial.name}`}</h3>
			<div>
				<label htmlFor={`${id}-name`} className="block text-sm font-medium">
					Name
				</label>
				<input
					id={`${id}-name`}
					required
					value={name}
					onChange={(event) => setName(event.target.value)}
					placeholder="nas.lan.home"
					className={inputClass}
				/>
			</div>
			<div>
				<label htmlFor={`${id}-rtype`} className="block text-sm font-medium">
					Type
				</label>
				<select
					id={`${id}-rtype`}
					value={rtype}
					onChange={(event) => setRtype(event.target.value as LocalRecordType)}
					className={inputClass}
				>
					{RTYPES.map((option) => (
						<option key={option} value={option}>
							{option}
						</option>
					))}
				</select>
			</div>
			<div>
				<label htmlFor={`${id}-value`} className="block text-sm font-medium">
					Value
				</label>
				<input
					id={`${id}-value`}
					required
					value={value}
					onChange={(event) => setValue(event.target.value)}
					placeholder={
						rtype === "CNAME" ? "target.example.com" : rtype === "AAAA" ? "fd00::10" : "192.168.1.10"
					}
					className={inputClass}
				/>
			</div>
			<div>
				<label htmlFor={`${id}-ttl`} className="block text-sm font-medium">
					TTL (seconds)
				</label>
				<input
					id={`${id}-ttl`}
					type="number"
					min={0}
					value={ttl}
					onChange={(event) => setTtl(event.target.value)}
					placeholder="300"
					className={inputClass}
				/>
			</div>
			<div className="flex gap-2">
				<button type="submit" disabled={busy} className={largePrimaryButtonClass}>
					{busy ? "Saving…" : "Save"}
				</button>
				<button type="button" onClick={onCancel} className={largeButtonClass}>
					Cancel
				</button>
			</div>
			<InlineError error={error} />
		</form>
	);
}

export default function RecordsTab() {
	const records = useSuspenseQuery(localRecordsQuery()).data;
	const { create, update, remove, form, openForm, closeForm, onSubmit, onDelete } = useCrudForm<
		LocalRecord,
		LocalRecordInput
	>({
		create: localRecordCreateMutation,
		update: localRecordUpdateMutation,
		remove: localRecordDeleteMutation,
		confirmDelete: (record) => `Delete record "${record.name}"?`,
	});

	return (
		<div>
			<div className="mt-4 flex items-center justify-between">
				<p className="text-sm text-zinc-500">Answers served directly for LAN names. Changes apply live.</p>
				<button type="button" onClick={() => openForm({ mode: "create" })} className={largePrimaryButtonClass}>
					Add record
				</button>
			</div>
			<InlineError error={remove.error} />
			{form?.mode === "create" && (
				<RecordForm busy={create.isPending} error={create.error} onSubmit={onSubmit} onCancel={closeForm} />
			)}
			<div className={tableWrapClass}>
				<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">
								Name
							</th>
							<th scope="col" className="py-2 pr-4 font-medium">
								Type
							</th>
							<th scope="col" className="py-2 pr-4 font-medium">
								Value
							</th>
							<th scope="col" className="py-2 pr-4 font-medium">
								TTL
							</th>
							<th scope="col" className="py-2">
								<span className="sr-only">Actions</span>
							</th>
						</tr>
					</thead>
					<tbody>
						{records.length === 0 && (
							<tr>
								<td colSpan={5} className="py-4 text-zinc-500">
									No local records yet.
								</td>
							</tr>
						)}
						{records.map((record) => (
							<tr key={record.id} className="border-b border-zinc-100 dark:border-zinc-900">
								{form?.mode === "edit" && form.entity.id === record.id ? (
									<td colSpan={5}>
										<RecordForm
											initial={record}
											busy={update.isPending}
											error={update.error}
											onSubmit={onSubmit}
											onCancel={closeForm}
										/>
									</td>
								) : (
									<>
										<td className="py-2 pr-4 font-mono">{record.name}</td>
										<td className="py-2 pr-4">{record.rtype}</td>
										<td className="py-2 pr-4 font-mono">{record.value}</td>
										<td className="py-2 pr-4">{record.ttl}</td>
										<td className="py-2 text-right whitespace-nowrap">
											<button
												type="button"
												onClick={() => openForm({ mode: "edit", entity: record })}
												className={rowButtonClass}
											>
												Edit
											</button>
											<button
												type="button"
												onClick={() => onDelete(record)}
												disabled={remove.isPending}
												className={`${rowButtonClass} text-red-600 dark:text-red-400`}
											>
												Delete
											</button>
										</td>
									</>
								)}
							</tr>
						))}
					</tbody>
				</table>
			</div>
		</div>
	);
}
