"use client";

import { useEffect, useState, useCallback, useRef } from "react";
import {
	ResponsiveContainer, LineChart, Line, BarChart, Bar,
	XAxis, YAxis, Tooltip, CartesianGrid, Legend, Brush, ReferenceArea,
} from "recharts";
import { IconRefresh } from "@tabler/icons-react";
import SideNav from "../components/SideNav";

// ── Types ────────────────────────────────────────────────────────────────────

interface DeviceReading { name: string; watts: number; on: boolean; today_wh: number; month_wh: number; }
interface HistoryEntry { ts: string; devices: DeviceReading[]; }
interface Candle { open: number; close: number; high: number; low: number; }
interface CandleBucket { ts: number; label: string; [device: string]: Candle | number | string; }
type ChartType = "line" | "bar" | "candle";

const COST_PER_KWH = 0.24; // LADWP Northridge CA 2025
const DEVICE_COLORS: Record<string, string> = { server: "#428ce2", desktop: "#a78bfa" };
const CHART_MARGIN = { top: 4, right: 16, bottom: 4, left: 0 };

// ── Helpers ──────────────────────────────────────────────────────────────────

function fmtTs(ts: string, spanH: number): string {
	const d = new Date(ts);
	if (spanH <= 24) return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
	return d.toLocaleDateString([], { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
}

function fmtDt(iso: string) {
	// "2025-01-15T14:30" → "Jan 15, 2:30 PM"
	try { return new Date(iso).toLocaleString([], { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); }
	catch { return iso; }
}

function bucketCandles(readings: HistoryEntry[], spanH: number): CandleBucket[] {
	const bucketMs = (spanH <= 6 ? 30 : spanH <= 24 ? 60 : spanH <= 168 ? 360 : 1440) * 60_000;
	const map = new Map<number, Map<string, number[]>>();
	for (const r of readings) {
		const key = Math.floor(new Date(r.ts).getTime() / bucketMs) * bucketMs;
		if (!map.has(key)) map.set(key, new Map());
		for (const d of r.devices) {
			if (!map.get(key)!.has(d.name)) map.get(key)!.set(d.name, []);
			map.get(key)!.get(d.name)!.push(d.watts);
		}
	}
	return Array.from(map.entries()).sort(([a], [b]) => a - b).map(([ts, devices]) => {
		const label = fmtTs(new Date(ts).toISOString(), spanH);
		const pt: CandleBucket = { ts, label };
		for (const [name, watts] of devices) {
			const s = [...watts].sort((a, b) => a - b);
			pt[name] = { open: watts[0], close: watts[watts.length - 1], high: s[s.length - 1], low: s[0] };
		}
		return pt;
	});
}

function computeSummary(readings: HistoryEntry[], deviceName: string) {
	const pts = readings.map(r => {
		const d = r.devices.find(x => x.name === deviceName);
		return d ? { ts: new Date(r.ts).getTime(), watts: d.watts, on: d.on } : null;
	}).filter(Boolean).sort((a, b) => a!.ts - b!.ts) as { ts: number; watts: number; on: boolean }[];
	if (!pts.length) return null;
	const avgW = pts.reduce((s, p) => s + p.watts, 0) / pts.length;
	const peakW = Math.max(...pts.map(p => p.watts));
	const uptimePct = pts.filter(p => p.on).length / pts.length * 100;
	let kWh = pts.length >= 2
		? pts.slice(1).reduce((s, p, i) => s + (p.watts + pts[i].watts) / 2 * (p.ts - pts[i].ts) / 3_600_000_000, 0)
		: pts[0].watts / 1000 * (5 / 60);
	return { avgW, peakW, kWh, cost: kWh * COST_PER_KWH, uptimePct };
}

function autoYDomain(data: Record<string, number | string>[], names: string[]): [number, number] | null {
	const vals = data.flatMap(pt => names.map(n => pt[n]).filter(v => typeof v === "number")) as number[];
	if (!vals.length) return null;
	const mn = Math.min(...vals), mx = Math.max(...vals);
	const pad = Math.max((mx - mn) * 0.08, 5);
	return [Math.max(0, mn - pad), mx + pad];
}

// ── Candle chart ─────────────────────────────────────────────────────────────

function CandleChart({ data, activeDevices, yDomain, onYDomainChange, onBrush }: {
	data: CandleBucket[];
	activeDevices: string[];
	yDomain: [number, number] | null;
	onYDomainChange: (d: [number, number]) => void;
	onBrush: (start: number, end: number) => void;
}) {
	const containerRef = useRef<HTMLDivElement>(null);
	const [width, setWidth] = useState(600);
	const [tooltip, setTooltip] = useState<{ x: number; y: number; bucket: CandleBucket } | null>(null);
	const [selecting, setSelecting] = useState<{ startPx: number; endPx: number } | null>(null);

	useEffect(() => {
		const el = containerRef.current;
		if (!el) return;
		const ro = new ResizeObserver(e => setWidth(e[0].contentRect.width));
		ro.observe(el);
		setWidth(el.getBoundingClientRect().width);
		return () => ro.disconnect();
	}, []);

	const H = 300, margin = { top: 10, right: 20, bottom: 28, left: 54 };
	const innerW = width - margin.left - margin.right;
	const innerH = H - margin.top - margin.bottom;

	// Y domain
	let yMin = Infinity, yMax = -Infinity;
	for (const pt of data) for (const n of activeDevices) {
		const c = pt[n] as Candle | undefined;
		if (c && typeof c === "object") { yMin = Math.min(yMin, c.low); yMax = Math.max(yMax, c.high); }
	}
	if (yMin === Infinity) { yMin = 0; yMax = 500; }
	const pad = Math.max((yMax - yMin) * 0.08, 5);
	const [effMin, effMax] = yDomain ?? [Math.max(0, yMin - pad), yMax + pad];
	const yScale = (v: number) => margin.top + innerH - ((v - effMin) / (effMax - effMin)) * innerH;
	const yFromPx = (py: number) => effMin + (1 - (py - margin.top) / innerH) * (effMax - effMin);

	const slotW = innerW / Math.max(data.length, 1);
	const candleW = Math.max(3, Math.min(18, slotW / activeDevices.length - 3));
	const xScale = (i: number) => margin.left + (i + 0.5) * slotW;
	const xToIdx = (px: number) => Math.max(0, Math.min(data.length - 1, Math.floor((px - margin.left) / slotW)));

	const yTicks = Array.from({ length: 5 }, (_, i) => effMin + (effMax - effMin) * i / 4);
	const xStep = Math.max(1, Math.floor(data.length / 6));

	// Scroll = Y zoom
	useEffect(() => {
		const el = containerRef.current;
		if (!el) return;
		const handler = (e: WheelEvent) => {
			e.preventDefault();
			const factor = e.deltaY > 0 ? 1.15 : 1 / 1.15;
			const py = e.clientY - el.getBoundingClientRect().top;
			const center = yFromPx(py);
			const half = (effMax - effMin) / 2 * factor;
			onYDomainChange([Math.max(0, center - half), center + half]);
		};
		el.addEventListener("wheel", handler, { passive: false });
		return () => el.removeEventListener("wheel", handler);
	}, [effMin, effMax]);

	// Mouse drag = X brush selection
	const svgRef = useRef<SVGSVGElement>(null);

	const onMouseDown = (e: React.MouseEvent<SVGSVGElement>) => {
		const rect = svgRef.current!.getBoundingClientRect();
		setSelecting({ startPx: e.clientX - rect.left, endPx: e.clientX - rect.left });
	};
	const onMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {
		if (!selecting) return;
		const rect = svgRef.current!.getBoundingClientRect();
		setSelecting(s => s ? { ...s, endPx: e.clientX - rect.left } : null);
		setTooltip(null);
	};
	const onMouseUp = () => {
		if (!selecting) return;
		const s = xToIdx(selecting.startPx), e = xToIdx(selecting.endPx);
		if (Math.abs(s - e) > 0) onBrush(Math.min(s, e), Math.max(s, e));
		setSelecting(null);
	};

	const selX1 = selecting ? Math.min(selecting.startPx, selecting.endPx) : 0;
	const selX2 = selecting ? Math.max(selecting.startPx, selecting.endPx) : 0;

	return (
		<div ref={containerRef} className="relative w-full select-none" style={{ height: H }}>
			<svg ref={svgRef} width={width} height={H}
				onMouseDown={onMouseDown} onMouseMove={onMouseMove} onMouseUp={onMouseUp}
				onDoubleClick={() => { onYDomainChange(null as any); onBrush(0, data.length - 1); }}
			>
				{/* Grid */}
				{yTicks.map((v, i) => (
					<g key={i}>
						<line x1={margin.left} y1={yScale(v)} x2={margin.left + innerW} y2={yScale(v)} stroke="currentColor" strokeOpacity={0.08} strokeDasharray="3 3" />
						<text x={margin.left - 6} y={yScale(v)} textAnchor="end" dominantBaseline="middle" fontSize={11} fill="currentColor" fillOpacity={0.4}>{Math.round(v)}W</text>
					</g>
				))}
				{data.map((pt, i) => i % xStep !== 0 && i !== data.length - 1 ? null : (
					<text key={i} x={xScale(i)} y={margin.top + innerH + 18} textAnchor="middle" fontSize={11} fill="currentColor" fillOpacity={0.4}>{pt.label}</text>
				))}

				{/* Candles */}
				{data.map((pt, i) => {
					const cx = xScale(i);
					return activeDevices.map((name, di) => {
						const c = pt[name] as Candle | undefined;
						if (!c || typeof c !== "object") return null;
						const off = activeDevices.length > 1 ? (di - (activeDevices.length - 1) / 2) * (candleW + 3) : 0;
						const x = cx + off;
						const isUp = c.close >= c.open;
						const color = isUp ? "#5dd776" : "#ef4444";
						const bodyTop = Math.min(yScale(c.open), yScale(c.close));
						const bodyH = Math.max(1, Math.abs(yScale(c.close) - yScale(c.open)));
						return (
							<g key={name}
								onMouseEnter={e => {
									const r = containerRef.current?.getBoundingClientRect();
									if (r) setTooltip({ x: e.clientX - r.left, y: e.clientY - r.top, bucket: pt });
								}}
								onMouseLeave={() => setTooltip(null)}
							>
								<line x1={x} y1={yScale(c.high)} x2={x} y2={yScale(c.low)} stroke={color} strokeWidth={1.5} />
								<rect x={x - candleW / 2} y={bodyTop} width={candleW} height={bodyH} fill={color} fillOpacity={0.85} />
								<rect x={cx - slotW / 2} y={margin.top} width={slotW} height={innerH} fill="transparent" />
							</g>
						);
					});
				})}

				{/* Drag selection overlay */}
				{selecting && selX2 - selX1 > 2 && (
					<rect x={selX1} y={margin.top} width={selX2 - selX1} height={innerH}
						fill="#428ce2" fillOpacity={0.15} stroke="#428ce2" strokeOpacity={0.5} strokeWidth={1} />
				)}
			</svg>

			{/* Hover tooltip */}
			{tooltip && !selecting && (
				<div className="pointer-events-none absolute z-10 bg-primary border border-secondary rounded-xl px-3 py-2 text-xs shadow-lg"
					style={{ left: Math.min(tooltip.x + 12, width - 160), top: Math.max(0, tooltip.y - 10) }}>
					<p className="text-foreground-sec mb-1.5">{tooltip.bucket.label}</p>
					{activeDevices.map(name => {
						const c = tooltip.bucket[name] as Candle | undefined;
						if (!c || typeof c !== "object") return null;
						return (
							<div key={name} className="flex flex-col gap-0.5 mb-1" style={{ color: DEVICE_COLORS[name] }}>
								<span className="font-medium capitalize">{name}</span>
								<span className="text-foreground-sec font-mono text-[10px]">
									O {c.open.toFixed(1)}  H {c.high.toFixed(1)}<br />
									L {c.low.toFixed(1)}  C {c.close.toFixed(1)} W
								</span>
							</div>
						);
					})}
				</div>
			)}
		</div>
	);
}

// ── Shared tooltip ────────────────────────────────────────────────────────────

const CustomTooltip = ({ active, payload, label }: any) => {
	if (!active || !payload?.length) return null;
	return (
		<div className="bg-primary border border-secondary rounded-xl px-3 py-2 text-xs shadow-lg">
			<p className="text-foreground-sec mb-1">{label}</p>
			{payload.map((p: any) => (
				<p key={p.name} style={{ color: p.color }} className="font-medium">
					{String(p.name).charAt(0).toUpperCase() + String(p.name).slice(1)}: {Number(p.value).toFixed(1)} W
				</p>
			))}
		</div>
	);
};

function SummaryCard({ label, value, sub, color }: { label: string; value: string; sub?: string; color?: string }) {
	return (
		<div className="bg-primary border border-secondary rounded-2xl p-5 flex flex-col gap-1">
			<span className="text-xs font-medium text-foreground-sec">{label}</span>
			<span className="text-2xl font-medium tracking-tight text-foreground leading-none mt-1" style={color ? { color } : undefined}>{value}</span>
			{sub && <span className="text-[0.7rem] text-foreground-sec mt-0.5">{sub}</span>}
		</div>
	);
}

// ── Page ──────────────────────────────────────────────────────────────────────

const PRESETS = [{ label: "6h", h: 6 }, { label: "24h", h: 24 }, { label: "7d", h: 168 }, { label: "30d", h: 720 }];

export default function AnalyticsPage() {
	// Time range
	const [presetH, setPresetH] = useState(24);
	const [showCustom, setShowCustom] = useState(false);
	const [customFrom, setCustomFrom] = useState(() => { const d = new Date(); d.setDate(d.getDate() - 1); return d.toISOString().slice(0, 16); });
	const [customTo, setCustomTo] = useState(() => new Date().toISOString().slice(0, 16));
	const [appliedRange, setAppliedRange] = useState<{ from: string; to: string } | null>(null);

	// Data
	const [readings, setReadings] = useState<HistoryEntry[]>([]);
	const [loading, setLoading] = useState(true);

	// Chart
	const [chartType, setChartType] = useState<ChartType>("line");
	const [activeDevices, setActiveDevices] = useState<Set<string>>(new Set());

	// Zoom
	const [yDomain, setYDomain] = useState<[number, number] | null>(null);
	const [brushIdx, setBrushIdx] = useState<[number, number] | null>(null); // [start, end] indices into flatData
	const [candleBrushIdx, setCandleBrushIdx] = useState<[number, number] | null>(null);
	const lineBarRef = useRef<HTMLDivElement>(null);
	const yDomainRef = useRef<[number, number] | null>(null);
	const visibleRef = useRef<Record<string, number | string>[]>([]);
	const activeListRef = useRef<string[]>([]);
	yDomainRef.current = yDomain;

	const effectiveSpanH = appliedRange
		? (new Date(appliedRange.to).getTime() - new Date(appliedRange.from).getTime()) / 3_600_000
		: presetH;

	const fetchHistory = useCallback(async () => {
		setLoading(true);
		try {
			let hoursToFetch = presetH;
			if (appliedRange) {
				hoursToFetch = Math.ceil((Date.now() - new Date(appliedRange.from).getTime()) / 3_600_000) + 1;
			}
			const res = await fetch(`/api/power/history?hours=${Math.min(hoursToFetch, 24 * 60)}`);
			if (!res.ok) return;
			let r: HistoryEntry[] = (await res.json()).readings ?? [];
			if (appliedRange) {
				const from = new Date(appliedRange.from).getTime();
				const to = new Date(appliedRange.to).getTime();
				r = r.filter(e => { const t = new Date(e.ts).getTime(); return t >= from && t <= to; });
			}
			setReadings(r);
			setBrushIdx(null);
			setCandleBrushIdx(null);
			setYDomain(null);
		} finally {
			setLoading(false);
		}
	}, [presetH, appliedRange]);

	useEffect(() => { fetchHistory(); }, [fetchHistory]);

	const deviceNames = Array.from(new Set(readings.flatMap(r => r.devices.map(d => d.name)))).sort();
	useEffect(() => {
		setActiveDevices(prev => prev.size > 0 ? prev : new Set(deviceNames));
	}, [deviceNames.join(",")]);

	const activeList = deviceNames.filter(n => activeDevices.has(n));
	activeListRef.current = activeList;

	// Flat data for line/bar
	const flatData = readings.map(r => {
		const pt: Record<string, number | string> = { ts: fmtTs(r.ts, effectiveSpanH) };
		for (const d of r.devices) if (activeDevices.has(d.name)) pt[d.name] = Number(d.watts.toFixed(1));
		return pt;
	});
	const visibleFlat = brushIdx ? flatData.slice(brushIdx[0], brushIdx[1] + 1) : flatData;
	visibleRef.current = visibleFlat;

	// Candle data
	const candleData = bucketCandles(readings, effectiveSpanH);
	const visibleCandle = candleBrushIdx ? candleData.slice(candleBrushIdx[0], candleBrushIdx[1] + 1) : candleData;

	// Y domain: scroll-zoomed > auto from visible data > recharts auto
	const effectiveYDomain = yDomain ?? autoYDomain(chartType === "candle" ? [] : visibleFlat, activeList);

	// Scroll Y zoom for line/bar
	useEffect(() => {
		const el = lineBarRef.current;
		if (!el) return;
		const handler = (e: WheelEvent) => {
			e.preventDefault();
			const [curMin, curMax] = yDomainRef.current ?? autoYDomain(visibleRef.current, activeListRef.current) ?? [0, 500];
			const factor = e.deltaY > 0 ? 1.15 : 1 / 1.15;
			const rect = el.getBoundingClientRect();
			const pct = 1 - (e.clientY - rect.top) / rect.height;
			const center = curMin + pct * (curMax - curMin);
			const half = (curMax - curMin) / 2 * factor;
			setYDomain([Math.max(0, center - half), center + half]);
		};
		el.addEventListener("wheel", handler, { passive: false });
		return () => el.removeEventListener("wheel", handler);
	}, []);

	const isZoomed = !!(yDomain || brushIdx || candleBrushIdx);
	const resetZoom = () => { setYDomain(null); setBrushIdx(null); setCandleBrushIdx(null); };

	const toggleDevice = (name: string) => {
		setActiveDevices(prev => {
			const next = new Set(prev);
			if (next.has(name)) { if (next.size > 1) next.delete(name); } else next.add(name);
			return next;
		});
	};

	const summaries = deviceNames.map(name => ({ name, summary: computeSummary(readings, name) }));
	const totalKWh = summaries.reduce((s, { summary }) => s + (summary?.kWh ?? 0), 0);

	const axisProps = { tick: { fontSize: 11, fill: "currentColor", fillOpacity: 0.4 } as any, tickLine: false, axisLine: false };

	// Double-click resets all zoom
	const onChartDblClick = () => resetZoom();

	return (
		<div className="w-full h-full bg-primary text-foreground overflow-hidden flex flex-row">
			<SideNav online={false} devConsoleOpen={false} onToggleDevConsole={() => {}} />

			<div className="flex-1 overflow-y-auto pt-[52px] lg:pt-0 lg:m-[10px_10px_10px_0px] lg:rounded-2xl lg:border lg:border-blue/20 min-w-0">
				<div className="max-w-5xl mx-auto px-3 pb-20 pt-8">

					{/* Header */}
					<div className="flex flex-wrap items-start justify-between gap-4 mb-8">
						<div>
							<h1 className="text-2xl font-semibold tracking-tight text-foreground">Power Analytics</h1>
							<p className="text-sm text-foreground-sec mt-1">
								{readings.length} readings · LADWP ${COST_PER_KWH}/kWh
								{appliedRange && <span> · {fmtDt(appliedRange.from)} – {fmtDt(appliedRange.to)}</span>}
							</p>
						</div>

						{/* Range picker */}
						<div className="flex flex-col gap-2 items-end">
							<div className="flex gap-1 bg-secondary/50 rounded-xl p-1">
								{PRESETS.map(({ label, h }) => (
									<button key={h} onClick={() => { setPresetH(h); setAppliedRange(null); setShowCustom(false); }}
										className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
											(!appliedRange && presetH === h ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
										{label}
									</button>
								))}
								<button onClick={() => setShowCustom(s => !s)}
									className={"px-3 py-1.5 rounded-lg text-xs font-medium transition-colors cursor-pointer " +
										(showCustom || appliedRange ? "bg-blue text-white" : "text-foreground-sec hover:text-foreground")}>
									Custom
								</button>
							</div>

							{/* Custom date range picker */}
							{showCustom && (
								<div className="flex flex-wrap items-center gap-2 bg-secondary/40 border border-secondary rounded-xl p-2.5 text-xs">
									<div className="flex items-center gap-1.5">
										<span className="text-foreground-sec">From</span>
										<input type="datetime-local" value={customFrom} onChange={e => setCustomFrom(e.target.value)}
											className="bg-secondary/60 border border-secondary rounded-lg px-2 py-1 text-foreground text-xs outline-none focus:border-blue/60" />
									</div>
									<div className="flex items-center gap-1.5">
										<span className="text-foreground-sec">To</span>
										<input type="datetime-local" value={customTo} onChange={e => setCustomTo(e.target.value)}
											className="bg-secondary/60 border border-secondary rounded-lg px-2 py-1 text-foreground text-xs outline-none focus:border-blue/60" />
									</div>
									<button
										onClick={() => { if (customFrom && customTo) { setAppliedRange({ from: customFrom, to: customTo }); setShowCustom(false); } }}
										className="px-3 py-1 bg-blue/10 border border-blue/30 text-blue rounded-lg font-medium hover:bg-blue/20 transition-colors cursor-pointer">
										Apply
									</button>
								</div>
							)}
						</div>
					</div>

					{/* Summary cards */}
					<div className="grid grid-cols-2 md:grid-cols-4 gap-3.5 mb-8">
						<SummaryCard label="Total energy" value={`${totalKWh.toFixed(3)} kWh`} sub={`≈ $${(totalKWh * COST_PER_KWH).toFixed(3)}`} />
						{summaries.map(({ name, summary }) => (
							<SummaryCard key={name} label={`${name[0].toUpperCase() + name.slice(1)} avg`}
								value={summary ? `${summary.avgW.toFixed(1)} W` : "—"}
								sub={summary ? `Peak ${summary.peakW.toFixed(1)} W` : undefined}
								color={DEVICE_COLORS[name]} />
						))}
						{summaries.map(({ name, summary }) => (
							<SummaryCard key={`${name}-u`} label={`${name[0].toUpperCase() + name.slice(1)} uptime`}
								value={summary ? `${summary.uptimePct.toFixed(0)}%` : "—"}
								sub={summary ? `${summary.kWh.toFixed(3)} kWh` : undefined} />
						))}
					</div>

					{/* Chart card */}
					<div className="bg-primary border border-secondary rounded-2xl p-5 mb-8">
						{/* Controls row */}
						<div className="flex flex-wrap items-center justify-between gap-3 mb-4">
							<div className="flex items-center gap-3 flex-wrap">
								<h2 className="text-sm font-medium text-foreground">Power over time</h2>
								{deviceNames.map(name => {
									const active = activeDevices.has(name);
									const color = DEVICE_COLORS[name] ?? "#888";
									return (
										<button key={name} onClick={() => toggleDevice(name)}
											className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium transition-all cursor-pointer border"
											style={{ borderColor: active ? color + "55" : "transparent", background: active ? color + "18" : "transparent", color: active ? color : "var(--color-foreground-sec)" }}>
											<span className="w-2 h-2 rounded-full" style={{ background: active ? color : "var(--color-secondary)" }} />
											<span className="capitalize">{name}</span>
										</button>
									);
								})}
							</div>
							<div className="flex items-center gap-2">
								{isZoomed && (
									<button onClick={resetZoom}
										className="flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-foreground-sec hover:text-foreground border border-secondary hover:border-secondary/80 transition-colors cursor-pointer">
										<IconRefresh size={11} />
										Reset zoom
									</button>
								)}
								<div className="flex gap-0.5 bg-secondary/50 rounded-lg p-0.5">
									{(["line", "bar", "candle"] as ChartType[]).map(type => (
										<button key={type} onClick={() => { setChartType(type); resetZoom(); }}
											className={"px-3 py-1 rounded-md text-xs font-medium transition-colors cursor-pointer capitalize " +
												(chartType === type ? "bg-primary text-foreground shadow-sm" : "text-foreground-sec hover:text-foreground")}>
											{type}
										</button>
									))}
								</div>
							</div>
						</div>

						<p className="text-[11px] text-foreground-sec/50 mb-3">
							{chartType === "candle" ? "Drag to zoom X · scroll to zoom Y · double-click to reset" : "Drag brush below chart to zoom X · scroll to zoom Y · double-click to reset"}
						</p>

						{/* Chart body */}
						{loading ? (
							<div className="skeleton h-[300px]" />
						) : readings.length === 0 ? (
							<div className="flex items-center justify-center h-[300px] text-foreground-sec text-sm">
								No data yet — readings are recorded every 5 minutes.
							</div>
						) : chartType === "candle" ? (
							<CandleChart
								data={visibleCandle}
								activeDevices={activeList}
								yDomain={yDomain}
								onYDomainChange={d => setYDomain(d)}
								onBrush={(s, e) => {
									const base = candleBrushIdx ? candleBrushIdx[0] : 0;
									setCandleBrushIdx([base + s, base + e]);
								}}
							/>
						) : (
							<div ref={lineBarRef} onDoubleClick={onChartDblClick}>
								<ResponsiveContainer width="100%" height={300}>
									{chartType === "bar" ? (
										<BarChart data={flatData} margin={CHART_MARGIN}>
											<CartesianGrid strokeDasharray="3 3" stroke="currentColor" strokeOpacity={0.08} />
											<XAxis dataKey="ts" {...axisProps} interval="preserveStartEnd" />
											<YAxis {...axisProps} domain={effectiveYDomain ?? ["auto", "auto"]} tickFormatter={v => `${v}W`} width={50} />
											<Tooltip content={<CustomTooltip />} />
											<Legend wrapperStyle={{ fontSize: 11, paddingTop: 8 }} formatter={v => String(v)[0].toUpperCase() + String(v).slice(1)} />
											{activeList.map(name => <Bar key={name} dataKey={name} fill={DEVICE_COLORS[name] ?? "#888"} fillOpacity={0.8} radius={[2, 2, 0, 0]} maxBarSize={16} />)}
											<Brush dataKey="ts" height={22} stroke="var(--color-secondary)" fill="var(--color-primary)" travellerWidth={6}
												onChange={({ startIndex, endIndex }) => {
													setBrushIdx([startIndex as number, endIndex as number]);
													setYDomain(null);
												}} />
										</BarChart>
									) : (
										<LineChart data={flatData} margin={CHART_MARGIN}>
											<CartesianGrid strokeDasharray="3 3" stroke="currentColor" strokeOpacity={0.08} />
											<XAxis dataKey="ts" {...axisProps} interval="preserveStartEnd" />
											<YAxis {...axisProps} domain={effectiveYDomain ?? ["auto", "auto"]} tickFormatter={v => `${v}W`} width={50} />
											<Tooltip content={<CustomTooltip />} />
											<Legend wrapperStyle={{ fontSize: 11, paddingTop: 8 }} formatter={v => String(v)[0].toUpperCase() + String(v).slice(1)} />
											{activeList.map(name => (
												<Line key={name} type="monotone" dataKey={name} stroke={DEVICE_COLORS[name] ?? "#888"} strokeWidth={1.5} dot={false} activeDot={{ r: 3 }} />
											))}
											<Brush dataKey="ts" height={22} stroke="var(--color-secondary)" fill="var(--color-primary)" travellerWidth={6}
												onChange={({ startIndex, endIndex }) => {
													setBrushIdx([startIndex as number, endIndex as number]);
													setYDomain(null);
												}} />
										</LineChart>
									)}
								</ResponsiveContainer>
							</div>
						)}
					</div>

					{/* Device breakdown */}
					{summaries.length > 0 && (
						<>
							<h2 className="text-lg font-medium tracking-tight text-foreground mb-5">Device breakdown</h2>
							<div className="grid grid-cols-1 md:grid-cols-2 gap-3.5">
								{summaries.map(({ name, summary }) => {
									if (!summary) return null;
									const color = DEVICE_COLORS[name] ?? "#888";
									return (
										<div key={name} className="bg-primary border border-secondary rounded-2xl p-5">
											<div className="flex items-center gap-2 mb-4">
												<span className="w-2.5 h-2.5 rounded-full" style={{ background: color }} />
												<h3 className="text-sm font-medium text-foreground capitalize">{name}</h3>
											</div>
											<div className="grid grid-cols-3 gap-4">
												{[
													{ label: "Average", value: `${summary.avgW.toFixed(1)} W` },
													{ label: "Peak", value: `${summary.peakW.toFixed(1)} W` },
													{ label: "Uptime", value: `${summary.uptimePct.toFixed(1)}%` },
													{ label: "Energy", value: `${summary.kWh.toFixed(3)} kWh` },
													{ label: "Est. cost", value: `$${summary.cost.toFixed(3)}` },
													{ label: "Readings", value: String(readings.filter(r => r.devices.some(d => d.name === name)).length) },
												].map(({ label, value }) => (
													<div key={label} className="flex flex-col gap-0.5">
														<span className="text-xs text-foreground-sec">{label}</span>
														<span className="text-sm font-medium text-foreground">{value}</span>
													</div>
												))}
											</div>
										</div>
									);
								})}
							</div>
						</>
					)}
				</div>
			</div>
		</div>
	);
}
