import { useMemo, useState } from "react";
import {
	Alert,
	Box,
	Button,
	Chip,
	FormControl,
	Grid,
	InputLabel,
	MenuItem,
	Paper,
	Select,
	Stack,
	Table,
	TableBody,
	TableCell,
	TableContainer,
	TableHead,
	TableRow,
	Typography,
} from "@mui/material";
import { MetricCard } from "./MetricCard";
import { MonitoringCharts } from "./MonitoringCharts";
import type { MonitoringMachine } from "../types";
import {
	useCollectorControls,
	useDiskSpace,
	useMachineActions,
	useMonitoringMetrics,
	useMonitoringStatus,
} from "../hooks/useMonitoring";

function formatBytes(bytes: number): string {
	if (!bytes || bytes === 0) return "0 B";
	const units = ["B", "KB", "MB", "GB", "TB"];
	let value = bytes;
	let unitIdx = 0;
	while (value >= 1000 && unitIdx < units.length - 1) {
		value /= 1000;
		unitIdx++;
	}
	return `${value.toFixed(1)} ${units[unitIdx]}`;
}

function formatRate(bytes: number): string {
	return `${formatBytes(bytes)}/s`;
}

function avg(arr: number[]) {
	return arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
}
function max(arr: number[]) {
	return arr.length ? Math.max(...arr) : 0;
}

function formatActionTime(epochSeconds: number): string {
	return new Date(epochSeconds * 1000).toLocaleString();
}

function ErrorBanner({ label, error }: { label: string; error: unknown }) {
	if (!error) return null;
	return (
		<Alert severity="error">
			{label}: {String(error)}
		</Alert>
	);
}

export function MachineMonitoringSection({
	machine,
}: {
	machine: MonitoringMachine;
}) {
	const statusQuery = useMonitoringStatus(machine.id, machine.enabled);
	const metricsQuery = useMonitoringMetrics(machine.id, machine.enabled);
	const diskQuery = useDiskSpace(machine.id, machine.enabled);
	const { start, stop, restart } = useCollectorControls(machine.id);
	const actionsQuery = useMachineActions(machine.id, machine.enabled);
	const [actionFilter, setActionFilter] = useState("all");
	const [resultFilter, setResultFilter] = useState("all");

	const status = statusQuery.data;
	const metrics = metricsQuery.data;
	const disk = diskQuery.data;
	const samples = metrics?.samples ?? [];
	const latest = samples.at(-1);
	const cpuArr = samples.map((s) => s.cpu_pct);
	const iowArr = samples.map((s) => s.iowait_pct ?? 0);
	const memArr = samples.map((s) => s.mem_pct);
	const netDownArr = samples.map((s) => s.net_rx_bytes_per_sec);
	const netUpArr = samples.map((s) => s.net_tx_bytes_per_sec);
	const diskReadArr = samples.map((s) => s.disk_read_bps);
	const diskWriteArr = samples.map((s) => s.disk_write_bps);
	const actions = actionsQuery.data?.items ?? [];
	const visibleActions = useMemo(
		() =>
			actions.filter((action) => {
				const actionMatches =
					actionFilter === "all" || action.action === actionFilter;
				const resultMatches =
					resultFilter === "all" || action.status === resultFilter;
				return actionMatches && resultMatches;
			}),
		[actions, actionFilter, resultFilter],
	);
	const hasQueryError =
		statusQuery.error ||
		metricsQuery.error ||
		diskQuery.error ||
		actionsQuery.error;

	return (
		<Stack spacing={2}>
			<Stack
				direction="row"
				spacing={1.5}
				sx={{ alignItems: "center", flexWrap: "wrap" }}
			>
				<Box>
					<Typography variant="h6" sx={{ fontWeight: 700 }}>
						{machine.name}
					</Typography>
					<Typography variant="caption" color="text.secondary">
						{machine.mode === "local"
							? "Local API host"
							: `${machine.username || "user"}@${machine.host || "host"}:${machine.port}`}
						{machine.media_root ? ` · media root ${machine.media_root}` : ""}
					</Typography>
				</Box>
				<Chip label={machine.mode} variant="outlined" />
				<Chip
					label={machine.enabled ? "Enabled" : "Disabled"}
					color={machine.enabled ? "success" : "default"}
					variant="outlined"
				/>
				<Chip
					label={status?.status ?? "unknown"}
					color={status?.status?.includes("running") ? "success" : "primary"}
					variant="outlined"
				/>
				<Button
					size="small"
					variant="outlined"
					onClick={() => start.mutate()}
					disabled={start.isPending || !machine.enabled}
				>
					Start
				</Button>
				<Button
					size="small"
					variant="outlined"
					onClick={() => restart.mutate()}
					disabled={restart.isPending || !machine.enabled}
				>
					Restart
				</Button>
				<Button
					size="small"
					variant="outlined"
					onClick={() => stop.mutate()}
					disabled={stop.isPending || !machine.enabled}
				>
					Stop
				</Button>
			</Stack>

			{hasQueryError && (
				<Stack spacing={1}>
					<ErrorBanner label="Status" error={statusQuery.error} />
					<ErrorBanner label="Metrics" error={metricsQuery.error} />
					<ErrorBanner label="Disk" error={diskQuery.error} />
					<ErrorBanner label="Recent activity" error={actionsQuery.error} />
				</Stack>
			)}

			<Grid container spacing={1.5}>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="CPU now"
						value={latest ? `${latest.cpu_pct.toFixed(1)}%` : "-"}
						subtext={`avg ${avg(cpuArr).toFixed(1)}%\npeak ${max(cpuArr).toFixed(1)}%`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="IO Wait"
						value={latest ? `${(latest.iowait_pct ?? 0).toFixed(1)}%` : "-"}
						subtext={`avg ${avg(iowArr).toFixed(1)}%\npeak ${max(iowArr).toFixed(1)}%`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="RAM now"
						value={latest ? `${latest.mem_pct.toFixed(1)}%` : "-"}
						subtext={`avg ${avg(memArr).toFixed(1)}%\npeak ${max(memArr).toFixed(1)}%`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="Net down"
						value={latest ? formatRate(latest.net_rx_bytes_per_sec) : "-"}
						subtext={`avg ${formatRate(avg(netDownArr))}\npeak ${formatRate(max(netDownArr))}`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="Net up"
						value={latest ? formatRate(latest.net_tx_bytes_per_sec) : "-"}
						subtext={`avg ${formatRate(avg(netUpArr))}\npeak ${formatRate(max(netUpArr))}`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="Disk read"
						value={latest ? formatRate(latest.disk_read_bps) : "-"}
						subtext={`avg ${formatRate(avg(diskReadArr))}\npeak ${formatRate(max(diskReadArr))}`}
					/>
				</Grid>
				<Grid size={{ xs: 6, md: 3, lg: 12 / 7 }}>
					<MetricCard
						label="Disk write"
						value={latest ? formatRate(latest.disk_write_bps) : "-"}
						subtext={`avg ${formatRate(avg(diskWriteArr))}\npeak ${formatRate(max(diskWriteArr))}`}
					/>
				</Grid>
			</Grid>

			{disk && (
				<Grid container spacing={1.5}>
					<Grid size={{ xs: 6, md: 3 }}>
						<MetricCard label="Disk used" value={formatBytes(disk.used)} />
					</Grid>
					<Grid size={{ xs: 6, md: 3 }}>
						<MetricCard
							label="Disk available"
							value={formatBytes(disk.available)}
						/>
					</Grid>
					<Grid size={{ xs: 6, md: 3 }}>
						<MetricCard label="Disk total" value={formatBytes(disk.size)} />
					</Grid>
					<Grid size={{ xs: 6, md: 3 }}>
						<MetricCard label="Used %" value={disk.used_pct} />
					</Grid>
				</Grid>
			)}

			<Box>
				<MonitoringCharts samples={samples} />
			</Box>

			<Stack spacing={1.5}>
				<Stack
					direction="row"
					spacing={1}
					sx={{ alignItems: "center", flexWrap: "wrap" }}
				>
					<Box>
						<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
							Recent activity
						</Typography>
						<Typography variant="caption" color="text.secondary">
							Collected automatically by the backend poller.
						</Typography>
					</Box>
					<Chip
						label={`${visibleActions.length}/${actions.length || 0}`}
						size="small"
						variant="outlined"
					/>
					<FormControl size="small" sx={{ minWidth: 150 }}>
						<InputLabel>Action</InputLabel>
						<Select
							label="Action"
							value={actionFilter}
							onChange={(e) => setActionFilter(e.target.value as string)}
						>
							<MenuItem value="all">All actions</MenuItem>
							<MenuItem value="status lookup">Status</MenuItem>
							<MenuItem value="metrics read">Metrics</MenuItem>
							<MenuItem value="disk lookup">Disk</MenuItem>
							<MenuItem value="collector start">Start</MenuItem>
							<MenuItem value="collector stop">Stop</MenuItem>
							<MenuItem value="collector restart">Restart</MenuItem>
							<MenuItem value="collector diagnostics">Diagnostics</MenuItem>
						</Select>
					</FormControl>
					<FormControl size="small" sx={{ minWidth: 120 }}>
						<InputLabel>Result</InputLabel>
						<Select
							label="Result"
							value={resultFilter}
							onChange={(e) => setResultFilter(e.target.value as string)}
						>
							<MenuItem value="all">All results</MenuItem>
							<MenuItem value="ok">OK</MenuItem>
							<MenuItem value="error">Error</MenuItem>
						</Select>
					</FormControl>
				</Stack>
				{actionsQuery.error && (
					<Alert severity="error">
						Recent activity: {String(actionsQuery.error)}
					</Alert>
				)}
				<TableContainer component={Paper} variant="outlined">
					<Table size="small">
						<TableHead>
							<TableRow>
								<TableCell>Time</TableCell>
								<TableCell>Action</TableCell>
								<TableCell>Status</TableCell>
								<TableCell align="right">Duration</TableCell>
								<TableCell>Message</TableCell>
							</TableRow>
						</TableHead>
						<TableBody>
							{visibleActions.length === 0 ? (
								<TableRow>
									<TableCell colSpan={5}>
										<Typography variant="body2" color="text.secondary">
											No activity matches the current filters.
										</Typography>
									</TableCell>
								</TableRow>
							) : (
								visibleActions.map((action) => (
									<TableRow
										key={`${action.machine_id}-${action.created_at}-${action.action}-${action.status}`}
									>
										<TableCell>{formatActionTime(action.created_at)}</TableCell>
										<TableCell>{action.action}</TableCell>
										<TableCell>
											<Chip
												size="small"
												label={action.status}
												color={action.status === "ok" ? "success" : "error"}
												variant="outlined"
											/>
										</TableCell>
										<TableCell align="right">{action.duration_ms} ms</TableCell>
										<TableCell>
											{action.message || action.error || "-"}
										</TableCell>
									</TableRow>
								))
							)}
						</TableBody>
					</Table>
				</TableContainer>
			</Stack>
		</Stack>
	);
}
