import { useId, useState, type FormEvent } from "react";
import { useQuery } from "@tanstack/react-query";
import * as stylex from "@stylexjs/stylex";
import {
	localRecordCreateMutation,
	localRecordDeleteMutation,
	localRecordUpdateMutation,
	localRecordsQuery,
} from "@/lib/queries";
import type { LocalRecord, LocalRecordInput, LocalRecordType } from "@/lib/types";
import InlineError from "@/lib/InlineError";
import ConfirmDialog from "@/ui/ConfirmDialog";
import Select from "@/ui/Select";
import { useCrudForm } from "@/ui/useCrudForm";
import QueryPanel from "./QueryPanel";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";

const RTYPES: readonly LocalRecordType[] = ["A", "AAAA", "CNAME"];
const RTYPE_OPTIONS = RTYPES.map((rtype) => ({ value: rtype, label: rtype }));

const styles = stylex.create({
	formHeading: {
		fontWeight: 500,
	},
	fieldLabel: {
		display: "block",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		fontWeight: 500,
	},
	buttonRow: {
		display: "flex",
		gap: "0.5rem",
	},
	toolbar: {
		display: "flex",
		alignItems: "center",
		justifyContent: "space-between",
		marginTop: "1rem",
	},
	intro: {
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.textMuted,
	},
	table: {
		width: "100%",
		textAlign: "left",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	headRow: {
		borderBottomWidth: 1,
		borderBottomStyle: "solid",
		borderBottomColor: colors.border,
		color: colors.textMuted,
	},
	headCell: {
		paddingBlock: "0.5rem",
		paddingRight: "1rem",
		fontWeight: 500,
	},
	headCellLast: {
		paddingBlock: "0.5rem",
	},
	bodyRow: {
		borderBottomWidth: 1,
		borderBottomStyle: "solid",
		borderBottomColor: colors.border,
	},
	cell: {
		paddingBlock: "0.5rem",
		paddingRight: "1rem",
	},
	emptyCell: {
		paddingBlock: "1rem",
		color: colors.textMuted,
	},
	actionCell: {
		paddingBlock: "0.5rem",
		textAlign: "right",
		whiteSpace: "nowrap",
	},
	dangerText: {
		color: colors.danger,
	},
	dimWhenDisabled: {
		opacity: { default: 1, ":disabled": 0.5 },
	},
});

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} {...stylex.props(shared.formCard)}>
			<h3 {...stylex.props(styles.formHeading)}>
				{initial === undefined ? "New record" : `Edit ${initial.name}`}
			</h3>
			<div>
				<label htmlFor={`${id}-name`} {...stylex.props(styles.fieldLabel)}>
					Name
				</label>
				<input
					id={`${id}-name`}
					required
					value={name}
					onChange={(event) => setName(event.target.value)}
					placeholder="nas.lan.home"
					{...stylex.props(shared.input, shared.focusRing)}
				/>
			</div>
			<div>
				<Select
					label="Type"
					value={rtype}
					onChange={(next) => setRtype(next as LocalRecordType)}
					options={RTYPE_OPTIONS}
				/>
			</div>
			<div>
				<label htmlFor={`${id}-value`} {...stylex.props(styles.fieldLabel)}>
					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"
					}
					{...stylex.props(shared.input, shared.focusRing)}
				/>
			</div>
			<div>
				<label htmlFor={`${id}-ttl`} {...stylex.props(styles.fieldLabel)}>
					TTL (seconds)
				</label>
				<input
					id={`${id}-ttl`}
					type="number"
					min={0}
					value={ttl}
					onChange={(event) => setTtl(event.target.value)}
					placeholder="300"
					{...stylex.props(shared.input, shared.focusRing)}
				/>
			</div>
			<div {...stylex.props(styles.buttonRow)}>
				<button type="submit" disabled={busy} {...stylex.props(shared.largePrimaryButton, shared.focusRing)}>
					{busy ? "Saving…" : "Save"}
				</button>
				<button type="button" onClick={onCancel} {...stylex.props(shared.largeButton, shared.focusRing)}>
					Cancel
				</button>
			</div>
			<InlineError error={error} />
		</form>
	);
}

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

	return (
		<div>
			<div {...stylex.props(styles.toolbar)}>
				<p {...stylex.props(styles.intro)}>Answers served directly for LAN names. Changes apply live.</p>
				<button
					type="button"
					onClick={() => openForm({ mode: "create" })}
					{...stylex.props(shared.largePrimaryButton, shared.focusRing)}
				>
					Add record
				</button>
			</div>
			<InlineError error={remove.error} />
			{form?.mode === "create" && (
				<RecordForm busy={create.isPending} error={create.error} onSubmit={onSubmit} onCancel={closeForm} />
			)}
			<QueryPanel query={query}>
				{(records) => (
					<div {...stylex.props(shared.tableWrap)}>
						<table {...stylex.props(styles.table)}>
							<thead>
								<tr {...stylex.props(styles.headRow)}>
									<th scope="col" {...stylex.props(styles.headCell)}>
										Name
									</th>
									<th scope="col" {...stylex.props(styles.headCell)}>
										Type
									</th>
									<th scope="col" {...stylex.props(styles.headCell)}>
										Value
									</th>
									<th scope="col" {...stylex.props(styles.headCell)}>
										TTL
									</th>
									<th scope="col" {...stylex.props(styles.headCellLast)}>
										<span {...stylex.props(shared.srOnly)}>Actions</span>
									</th>
								</tr>
							</thead>
							<tbody>
								{records.length === 0 && (
									<tr>
										<td colSpan={5} {...stylex.props(styles.emptyCell)}>
											No local records yet.
										</td>
									</tr>
								)}
								{records.map((record) => (
									<tr key={record.id} {...stylex.props(styles.bodyRow)}>
										{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 {...stylex.props(styles.cell, shared.mono)}>{record.name}</td>
												<td {...stylex.props(styles.cell)}>{record.rtype}</td>
												<td {...stylex.props(styles.cell, shared.mono)}>{record.value}</td>
												<td {...stylex.props(styles.cell)}>{record.ttl}</td>
												<td {...stylex.props(styles.actionCell)}>
													<button
														type="button"
														onClick={() => openForm({ mode: "edit", entity: record })}
														{...stylex.props(
															shared.rowButton,
															styles.dimWhenDisabled,
															shared.focusRing,
														)}
													>
														Edit
													</button>
													<button
														type="button"
														onClick={() => onDelete(record)}
														disabled={remove.isPending}
														{...stylex.props(
															shared.rowButton,
															styles.dangerText,
															styles.dimWhenDisabled,
															shared.focusRing,
														)}
													>
														Delete
													</button>
												</td>
											</>
										)}
									</tr>
								))}
							</tbody>
						</table>
					</div>
				)}
			</QueryPanel>
			<ConfirmDialog
				isOpen={pendingDelete !== null}
				title="Delete record"
				message={pendingDelete?.message ?? ""}
				confirmLabel="Delete"
				onConfirm={confirmPendingDelete}
				onCancel={cancelPendingDelete}
			/>
		</div>
	);
}
