/**
 * The client column of the query tables reads as a name wherever one is known,
 * with the same precedence the Clients page applies: a hand-typed `name` wins,
 * the reverse-DNS `learned_name` stands in muted behind it, and an address with
 * neither — including one the loaded list has never seen — stays bare.
 *
 * The muted colour is the whole of the affordance here. The Clients page pairs
 * it with an outlined "learned" tag, and keeps it: one mention per client is
 * information. Repeating that tag down every row of a query table is noise, so
 * the tables carry the name alone.
 */

import { useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import * as stylex from "@stylexjs/stylex";
import { clientsQuery } from "@/lib/queries";
import type { Client } from "@/lib/types";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";

const styles = stylex.create({
	/** Secondary to the name it qualifies, and never the only thing in the cell. */
	address: {
		color: colors.textMuted,
	},
});

export type ClientNames = ReadonlyMap<string, Pick<Client, "name" | "learned_name">>;

/**
 * The live stream names clients the loaded list has never seen. Polling folds
 * them in on the next tick, which keeps the lookup a single cached query
 * instead of a fetch fired per unknown address.
 */
const CLIENTS_POLL_MS = 30_000;

export function useClientNames(): ClientNames {
	const { data } = useQuery({ ...clientsQuery(), refetchInterval: CLIENTS_POLL_MS });
	return useMemo(
		() =>
			new Map(
				(data ?? []).map((client) => [client.ip, { name: client.name, learned_name: client.learned_name }]),
			),
		[data],
	);
}

/**
 * The name the loaded list gives this address right now, or null when it gives
 * none. Callers that must distinguish "named" from "bare address" — rather than
 * just render whichever applies — read this instead of re-deriving precedence.
 */
export function clientLabel(ip: string, names: ClientNames): { text: string; learned: boolean } | null {
	const client = names.get(ip);
	if (client === undefined) return null;
	if (client.name !== "") return { text: client.name, learned: false };
	if (client.learned_name !== "") return { text: client.learned_name, learned: true };
	return null;
}

export function ClientName({ ip, names }: { ip: string; names: ClientNames }) {
	const label = clientLabel(ip, names);
	if (label === null) return <span {...stylex.props(shared.mono)}>{ip}</span>;
	// The name replaces the address, so the address follows it as real text that
	// anyone can read and copy. A `title` carried it before, which reaches
	// neither a keyboard nor a touch screen.
	return (
		<span {...stylex.props(label.learned && shared.learnedName)}>
			{label.text}
			<span {...stylex.props(styles.address)}> ({ip})</span>
		</span>
	);
}
