/**
 * Activity: one surface over the queries nxdns answered, in two modes.
 *
 * History reads the persisted log and Live reads the stream, but they are the
 * same seven columns over the same filters, and the reader moves between them
 * without losing the question they were asking. The mode lives in the URL with
 * the filters, so an investigation is one link — including which half of it the
 * recipient should be looking at.
 */

import { Link, useNavigate, useSearch } from "@tanstack/react-router";
import * as stylex from "@stylexjs/stylex";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
import ActivityFilters, { NO_FILTERS, type AppliedFilters } from "./ActivityFilters";
import HistoryActivity from "./HistoryActivity";
import LiveActivity from "./LiveActivity";
import type { ActivityMode } from "./search";

const MODES: ReadonlyArray<{ mode: ActivityMode; label: string }> = [
	{ mode: "history", label: "History" },
	{ mode: "live", label: "Live" },
];

const styles = stylex.create({
	header: {
		display: "flex",
		flexWrap: "wrap",
		alignItems: "center",
		gap: "0.75rem",
	},
	heading: {
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	switch: {
		display: "flex",
		gap: "0.25rem",
		borderRadius: "0.25rem",
		borderWidth: 1,
		borderStyle: "solid",
		borderColor: colors.border,
		padding: "0.125rem",
	},
	modeButton: {
		borderStyle: "none",
		borderRadius: "0.1875rem",
		paddingInline: "0.75rem",
		paddingBlock: "0.25rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		fontWeight: 500,
		cursor: "pointer",
	},
	modeIdle: {
		backgroundColor: { default: "transparent", ":hover": colors.surfaceHover },
		color: { default: colors.textSecondary, ":hover": colors.text },
	},
	/** The selected mode reads as a filled chip, the same weight the nav uses. */
	modeSelected: {
		backgroundColor: colors.primary,
		color: colors.primaryText,
	},
	/** The one way into the simulation from here, so it cannot sit behind a row. */
	simulationLink: {
		marginInlineStart: "auto",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.primaryOnSurface,
		textDecorationLine: "none",
	},
	liveNote: {
		marginTop: "0.5rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.textMuted,
	},
});

export default function ActivityPage() {
	const search = useSearch({ from: "/shell/activity" });
	const navigate = useNavigate({ from: "/activity" });
	const live = search.mode === "live";

	// The functional form, not a replacement object: the filters are retained
	// across a mode switch on purpose, and spelling out a new search here would
	// drop every one of them on the way to Live and back.
	function selectMode(mode: ActivityMode) {
		if (mode === search.mode) return;
		void navigate({ search: (prev) => ({ ...prev, mode }) });
	}

	function apply(filters: AppliedFilters) {
		void navigate({ search: { mode: search.mode, ...filters } });
	}

	return (
		<section>
			<div {...stylex.props(styles.header)}>
				<h1 {...stylex.props(styles.heading)}>Activity</h1>
				<div role="group" aria-label="Activity mode" {...stylex.props(styles.switch)}>
					{MODES.map((option) => {
						const selected = option.mode === search.mode;
						return (
							<button
								key={option.mode}
								type="button"
								aria-pressed={selected}
								onClick={() => selectMode(option.mode)}
								{...stylex.props(
									styles.modeButton,
									selected ? styles.modeSelected : styles.modeIdle,
									shared.focusRing,
								)}
							>
								{option.label}
							</button>
						);
					})}
				</div>
				<Link to="/activity/test" {...stylex.props(styles.simulationLink, shared.focusRing)}>
					Current policy simulation
				</Link>
			</div>

			{/*
			 * Remounted whenever the applied search changes, which is what makes
			 * the back button work: the draft is derived state, and the browser
			 * moving the URL under it has to move the form with it.
			 */}
			<ActivityFilters
				key={`${search.domain ?? ""}|${search.client ?? ""}|${String(search.blocked)}|${String(search.since)}|${String(search.until)}`}
				applied={search}
				isDisabled={live}
				onApply={apply}
				onClear={() => apply(NO_FILTERS)}
			/>

			{live ? (
				<>
					<p {...stylex.props(styles.liveNote)}>
						The stream carries every query the server answers; these filters apply to history only.
					</p>
					<LiveActivity origin={search} />
				</>
			) : (
				<HistoryActivity search={search} />
			)}
		</section>
	);
}
