import { useEffect, useState, type FormEvent } from "react";
import { useRouter, useSearch } from "@tanstack/react-router";
import * as stylex from "@stylexjs/stylex";
import { ApiError } from "@/lib/api";
import { useAuth } from "@/auth/store";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";

const styles = stylex.create({
	/** Login renders outside AppShell, so it paints the page ground itself. */
	page: {
		display: "flex",
		minHeight: "100dvh",
		alignItems: "center",
		justifyContent: "center",
		backgroundColor: colors.surface,
		color: colors.text,
		padding: "1rem",
	},
	card: {
		width: "100%",
		maxWidth: "24rem",
	},
	heading: {
		fontSize: "1.5rem",
		lineHeight: "2rem",
		fontWeight: 600,
	},
	probing: {
		marginTop: "1rem",
		color: colors.textMuted,
	},
	form: {
		display: "flex",
		flexDirection: "column",
		gap: "1rem",
		marginTop: "1.5rem",
	},
	fieldLabel: {
		display: "block",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		fontWeight: 500,
	},
	submit: {
		width: "100%",
	},
	error: {
		marginTop: "1rem",
		fontSize: "0.875rem",
		lineHeight: "1.25rem",
		color: colors.danger,
	},
});

export function safeRedirect(raw: string | undefined): string {
	if (raw === undefined) return "/";
	if (!/^\/(?![/\\])/.test(raw) || raw.includes("\\")) return "/";
	return raw;
}

function errorMessage(error: unknown, remaining: number | null): string {
	if (error instanceof ApiError) {
		if (error.status === 401) return "Incorrect password.";
		if (error.status === 429) {
			return remaining !== null && remaining > 0
				? `Too many attempts. Try again in ${remaining}s.`
				: "Too many attempts. Try again shortly.";
		}
		if (error.status === 503) return "The server is starting or degraded. Try again shortly.";
		return error.message;
	}
	return "Could not reach the server.";
}

export default function LoginPage() {
	const { authRequired, probe, login } = useAuth();
	const router = useRouter();
	const search = useSearch({ from: "/login" });
	const redirect = safeRedirect(search.redirect);

	const [password, setPassword] = useState("");
	const [error, setError] = useState<unknown>(null);
	const [busy, setBusy] = useState(false);

	const retryAfter = error instanceof ApiError && error.status === 429 ? (error.retryAfter ?? null) : null;
	const [remaining, setRemaining] = useState<number | null>(null);

	useEffect(() => {
		setRemaining(retryAfter);
		if (retryAfter === null) return;
		const timer = setInterval(() => setRemaining((s) => (s === null || s <= 1 ? 0 : s - 1)), 1000);
		return () => clearInterval(timer);
	}, [error, retryAfter]);

	const lockedOut = remaining !== null && remaining > 0;

	useEffect(() => {
		if (authRequired === false) {
			router.history.replace(redirect);
			return;
		}
		if (authRequired === null) {
			probe()
				.then((required) => {
					if (!required) router.history.replace(redirect);
				})
				.catch((probeError: unknown) => setError(probeError));
		}
	}, [authRequired, probe, redirect, router]);

	async function onSubmit(event: FormEvent<HTMLFormElement>) {
		event.preventDefault();
		if (busy || lockedOut) return;
		setBusy(true);
		setError(null);
		try {
			await login(password);
			router.history.push(redirect);
		} catch (loginError) {
			setError(loginError);
		} finally {
			setBusy(false);
		}
	}

	return (
		<main {...stylex.props(styles.page)}>
			<section {...stylex.props(styles.card)}>
				<h1 {...stylex.props(styles.heading)}>nxdns</h1>
				{authRequired !== true ? (
					<p {...stylex.props(styles.probing)}>Checking whether a password is required…</p>
				) : (
					<form onSubmit={onSubmit} {...stylex.props(styles.form)}>
						<div>
							<label htmlFor="password" {...stylex.props(styles.fieldLabel)}>
								Password
							</label>
							<input
								id="password"
								type="password"
								autoComplete="current-password"
								autoFocus
								required
								value={password}
								onChange={(event) => setPassword(event.target.value)}
								{...stylex.props(shared.input, shared.focusRing)}
							/>
						</div>
						<button
							type="submit"
							disabled={busy || lockedOut}
							{...stylex.props(shared.largePrimaryButton, styles.submit, shared.focusRing)}
						>
							{busy ? "Logging in…" : "Log in"}
						</button>
					</form>
				)}
				{error !== null && (
					<p role="alert" {...stylex.props(styles.error)}>
						{errorMessage(error, remaining)}
					</p>
				)}
			</section>
		</main>
	);
}
