/**
 * The part of Overview that does not wait for anything: the heading, the period
 * picker, and the pulsing body the page shows while the window is in flight.
 *
 * It lives apart from `OverviewPage` so the route's pending component can render
 * the identical surface while the page chunk loads. Importing the page itself
 * would pull the charts into the main bundle, and a second hand-written copy of
 * the frame would drift. Nothing here imports a chart.
 */

import * as stylex from "@stylexjs/stylex";
import { useNavigate, useSearch } from "@tanstack/react-router";
import { Radio, RadioGroup } from "react-aria-components";
import type { Period } from "@/lib/types";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
import { DEFAULT_PERIOD, PERIODS } from "./period";

const styles = stylex.create({
	page: {
		display: "flex",
		flexDirection: "column",
		gap: "1rem",
	},
	headingRow: {
		display: "flex",
		flexWrap: "wrap",
		alignItems: "center",
		justifyContent: "space-between",
		gap: "0.75rem",
	},
	heading: {
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	periodGroup: {
		display: "flex",
		gap: "0.25rem",
	},
	period: {
		cursor: "pointer",
		borderStyle: "none",
		borderRadius: "0.25rem",
		paddingInline: "0.625rem",
		paddingBlock: "0.25rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
	},
	/** A Radio is a `label`, so RAC drives the ring rather than `:focus-visible`. */
	periodFocusVisible: {
		outlineWidth: 2,
		outlineStyle: "solid",
		outlineColor: colors.focus,
		outlineOffset: 2,
	},
	/** The pressed fill is heavier than `surfaceHover`, so a hover cannot mimic it. */
	periodSelected: {
		backgroundColor: {
			default: "oklch(92% 0.004 286.32)",
			"@media (prefers-color-scheme: dark)": "oklch(37% 0.013 285.805)",
		},
		color: colors.text,
		fontWeight: 500,
	},
	periodIdle: {
		backgroundColor: { default: "transparent", ":hover": colors.surfaceHover },
		color: colors.textSecondary,
	},
	loading: {
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.textMuted,
	},
});

export function PeriodPicker({ period, onChange }: { period: Period; onChange: (period: Period) => void }) {
	return (
		<RadioGroup
			aria-label="Period"
			orientation="horizontal"
			value={period}
			onChange={(next) => onChange(next as Period)}
			className={() => stylex.props(styles.periodGroup).className ?? ""}
		>
			{PERIODS.map((option) => (
				<Radio
					key={option}
					value={option}
					className={({ isSelected, isFocusVisible }) =>
						stylex.props(
							styles.period,
							isSelected ? styles.periodSelected : styles.periodIdle,
							isFocusVisible && styles.periodFocusVisible,
						).className ?? ""
					}
				>
					{option}
				</Radio>
			))}
		</RadioGroup>
	);
}

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

export function OverviewFrame({
	period,
	onChange,
	children,
}: {
	period: Period;
	onChange: (period: Period) => void;
	children: React.ReactNode;
}) {
	return (
		<div {...stylex.props(styles.page)}>
			<div {...stylex.props(styles.headingRow)}>
				<h1 {...stylex.props(styles.heading)}>Overview</h1>
				<PeriodPicker period={period} onChange={onChange} />
			</div>
			{children}
		</div>
	);
}

/**
 * The route's pending surface. The picker stays live because it only writes the
 * search parameter, which the route already re-reads on its own.
 */
export function OverviewPending() {
	const period = useSearch({ from: "/shell/overview" }).period ?? DEFAULT_PERIOD;
	const navigate = useNavigate({ from: "/overview" });
	return (
		<OverviewFrame
			period={period}
			onChange={(next) => void navigate({ search: (prev) => ({ ...prev, period: next }) })}
		>
			<OverviewLoading />
		</OverviewFrame>
	);
}
