/* R3T Monitor — single-device (detail view) components */
const { useState, useEffect, useRef, useMemo } = React;

/* ---------- formatting helpers ---------- */
const MON = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
function parse(iso){ return new Date(iso.replace(" ", "T")); }
function fmtClock(iso){ const d = parse(iso); return String(d.getHours()).padStart(2,"0")+":"+String(d.getMinutes()).padStart(2,"0"); }
function fmtDay(iso){ const d = parse(iso); return `${String(d.getDate()).padStart(2,"0")} ${MON[d.getMonth()]}`; }
function fmtMonth(iso){ const d = parse(iso); return `${MON[d.getMonth()]} ${d.getFullYear()}`; }
function fmtLong(iso){ const d = parse(iso); return `${fmtDay(iso)} ${d.getFullYear()}, ${fmtClock(iso)} WIB`; }
function relTime(iso, nowIso){
  const diff = Math.max(0, Math.round((parse(nowIso) - parse(iso))/60000));
  if(diff < 1) return "just now";
  if(diff < 60) return `${diff} min ago`;
  const h = Math.floor(diff/60), m = diff%60; return m ? `${h}h ${m}m ago` : `${h} hr ago`;
}
function bars(signal){
  if(signal >= 75) return 4; if(signal >= 55) return 3; if(signal >= 35) return 2; if(signal >= 15) return 1; return 0;
}

function SigBars({ n }){
  const hs = [6,9,12,15];
  return (<span className="sig-mini">{hs.map((h,i)=> <i key={i} className={i < n ? "lit" : ""} style={{height:h}}/>)}</span>);
}

/* period helpers */
function baseFor(device, period){ return period==="year" ? device.year : period==="month" ? device.month : device.today; }

/* ---------- detail header (back + device identity + status + period switch) ---------- */
function DeviceHeader({ device, now, showLive, period, setPeriod, onBack }){
  const live = device.today[0];
  const sig = live.signal;
  const online = device.status === "online";
  return (
    <div className="detail-head">
      <div className="detail-top">
        <button className="back-btn" onClick={onBack}><span className="chev">‹</span> All devices</button>
        <div className="seg period-seg">
          <button className={period === "today" ? "on" : ""} onClick={() => setPeriod("today")}>Today</button>
          <button className={period === "month" ? "on" : ""} onClick={() => setPeriod("month")} data-comment-anchor="831debba11-button-37-11">Last 30 Days</button>
          <button className={period === "year" ? "on" : ""} onClick={() => setPeriod("year")}>12 Months</button>
        </div>
      </div>
      <header className="topbar">
        <div className="brand">
          <div className="logo dev"><span>{String(device.id).padStart(2, "0")}</span></div>
          <div>
            <div className="brand-name">{device.name}
              <span className={"status-dot " + (online ? "on" : "off")}></span>
              <span className="status-txt">{online ? "Online" : "Offline"}</span>
            </div>
            <div className="brand-sub">
              <span>SN {device.serial}</span><i className="dot"></i><span>{device.user}</span>
            </div>
          </div>
        </div>
        <div className="head-right">
          <div className="updated">
            {showLive && online && <span className="live-dot"></span>}
            <span>Last seen&nbsp; <b>{fmtLong(live.time)}</b></span>
            {showLive && <span className="rel">· {relTime(live.time, now)}</span>}
          </div>
          <div className="chips">
            <div className="chip">
              <span style={{ color: "var(--text-3)" }}><BatteryIcon style={{ width: 16, height: 16 }} /></span>
              <div className="stack"><span className="lab">Battery</span><span className="val">{live.battery.toFixed(2)} V</span></div>
            </div>
            <div className="chip">
              <div className="stack">
                <span className="lab">Signal</span>
                <span className="val" style={{ display: "flex", alignItems: "center" }} data-comment-anchor="6a73a4e74f-span-75-17"><SigBars n={bars(sig)} /></span>
              </div>
            </div>
          </div>
        </div>
      </header>
    </div>);
}

/* ---------- metric cards ---------- */
function MetricCard({ hero, icon, label, value, unit, foot, trend }){
  return (
    <div className={"card metric" + (hero ? " hero" : "")}>
      {hero && <div className="grid-tex"></div>}
      <div className="m-top">
        <span className="m-label">{label}</span>
        <span className="m-ico">{icon}</span>
      </div>
      <div className="m-value"><span className="num">{value}</span><span className="unit">{unit}</span></div>
      <div className="m-foot">{trend}{foot}</div>
    </div>);
}

/* aggregate raw readings (daily counter resets each day) into per-day / per-month usage */
function perDayUsage(history){
  const m = new Map();
  for(const r of history){ const day = r.time.slice(0,10); m.set(day, Math.max(m.get(day)||0, r.daily)); }
  return [...m.values()];
}
function perMonthUsage(history){
  const day = new Map();
  for(const r of history){ const d = r.time.slice(0,10); day.set(d, Math.max(day.get(d)||0, r.daily)); }
  const mon = new Map();
  for(const [d,u] of day){ const ym = d.slice(0,7); mon.set(ym, (mon.get(ym)||0)+u); }
  return [...mon.values()];
}
const mean = (a)=> a.length ? a.reduce((s,v)=>s+v,0)/a.length : 0;

function Metrics({ latest, history, period }){
  if(period === "year"){
    const months = perMonthUsage(history);
    const peak = months.length ? Math.max(...months) : 0;
    return (
      <div className="metrics">
        <MetricCard hero label="12-Month Usage" icon={<GaugeIcon style={{width:20,height:20}}/>}
          value={latest.total.toFixed(2)} unit="m³"
          trend={<span className="trend up">{months.length} mo</span>} foot="cumulative this period" />
        <MetricCard label="Avg per Month" icon={<CalendarIcon style={{width:20,height:20}}/>}
          value={mean(months).toFixed(2)} unit="m³"
          trend={<span className="trend flat">peak {peak.toFixed(2)}</span>} foot="monthly average" />
      </div>);
  }
  if(period === "month"){
    const days = perDayUsage(history);
    const peak = days.length ? Math.max(...days) : 0;
    return (
      <div className="metrics">
        <MetricCard hero label="30-Day Usage" icon={<GaugeIcon style={{width:20,height:20}}/>}
          value={latest.total.toFixed(2)} unit="m³"
          trend={<span className="trend up">{days.length} days</span>} foot="cumulative this period" />
        <MetricCard label="Avg per Day" icon={<CalendarIcon style={{width:20,height:20}}/>}
          value={mean(days).toFixed(2)} unit="m³"
          trend={<span className="trend flat">peak {peak.toFixed(2)}</span>} foot="daily average" />
      </div>);
  }
  const prev = history[1] || latest;
  const dTotal = +(latest.total - prev.total).toFixed(2);
  return (
    <div className="metrics">
      <MetricCard hero label="Total Usage" icon={<GaugeIcon style={{width:20,height:20}}/>}
        value={latest.total.toFixed(2)} unit="m³"
        trend={<span className={"trend " + (dTotal>0?"up":"flat")}>{dTotal>0?`+${dTotal.toFixed(2)}`:"±0.00"}</span>}
        foot="since previous reading" />
      <MetricCard label="Daily Usage" icon={<CalendarIcon style={{width:20,height:20}}/>}
        value={latest.daily.toFixed(2)} unit="m³"
        trend={<span className="trend flat">today</span>} foot={`${fmtDay(latest.time)} ${parse(latest.time).getFullYear()}`} />
    </div>);
}

/* ---------- main chart (cumulative) ---------- */
function MainChart({ history, chartStyle, period, themeKey }){
  const canvasRef = useRef(null);
  const chartRef = useRef(null);
  const isMonth = period === "month";
  const isYear = period === "year";

  const chrono = useMemo(()=> history.slice().reverse(), [history]);
  const series = useMemo(()=> chrono.map(r => ({ x: parse(r.time).valueOf(), y: r.total })), [chrono]);

  useEffect(()=>{
    if(!canvasRef.current || !window.Chart) return;
    const css = getComputedStyle(document.body);
    const accent = css.getPropertyValue("--accent").trim() || "#2563eb";
    const grid = css.getPropertyValue("--border").trim();
    const tickCol = css.getPropertyValue("--text-3").trim();
    const ctx = canvasRef.current.getContext("2d");

    const grad = ctx.createLinearGradient(0,0,0,280);
    grad.addColorStop(0, accent + "59");
    grad.addColorStop(1, accent + "00");

    const isBar = chartStyle === "bars";
    const fill = chartStyle === "area";
    const ys = series.map(p => p.y);
    const min = Math.min(...ys), max = Math.max(...ys);
    const padY = Math.max(0.02, (max - min) * 0.18);
    const timeCfg = isYear
      ? { unit:"month", stepSize:1, displayFormats:{ month:"MMM" }, tooltipFormat:"MMM yyyy" }
      : isMonth
      ? { unit:"day", stepSize:5, displayFormats:{ day:"d MMM" }, tooltipFormat:"d MMM" }
      : { unit:"minute", stepSize:15, displayFormats:{ minute:"HH:mm" }, tooltipFormat:"HH:mm" };
    const decim = 2;

    if(chartRef.current) chartRef.current.destroy();
    chartRef.current = new window.Chart(ctx, {
      type: isBar ? "bar" : "line",
      data: { datasets: [{
        label: "Total", data: series,
        borderColor: accent,
        backgroundColor: isBar ? accent : grad,
        borderWidth: isBar ? 0 : 2.4,
        borderRadius: isBar ? 5 : 0,
        maxBarThickness: isYear ? 24 : isMonth ? 16 : 34,
        fill, tension: 0.42,
        pointRadius: isBar ? 0 : (isYear ? 1.5 : period==="today" ? 3 : 2),
        pointHoverRadius: isBar ? 0 : 6,
        pointBackgroundColor: accent,
        pointBorderColor: css.getPropertyValue("--surface").trim(),
        pointBorderWidth: 2,
      }]},
      options: {
        responsive: true, maintainAspectRatio: false,
        animation: { duration: 600, easing: "easeOutCubic" },
        interaction: { mode: "index", intersect: false },
        layout: { padding: { top: 6 } },
        plugins: {
          legend: { display: false },
          tooltip: {
            backgroundColor: css.getPropertyValue("--text").trim(),
            titleColor: css.getPropertyValue("--surface").trim(),
            bodyColor: css.getPropertyValue("--surface").trim(),
            padding: 11, cornerRadius: 9, displayColors: false,
            titleFont: { family: "'IBM Plex Mono', monospace", size: 11, weight: "600" },
            bodyFont: { family: "'IBM Plex Sans', sans-serif", size: 13, weight: "600" },
            callbacks: {
              title: (it)=> {
                const d = new Date(it[0].parsed.x);
                const hm = String(d.getHours()).padStart(2,"0")+":"+String(d.getMinutes()).padStart(2,"0");
                if(period==="today") return hm+" WIB";
                return `${String(d.getDate()).padStart(2,"0")} ${MON[d.getMonth()]} ${d.getFullYear()}, ${hm}`;
              },
              label: (it)=> `${it.parsed.y.toFixed(decim)} m³`,
            }
          }
        },
        scales: {
          x: { type: "time", time: timeCfg, bounds: "data", offset: isBar,
               grid: { display: false }, border: { color: grid },
               ticks: { color: tickCol, font: { family: "'IBM Plex Mono', monospace", size: 11 },
                        maxRotation: 0, autoSkip: true, maxTicksLimit: isYear ? 12 : isMonth ? 7 : 8 } },
          y: { grid: { color: grid, drawTicks: false }, border: { display: false },
               suggestedMin: +(min - padY).toFixed(3),
               suggestedMax: +(max + padY).toFixed(3),
               ticks: { color: tickCol, font: { family: "'IBM Plex Mono', monospace", size: 11 },
                        padding: 8, callback: (v)=> v.toFixed(decim) } }
        }
      }
    });
    const paint = ()=>{ const ch = chartRef.current; if(!ch) return;
      try{ ch.resize(); ch.update("none"); ch.draw(); }catch(e){} };
    const raf1 = requestAnimationFrame(paint);
    const t1 = setTimeout(paint, 120);
    if(document.fonts && document.fonts.ready){ document.fonts.ready.then(paint); }
    return ()=>{ cancelAnimationFrame(raf1); clearTimeout(t1);
      if(chartRef.current){ chartRef.current.destroy(); chartRef.current = null; } };
  }, [series, chartStyle, isMonth, isYear, period, themeKey]);

  const rangeTxt = isYear
    ? `${fmtMonth(chrono[0].time)} – ${fmtMonth(chrono[chrono.length-1].time)}`
    : isMonth
    ? `${fmtDay(chrono[0].time)} – ${fmtDay(chrono[chrono.length-1].time)}`
    : `${fmtClock(chrono[0].time)}–${fmtClock(chrono[chrono.length-1].time)} WIB`;
  const subTitle = period==="today" ? "total over time" : isMonth ? "cumulative · 30 days" : "cumulative · 12 months";

  return (
    <div className="card panel">
      <div className="panel-head">
        <div className="panel-title">Usage Trend <span className="muted">· {subTitle}</span></div>
      </div>
      <div className="chart-meta">
        <div className="legend-item"><span className="legend-swatch"></span>Cumulative total (m³)</div>
        <div className="legend-item" style={{ color: "var(--text-3)" }}>
          <ClockIcon style={{ width: 14, height: 14 }} /> {rangeTxt}</div>
      </div>
      <div className="chart-box"><canvas ref={canvasRef}></canvas></div>
    </div>);
}

/* ---------- readings table ---------- */
function ReadingsTable({ history, period }){
  const isMonth = period === "month";
  const isYear = period === "year";
  // every reading with its timestamp, newest first (cap the DOM; the chart still plots all)
  const rows = history.slice(0, 500);
  const count = isYear ? `${history.length} readings · 12 mo`
              : isMonth ? `${history.length} readings · 30 days`
              : `${history.length} latest`;
  return (
    <div className="card panel">
      <div className="panel-head" style={{ marginBottom: 14 }}>
        <div className="panel-title">Reading History <span className="muted">· {count}</span></div>
      </div>
      <div className="tbl-wrap">
        <table className="readings slim">
          <thead><tr><th>Date · Time</th><th>Total</th><th>Daily</th></tr></thead>
          <tbody>
            {rows.map((r,i)=>(
              <tr key={r.time} className={i===0?"latest":""}>
                <td className="time">{fmtDay(r.time)} · {fmtClock(r.time)}{i===0 && <span className="new">Latest</span>}</td>
                <td>{r.total.toFixed(2)}</td>
                <td>{r.daily.toFixed(2)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>);
}

Object.assign(window, { DeviceHeader, Metrics, MainChart, ReadingsTable, SigBars, bars, parse, fmtClock, fmtDay, fmtMonth, fmtLong, relTime, baseFor });
