import {
	BrowserRouter,
	Routes,
	Route,
	NavLink,
	useLocation,
} from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ThemeProvider } from "@mui/material/styles";
import {
	AppBar,
	Toolbar,
	Typography,
	Box,
	Tabs,
	Tab,
	Container,
	CssBaseline,
	Chip,
	useMediaQuery,
	Button,
	Stack,
	Card,
	CardContent,
	CircularProgress,
} from "@mui/material";
import { useEffect, useMemo } from "react";
import { AuthProvider, useAuth } from "react-oidc-context";
import { Dashboard } from "./pages/Dashboard";
import { Monitoring } from "./pages/Monitoring";
import { Media } from "./pages/Media";
import { UsersPage } from "./pages/Users";
import { FileBrowser } from "./pages/FileBrowser";
import { getAppTheme } from "./theme";
import { getOidcConfig, isOidcConfigured, setAccessToken } from "./auth";

const queryClient = new QueryClient({
	defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false } },
});

function Shell({
	darkMode,
	authLabel,
	onSignOut,
}: {
	darkMode: boolean;
	authLabel?: string;
	onSignOut?: () => void;
}) {
	const location = useLocation();
	const current = location.pathname;

	return (
		<>
			<CssBaseline />
			<AppBar position="sticky" color="inherit" elevation={0}>
				<Toolbar sx={{ display: "flex", gap: 2, minHeight: 68 }}>
					<Typography variant="h6" sx={{ mr: 2, fontWeight: 700 }}>
						Media Library Viewer
					</Typography>
					<Tabs
						value={current}
						textColor="primary"
						indicatorColor="primary"
						sx={{ flex: 1 }}
					>
						<Tab value="/" label="Dashboard" component={NavLink} to="/" />
						<Tab
							value="/monitoring"
							label="Monitoring"
							component={NavLink}
							to="/monitoring"
						/>
						<Tab value="/media" label="Media" component={NavLink} to="/media" />
						<Tab value="/users" label="Users" component={NavLink} to="/users" />
						<Tab
							value="/files"
							label="File Browser"
							component={NavLink}
							to="/files"
						/>
					</Tabs>
					<Stack direction="row" spacing={1} sx={{ alignItems: "center" }}>
						{authLabel && (
							<Chip size="small" variant="outlined" label={authLabel} />
						)}
						<Chip
							size="small"
							variant="outlined"
							label={darkMode ? "Dark" : "Light"}
						/>
						{onSignOut && (
							<Button size="small" variant="text" onClick={onSignOut}>
								Sign out
							</Button>
						)}
					</Stack>
				</Toolbar>
			</AppBar>
			<Container maxWidth={false} sx={{ py: 3 }}>
				<Routes>
					<Route path="/" element={<Dashboard />} />
					<Route path="/monitoring" element={<Monitoring />} />
					<Route path="/media" element={<Media />} />
					<Route path="/users" element={<UsersPage />} />
					<Route path="/files" element={<FileBrowser />} />
				</Routes>
			</Container>
		</>
	);
}

function LoadingScreen({ label }: { label: string }) {
	return (
		<Box
			sx={{
				minHeight: "100vh",
				display: "grid",
				placeItems: "center",
				p: 2,
			}}
		>
			<Card variant="outlined" sx={{ maxWidth: 420, width: "100%" }}>
				<CardContent>
					<Stack spacing={2} sx={{ alignItems: "center", textAlign: "center" }}>
						<CircularProgress />
						<Typography variant="h6">{label}</Typography>
					</Stack>
				</CardContent>
			</Card>
		</Box>
	);
}

function SignInScreen({ onSignIn }: { onSignIn: () => void }) {
	return (
		<Box
			sx={{
				minHeight: "100vh",
				display: "grid",
				placeItems: "center",
				p: 2,
			}}
		>
			<Card variant="outlined" sx={{ maxWidth: 460, width: "100%" }}>
				<CardContent>
					<Stack spacing={2} sx={{ alignItems: "center", textAlign: "center" }}>
						<Typography variant="h5">Sign in required</Typography>
						<Typography variant="body2" color="text.secondary">
							Use your Authentik account to access the media library viewer.
						</Typography>
						<Button variant="contained" onClick={onSignIn}>
							Sign in with OIDC
						</Button>
					</Stack>
				</CardContent>
			</Card>
		</Box>
	);
}

function AuthenticatedApp({ darkMode }: { darkMode: boolean }) {
	const auth = useAuth();
	useEffect(() => {
		setAccessToken(auth.user?.access_token ?? null);
	}, [auth.user?.access_token]);

	const authLabel = useMemo(() => {
		const profile = auth.user?.profile as Record<string, unknown> | undefined;
		return String(
			profile?.name ??
				profile?.preferred_username ??
				profile?.email ??
				auth.user?.profile?.sub ??
				"Authenticated",
		);
	}, [auth.user]);

	if (auth.isLoading || auth.activeNavigator) {
		return <LoadingScreen label="Checking sign-in…" />;
	}

	if (auth.error) {
		return (
			<LoadingScreen
				label={`Authentication error: ${auth.error.message || "Unable to sign in"}`}
			/>
		);
	}

	if (!auth.isAuthenticated) {
		return <SignInScreen onSignIn={() => void auth.signinRedirect()} />;
	}

	return (
		<Box sx={{ minHeight: "100vh", bgcolor: "background.default" }}>
			<BrowserRouter>
				<Shell
					darkMode={darkMode}
					authLabel={authLabel}
					onSignOut={() => void auth.signoutRedirect()}
				/>
			</BrowserRouter>
		</Box>
	);
}

function AppInner() {
	const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
	const theme = useMemo(
		() => getAppTheme(prefersDarkMode ? "dark" : "light"),
		[prefersDarkMode],
	);

	return (
		<ThemeProvider theme={theme}>
			<QueryClientProvider client={queryClient}>
				{isOidcConfigured() ? (
					<AuthProvider {...getOidcConfig()}>
						<AuthenticatedApp darkMode={prefersDarkMode} />
					</AuthProvider>
				) : (
					<Box sx={{ minHeight: "100vh", bgcolor: "background.default" }}>
						<BrowserRouter>
							<Shell darkMode={prefersDarkMode} />
						</BrowserRouter>
					</Box>
				)}
			</QueryClientProvider>
		</ThemeProvider>
	);
}

export default function App() {
	return <AppInner />;
}
