import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { Link, useParams } from "@tanstack/react-router";
import * as stylex from "@stylexjs/stylex";
import InlineError from "@/lib/InlineError";
import { formatTime } from "@/lib/format";
import { clientsQuery } from "@/lib/queries";
import { useAuthority } from "@/features/configuration/authority";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
import { ClientDisplayName, provenanceOf } from "./clientIdentity";

/** The Activity window this page offers: the last day, in seconds. */
const ACTIVITY_WINDOW_SECONDS = 24 * 60 * 60;

const nowInSeconds = () => Math.floor(Date.now() / 1000);

const styles = stylex.create({
	back: {
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.primaryOnSurface,
		textDecorationLine: "none",
	},
	heading: {
		marginTop: "0.5rem",
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	address: {
		marginTop: "0.25rem",
		color: colors.textSecondary,
	},
	panel: {
		marginTop: "1rem",
		maxWidth: "48rem",
		borderRadius: "0.25rem",
		borderWidth: 1,
		borderStyle: "solid",
		borderColor: colors.border,
		backgroundColor: colors.surfaceRaised,
		padding: "1rem",
	},
	facts: {
		display: "grid",
		gap: "0.5rem 1rem",
		gridTemplateColumns: {
			default: "auto",
			"@media (min-width: 640px)": "max-content 1fr",
		},
		margin: 0,
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	term: {
		color: colors.textMuted,
	},
	value: {
		margin: 0,
	},
	provenanceDetail: {
		marginTop: "0.125rem",
		color: colors.textMuted,
	},
	sectionHeading: {
		marginTop: "1.5rem",
		fontSize: "1.125rem",
		lineHeight: "1.75rem",
		fontWeight: 600,
	},
	prose: {
		marginTop: "0.5rem",
		maxWidth: "48rem",
		fontSize: "0.875rem",
		lineHeight: "1.5rem",
	},
	links: {
		marginTop: "0.75rem",
		display: "flex",
		flexWrap: "wrap",
		gap: "1rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	link: {
		color: colors.primaryOnSurface,
	},
	loading: {
		marginTop: "1rem",
		color: colors.textMuted,
	},
});

function BackLink() {
	return (
		<Link to="/clients" search={{}} {...stylex.props(styles.back, shared.focusRing)}>
			← All clients
		</Link>
	);
}

/**
 * One client, addressed by the row id `PUT /api/clients/{id}` already uses.
 *
 * No endpoint answers for a single client, so the list is the source: the route
 * loader ensures it, which makes a cold deep link one fetch rather than a
 * miss. An id the loaded list does not contain is a row that was deleted or
 * never existed — a state this page explains once, with no refetch behind it.
 */
export default function ClientDetailPage() {
	const { id } = useParams({ from: "/shell/clients/$id" });
	const clientId = Number(id);
	const { data, error, isPending, refetch } = useQuery(clientsQuery());
	const authority = useAuthority();
	// The Activity window is relative to now, and a real link must carry its
	// bounds in the href before the click — that is what makes middle-click,
	// copy-link and open-in-new-tab work. A page left open would otherwise link
	// to yesterday's day, so the window is re-minted when the link is about to be
	// used: pointerdown precedes the click, and keydown precedes the click Enter
	// synthesizes. Focus re-mints too, but it cannot be the last word — a link can
	// hold focus for hours before the keypress. All three are discrete events, so
	// the href is fresh by the time navigation reads it.
	const [activityUntil, setActivityUntil] = useState(nowInSeconds);
	const freshenActivityWindow = () => setActivityUntil(nowInSeconds());

	if (isPending) {
		return (
			<p {...stylex.props(styles.loading, shared.pulse)} role="status">
				Loading client…
			</p>
		);
	}

	if (data === undefined) {
		return (
			<section>
				<BackLink />
				<InlineError error={error} onRetry={() => void refetch()} />
			</section>
		);
	}

	const client = data.find((row) => row.id === clientId);
	if (client === undefined) {
		return (
			<section>
				<BackLink />
				<h1 {...stylex.props(styles.heading)}>No such client</h1>
				<p {...stylex.props(styles.prose)}>
					nxdns has no client with id {id}. It was deleted, or the link was to a row that never existed. A
					device that is still on the network reappears in the list on its next DNS query.
				</p>
			</section>
		);
	}

	const provenance = provenanceOf(client, authority);

	return (
		<section>
			<BackLink />
			<h1 {...stylex.props(styles.heading)}>
				<ClientDisplayName client={client} />
			</h1>
			<p {...stylex.props(styles.address, shared.mono)}>{client.ip}</p>

			<div {...stylex.props(styles.panel)}>
				<dl {...stylex.props(styles.facts)}>
					<dt {...stylex.props(styles.term)}>Name</dt>
					<dd {...stylex.props(styles.value)}>
						<ClientDisplayName client={client} />
					</dd>
					<dt {...stylex.props(styles.term)}>Provenance</dt>
					<dd {...stylex.props(styles.value)}>
						{provenance.label}
						<span {...stylex.props(styles.provenanceDetail)}> — {provenance.detail}</span>
					</dd>
					<dt {...stylex.props(styles.term)}>First seen</dt>
					<dd {...stylex.props(styles.value)}>{formatTime(client.first_seen)}</dd>
					<dt {...stylex.props(styles.term)}>Last seen</dt>
					<dd {...stylex.props(styles.value)}>{formatTime(client.last_seen)}</dd>
				</dl>
			</div>

			<h2 {...stylex.props(styles.sectionHeading)}>Policy</h2>
			<p {...stylex.props(styles.prose)}>
				Filtering for this client follows the <strong>{client.group}</strong> group: its safe search setting,
				its blocklist sources and its rules.
			</p>
			<p {...stylex.props(styles.links)}>
				<Link
					to="/configuration/protection"
					search={{ tab: "groups", group: client.group_id }}
					{...stylex.props(styles.link, shared.focusRing)}
				>
					Group settings
				</Link>
			</p>

			<h2 {...stylex.props(styles.sectionHeading)}>Activity</h2>
			<p {...stylex.props(styles.links)}>
				<Link
					to="/activity"
					search={{
						mode: "history",
						client: client.ip,
						since: activityUntil - ACTIVITY_WINDOW_SECONDS,
						until: activityUntil,
						domain: undefined,
						blocked: undefined,
					}}
					onPointerDown={freshenActivityWindow}
					onFocus={freshenActivityWindow}
					onKeyDown={(event) => {
						if (event.key === "Enter") freshenActivityWindow();
					}}
					{...stylex.props(styles.link, shared.focusRing)}
				>
					Queries from this client, last 24 hours
				</Link>
			</p>
		</section>
	);
}
