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,
	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 { Applications } from "./pages/Applications";
import { Settings } from "./pages/Settings";
import { UsersPage } from "./pages/Users";
import { FileBrowser } from "./pages/FileBrowser";
import { Actions } from "./pages/Actions";
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;
	const isMobile = useMediaQuery("(max-width: 900px)");

	return (
		<>
			<CssBaseline />
			<AppBar
				position="sticky"
				color="inherit"
				elevation={0}
				sx={{
					borderBottom: 1,
					borderColor: "divider",
					backgroundImage: "none",
				}}
			>
				<Box
					sx={{
						display: "flex",
						flexDirection: { xs: "column", md: "row" },
						alignItems: { xs: "stretch", md: "center" },
						justifyContent: "space-between",
						gap: 1.5,
						px: { xs: 1.5, sm: 2.5, md: 3 },
						py: { xs: 1, md: 1.25 },
					}}
				>
					<Box
						sx={{
							display: "flex",
							alignItems: "center",
							gap: 1.5,
							minWidth: 0,
						}}
					>
						<Box
							sx={{
								width: 42,
								height: 42,
								borderRadius: 2,
								display: "grid",
								placeItems: "center",
								fontWeight: 800,
								fontSize: 20,
								color: "primary.contrastText",
								bgcolor: "primary.main",
								backgroundImage:
									"linear-gradient(135deg, rgba(255,255,255,0.22), rgba(255,255,255,0))",
								boxShadow: 1,
								flexShrink: 0,
							}}
						>
							M
						</Box>
						<Box sx={{ minWidth: 0 }}>
							<Typography
								variant="h6"
								sx={{ fontWeight: 800, lineHeight: 1.05 }}
							>
								Manage
							</Typography>
							<Typography variant="caption" color="text.secondary" noWrap>
								Media operations dashboard
							</Typography>
						</Box>
					</Box>

					<Stack
						direction="row"
						spacing={1}
						sx={{
							alignItems: "center",
							flexWrap: "wrap",
							justifyContent: { xs: "flex-start", md: "flex-end" },
							width: { xs: "100%", md: "auto" },
						}}
					>
						{authLabel && (
							<Chip
								label={authLabel}
								variant="outlined"
								sx={{ maxWidth: { xs: "100%", sm: 220 } }}
							/>
						)}
						<Chip label={darkMode ? "Dark" : "Light"} variant="outlined" />
						{onSignOut && (
							<Button
								variant="outlined"
								onClick={onSignOut}
								sx={{ whiteSpace: "nowrap" }}
							>
								Logout
							</Button>
						)}
					</Stack>
				</Box>

				<Box sx={{ borderTop: 1, borderColor: "divider" }}>
					<Tabs
						value={current}
						textColor="primary"
						indicatorColor="primary"
						variant={isMobile ? "scrollable" : "standard"}
						scrollButtons="auto"
						allowScrollButtonsMobile
						sx={{
							px: { xs: 0.75, sm: 1.5, md: 3 },
							minHeight: 44,
							"& .MuiTab-root": {
								minHeight: 44,
								py: 1,
								px: 1.5,
								minWidth: { xs: 88, md: 108 },
								textTransform: "none",
								fontWeight: 600,
							},
						}}
					>
						<Tab value="/" label="Dashboard" component={NavLink} to="/" />
						<Tab
							value="/monitoring"
							label="Monitoring"
							component={NavLink}
							to="/monitoring"
						/>
						<Tab
							value="/applications"
							label="Applications"
							component={NavLink}
							to="/applications"
						/>
						<Tab value="/users" label="Users" component={NavLink} to="/users" />
						<Tab
							value="/actions"
							label="Actions"
							component={NavLink}
							to="/actions"
						/>
						<Tab value="/files" label="Files" component={NavLink} to="/files" />
						<Tab
							value="/settings"
							label="Settings"
							component={NavLink}
							to="/settings"
						/>
					</Tabs>
				</Box>
			</AppBar>
			<Container
				maxWidth={false}
				sx={{ py: { xs: 1.5, md: 2 }, px: { xs: 1.25, sm: 2, md: 2.5 } }}
			>
				<Routes>
					<Route path="/" element={<Dashboard />} />
					<Route path="/monitoring" element={<Monitoring />} />
					<Route path="/applications" element={<Applications />} />
					<Route path="/media" element={<Applications />} />
					<Route path="/users" element={<UsersPage />} />
					<Route path="/actions" element={<Actions />} />
					<Route path="/files" element={<FileBrowser />} />
					<Route path="/settings" element={<Settings />} />
				</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 Manage.
						</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 />;
}
