"use client";

import { useEffect, useState, useRef, useCallback } from "react";
import { getStats, type Stats, type NetworkInterface } from "./lib/getStats";

import NavBar from "./components/NavBar";
import Hero from "./components/Hero";
import StatsGrid from "./components/StatsGrid";
import ServicesCard from "./components/ServicesCard";
import UptimeCard from "./components/UptimeCard";
import NetworkCard from "./components/NetworkCard";
import PowerGrid from "./components/PowerGrid";
import LinksGrid from "./components/LinksGrid";
import DevConsole, { type LogEntry } from "./components/DevConsole";
import { useCheckAuth } from "@/hooks/useCheckAuth";
import { useRouter } from "next/navigation";
import { getPower, type PowerData } from "./lib/getPower";

export default function Home() {
	const router = useRouter();
	useCheckAuth();

	const [stats, setStats] = useState<Stats | null>(null);
	const [power, setPower] = useState<PowerData | null>(null);
	const [netSpeed, setNetSpeed] = useState<
		Record<string, { rx: number; tx: number }>
	>({});

	const [panelOpen, setPanelOpen] = useState(false);
	const [panelWidth, setPanelWidth] = useState(440);
	const [isMobile, setIsMobile] = useState(false);
	const [logs, setLogs] = useState<LogEntry[]>([]);

	const prevNetRef = useRef<Record<string, NetworkInterface> | null>(null);
	const lastFetchRef = useRef<number>(0);
	const logIdRef = useRef(0);

	// Mobile detection
	useEffect(() => {
		const check = () => setIsMobile(window.innerWidth < 768);
		check();
		window.addEventListener("resize", check);
		return () => window.removeEventListener("resize", check);
	}, []);

	// Fetch interceptor — captures all /api/* requests
	useEffect(() => {
		const original = window.fetch;

		window.fetch = async (input, init) => {
			const url =
				typeof input === "string"
					? input
					: input instanceof URL
					? input.href
					: (input as Request).url;

			const shouldLog =
				(url.startsWith("/api/") && !url.startsWith("/api/dev/proxy")) ||
				url.includes("localhost:3001");

			if (!shouldLog) return original(input, init);

			const method = ((init?.method ?? (input instanceof Request ? input.method : "GET")) as string).toUpperCase();
			const id = ++logIdRef.current;
			let path = url;
			try {
				path = new URL(url, window.location.origin).pathname;
			} catch {
				// use raw url
			}
			const timestamp = new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
			const start = Date.now();

			setLogs((prev) => [
				...prev,
				{ id, method, path, url, status: null, duration: null, timestamp, response: null },
			]);

			try {
				const res = await original(input, init);
				const clone = res.clone();
				const text = await clone.text();
				const duration = Date.now() - start;
				setLogs((prev) =>
					prev.map((e) => (e.id === id ? { ...e, status: res.status, duration, response: text } : e))
				);
				return res;
			} catch (err) {
				const duration = Date.now() - start;
				setLogs((prev) =>
					prev.map((e) => (e.id === id ? { ...e, status: 0, duration, response: String(err) } : e))
				);
				throw err;
			}
		};

		return () => {
			window.fetch = original;
		};
	}, []);

	useEffect(() => {
		const fetchData = async () => {
			try {
				const now = Date.now();
				const data = await getStats();

				if (prevNetRef.current && lastFetchRef.current > 0) {
					const elapsed = (now - lastFetchRef.current) / 1000;
					const speeds: Record<string, { rx: number; tx: number }> = {};

					for (const iface of Object.keys(data.network)) {
						const prev = prevNetRef.current[iface];
						if (prev) {
							speeds[iface] = {
								rx: Math.max(0, (data.network[iface].rx - prev.rx) / elapsed),
								tx: Math.max(0, (data.network[iface].tx - prev.tx) / elapsed),
							};
						}
					}
					setNetSpeed(speeds);
				}

				prevNetRef.current = data.network;
				lastFetchRef.current = now;
				setStats(data);
			} catch (e) {
				if (e instanceof Error && e.message === "UNAUTHORIZED") {
					router.push(
						"/auth?callbackUrl=" + encodeURIComponent(window.location.pathname),
					);
					return;
				}
				console.error("Dashboard fetch failed:", e);
			}
		};

		fetchData();
		const id = setInterval(fetchData, 4000);
		return () => clearInterval(id);
	}, []);

	const fetchPower = useCallback(async () => {
		try {
			setPower(await getPower());
		} catch (e) {
			if (e instanceof Error && e.message === "UNAUTHORIZED") return;
			console.error("Power fetch failed:", e);
		}
	}, []);

	useEffect(() => {
		fetchPower();
		const id = setInterval(fetchPower, 10000);
		return () => clearInterval(id);
	}, [fetchPower]);

	const primaryIface = stats
		? Object.keys(stats.network).find(
				(k) =>
					!k.startsWith("docker") &&
					!k.startsWith("br-") &&
					stats.network[k].rx > 0,
			)
		: null;

	const primarySpeed = primaryIface ? netSpeed[primaryIface] || null : null;

	return (
		<>
			<div
				style={{
					paddingRight: panelOpen && !isMobile ? panelWidth : 0,
					transition: "padding-right 280ms cubic-bezier(0.4,0,0.2,1)",
				}}
			>
				<div className="max-w-5xl mx-auto px-6 pb-20">
					<NavBar
						online={!!stats}
						devConsoleOpen={panelOpen}
						onToggleDevConsole={() => setPanelOpen((o) => !o)}
					/>
					<Hero lastUpdated={stats?.timestamp ?? null} />

					<div className="flex items-baseline justify-between mb-5">
						<h2 className="text-lg font-medium tracking-tight text-gray-900">
							System Stats
						</h2>
					</div>

					<StatsGrid stats={stats} />

					<div className="grid grid-cols-1 md:grid-cols-2 gap-3.5 mb-11">
						<ServicesCard services={stats?.services ?? null} delay={200} />
						<div className="flex flex-col gap-3.5">
							<UptimeCard uptime={stats?.uptime ?? null} delay={250} />
							<NetworkCard
								iface={primaryIface ?? null}
								speed={primarySpeed}
								delay={300}
							/>
						</div>
					</div>

					<div className="flex items-baseline justify-between mb-5">
						<h2 className="text-lg font-medium tracking-tight text-gray-900">
							Power Consumption
						</h2>
					</div>

					<PowerGrid power={power} onRefresh={fetchPower} />

					<LinksGrid />
				</div>
			</div>

			<DevConsole
				open={panelOpen}
				width={panelWidth}
				isMobile={isMobile}
				onClose={() => setPanelOpen(false)}
				onWidthChange={setPanelWidth}
				logs={logs}
			/>
		</>
	);
}
