import { useState } from "react";
import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
import * as stylex from "@stylexjs/stylex";
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 ConfirmDialog from "@/ui/ConfirmDialog";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
import { READ_ONLY_HINT, useReadOnlyConfig } from "@/features/settings/authority";

const styles = stylex.create({
	heading: {
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	intro: {
		marginTop: "0.5rem",
		maxWidth: "42rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.textMuted,
	},
	empty: {
		marginTop: "1rem",
		color: colors.textMuted,
	},
	table: {
		width: "100%",
		minWidth: "max-content",
		borderCollapse: "collapse",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	url: {
		display: "block",
		maxWidth: "18rem",
		overflow: "hidden",
		textOverflow: "ellipsis",
		whiteSpace: "nowrap",
		fontWeight: 500,
	},
	actions: {
		display: "flex",
		gap: "0.75rem",
	},
	dimWhenDisabled: {
		opacity: { default: 1, ":disabled": 0.5 },
	},
});

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

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

	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 confirmDelete() {
		if (pendingDelete === null) return;
		remove.mutate(pendingDelete.id, { onSuccess: () => raiseRestartBanner() });
		setPendingDelete(null);
	}

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

	return (
		<section>
			<h1 {...stylex.props(styles.heading)}>Upstreams</h1>
			<p {...stylex.props(styles.intro)}>
				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 {...stylex.props(styles.empty)}>No upstreams yet. Add one below.</p>
			) : (
				<div {...stylex.props(shared.tableWrap)}>
					<table {...stylex.props(styles.table)}>
						<thead>
							<tr>
								<th {...stylex.props(shared.th)}>URL</th>
								<th {...stylex.props(shared.th)}>Priority</th>
								<th {...stylex.props(shared.th)}>Enabled</th>
								<th {...stylex.props(shared.th)}>TLS name</th>
								<th {...stylex.props(shared.th)}>
									<span {...stylex.props(shared.srOnly)}>Actions</span>
								</th>
							</tr>
						</thead>
						<tbody>
							{upstreams.map((u) => (
								<tr key={u.id}>
									<td {...stylex.props(shared.td)}>
										<span {...stylex.props(styles.url)} title={u.url}>
											{u.url}
										</span>
									</td>
									<td {...stylex.props(shared.td, shared.tabularNums)}>{u.priority}</td>
									<td {...stylex.props(shared.td)}>
										<input
											type="checkbox"
											aria-label={`${u.url} enabled`}
											checked={u.enabled}
											disabled={toggle.isPending || readOnly}
											title={readOnly ? READ_ONLY_HINT : undefined}
											onChange={() => toggleEnabled(u)}
											{...stylex.props(shared.focusRing)}
										/>
									</td>
									<td {...stylex.props(shared.td)}>{u.tls_name === "" ? "—" : u.tls_name}</td>
									<td {...stylex.props(shared.td)}>
										<div {...stylex.props(styles.actions)}>
											<button
												type="button"
												onClick={() => setEditing(u)}
												disabled={readOnly}
												title={readOnly ? READ_ONLY_HINT : undefined}
												{...stylex.props(
													shared.linkButton,
													styles.dimWhenDisabled,
													shared.focusRing,
												)}
											>
												Edit
											</button>
											<button
												type="button"
												onClick={() => setPendingDelete(u)}
												disabled={remove.isPending || readOnly}
												title={readOnly ? READ_ONLY_HINT : undefined}
												{...stylex.props(shared.dangerLinkButton, shared.focusRing)}
											>
												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}
				readOnly={readOnly}
				error={formError}
				onSubmit={submitForm}
				onCancel={editing === null ? undefined : () => setEditing(null)}
			/>

			<ConfirmDialog
				isOpen={pendingDelete !== null}
				title="Delete upstream"
				message={
					pendingDelete === null
						? ""
						: `Delete upstream "${pendingDelete.url}"? Queries stop being forwarded to it.`
				}
				confirmLabel="Delete"
				onConfirm={confirmDelete}
				onCancel={() => setPendingDelete(null)}
			/>
		</section>
	);
}
