/* global React */
const { useState, useEffect, useMemo } = React;

// ---------- Mock data ----------
const ROOMS = [
  {
    id: "A", name: "Hall A", sub: "Compute · 24 racks",
    status: "ok",
    powerKw: 86.4, powerCapKw: 160, powerThresholdKw: 128,
    uUsed: 412, uTotal: 1008,
    tempCold: 19.4, tempHot: 26.8,
    racks: { ok: 22, warn: 2, crit: 0 },
    sbyk: [78, 80, 82, 81, 84, 85, 83, 84, 86, 88, 87, 86, 85, 86, 87, 86.4],
  },
  {
    id: "B", name: "Hall B", sub: "Compute + Storage · 32 racks",
    status: "warn",
    powerKw: 142.8, powerCapKw: 200, powerThresholdKw: 160,
    uUsed: 1024, uTotal: 1344,
    tempCold: 20.1, tempHot: 30.4,
    racks: { ok: 25, warn: 5, crit: 2 },
    sbyk: [120, 122, 125, 130, 132, 138, 142, 144, 146, 144, 140, 141, 143, 144, 145, 142.8],
  },
  {
    id: "C", name: "Hall C", sub: "Edge / GPU · 12 racks",
    status: "ok",
    powerKw: 64.2, powerCapKw: 120, powerThresholdKw: 96,
    uUsed: 318, uTotal: 504,
    tempCold: 19.2, tempHot: 25.1,
    racks: { ok: 12, warn: 0, crit: 0 },
    sbyk: [58, 60, 61, 62, 64, 63, 65, 66, 64, 63, 62, 64, 65, 66, 65, 64.2],
  },
  {
    id: "D", name: "Hall D", sub: "Network + colo · 18 racks",
    status: "warn",
    powerKw: 78.1, powerCapKw: 100, powerThresholdKw: 80,
    uUsed: 612, uTotal: 756,
    tempCold: 20.8, tempHot: 28.6,
    racks: { ok: 15, warn: 3, crit: 0 },
    sbyk: [72, 73, 74, 76, 75, 77, 78, 79, 78, 77, 78, 79, 78, 77, 78, 78.1],
  },
];

const ALERTS_LIVE = [
  { id: "AL-2041", sev: "crit", msg: "Load PDU > 90% (5920W / 6400W)", src: "pdu-d03-a · titan-33 · Hall B", at: "14:31", ago: "4 min" },
  { id: "AL-2040", sev: "crit", msg: "Temperature sortie d'aisle > 30°C", src: "thermo-r-d03 · titan-33 · Hall B", at: "14:23", ago: "12 min" },
  { id: "AL-2039", sev: "warn", msg: "Load PDU > 85% pendant 15 min", src: "pdu-b03-a · mars-05 · Hall B", at: "14:13", ago: "22 min" },
  { id: "AL-2038", sev: "warn", msg: "Unbalanced load A/B > 100W", src: "mercury-15 · Hall A", at: "13:54", ago: "41 min" },
  { id: "AL-2037", sev: "warn", msg: "SNMP timeout intermittent", src: "pdu-a05-a · mercury-15 · Hall A", at: "14:21", ago: "14 min" },
  { id: "AL-2034", sev: "crit", msg: "Loss redondance alim (PSU2 KO)", src: "srv-lyon-db-01 · titan-33", at: "13:33", ago: "1h 02" },
];

const TICKETS_TODAY = {
  open: 14, inProgress: 6, doneToday: 8,
  // 7 derniers jours : [opened, closed]
  bars: [[5, 4], [7, 6], [4, 5], [9, 7], [6, 8], [5, 4], [8, 8]],
  days: ["L", "M", "M", "J", "V", "S", "D"],
  top: [
    { id: 2841, title: "Rslot PSU2 — srv-lyon-db-01", pri: "high", progress: 50, room: "B" },
    { id: 2837, title: "Verify unbalanced load PDU titan-31", pri: "high", progress: 0, room: "D" },
    { id: 2839, title: "Decom 4 servers HPE en mercury-13", pri: "normal", progress: 62, room: "A" },
  ],
};

const TICKER_EVENTS = [
  { t: "14:31", sev: "crit", text: "AL-2041 opene · pdu-d03-a load 5920W/6400W" },
  { t: "14:28", sev: "ok",   text: "TIC-2838 closed · cabling fibre mars-07" },
  { t: "14:23", sev: "crit", text: "AL-2040 opene · temperature hot aisle titan-33 = 31.2°C" },
  { t: "14:21", sev: "warn", text: "AL-2037 flap · SNMP timeout pdu-a05-a" },
  { t: "14:18", sev: "ok",   text: "Backup quotidien completed · 2.4 TB · duration 1h12" },
  { t: "14:13", sev: "warn", text: "AL-2039 opene · pdu-b03-a load > 85%" },
  { t: "14:08", sev: "info", text: "TIC-2841 step 2/4 validatede · srv-lyon-db-01 identified" },
  { t: "13:54", sev: "warn", text: "AL-2038 opene · unbalanced A/B > 100W mercury-15" },
  { t: "13:42", sev: "info", text: "TIC-2841 step 1/4 · byt sortie du stock" },
  { t: "13:33", sev: "crit", text: "AL-2034 opene · PSU2 KO sur srv-lyon-db-01" },
];

// ---------- Helpers ----------
const fmt2 = (n) => n.toFixed(1);
const ratioColor = (r) => {
  if (r < 0.55) return "var(--noc-ok)";
  if (r < 0.75) return "oklch(0.78 0.15 95)";
  if (r < 0.9) return "var(--noc-warn)";
  return "var(--noc-crit)";
};

// ---------- Sbykline ----------
function Sbyk({ data, color, height = 30 }) {
  const max = Math.max(...data);
  const min = Math.min(...data);
  const range = max - min || 1;
  const w = 200;
  const pts = data.map((v, i) => `${(i / (data.length - 1)) * w},${height - ((v - min) / range) * (height - 4) - 2}`).join(" ");
  const areaPts = `0,${height} ${pts} ${w},${height}`;
  return (
    <svg width="100%" height={height} viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none">
      <polygon points={areaPts} fill={color} fillOpacity="0.18"/>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round"/>
    </svg>
  );
}

// ---------- Header ----------
function Header() {
  const [now, setNow] = useState(new Date());
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(t);
  }, []);
  const pad = (n) => String(n).padStart(2, "0");
  const time = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
  const dateStr = now.toLocaleDateString("fr-FR", { weekday: "long", day: "numeric", month: "long", year: "numeric" });

  return (
    <header className="noc-head">
      <div className="noc-brand">
        <div className="noc-mark">
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <rect x="3" y="3" width="7" height="18" rx="1"/>
            <rect x="14" y="3" width="7" height="18" rx="1"/>
            <path d="M5 7h3M5 11h3M5 15h3M16 7h3M16 11h3M16 15h3"/>
          </svg>
        </div>
        <div className="noc-site">
          <div className="noc-site-name">DC mars-7 · NOC Wallboard</div>
          <div className="noc-site-sub">Site primaire · Tier III · 720 m² · 7 halls techniques</div>
        </div>
      </div>

      <div className="noc-status-master warn">
        <span className="pulse"/>
        <span>Operation · vigilance Hall B</span>
      </div>

      <div className="noc-head-right">
        <div className="noc-weather">
          <div className="temp">14°</div>
          <div className="wm">
            <div className="lbl">Exterior</div>
            <div className="val">Copen · 8 km/h</div>
          </div>
        </div>
        <div className="noc-meta-block">
          <div className="k">Oncall</div>
          <div className="v"><b>M. Cooper</b> · L. Wright</div>
        </div>
        <div>
          <div className="noc-clock">{time}</div>
          <div className="noc-clock-sub">{dateStr}</div>
        </div>
      </div>
    </header>
  );
}

// ---------- KPI XL ----------
function KpiXL({ kind, label, value, unit, sub, trend, trendKind, sbykColor, sbykData, live }) {
  return (
    <div className={`noc-kpi ${kind}`}>
      <div className="noc-kpi-label">
        <span>{label}</span>
        {live && <span className="live">LIVE</span>}
      </div>
      <div className="noc-kpi-val">{value}{unit && <span className="unit">{unit}</span>}</div>
      {sbykData && (
        <div className="noc-kpi-sbyk">
          <Sbyk data={sbykData} color={sbykColor || "var(--noc-accent)"} height={36}/>
        </div>
      )}
      <div className="noc-kpi-row">
        <div className="noc-kpi-sub">{sub}</div>
        {trend && <div className={`noc-kpi-trend ${trendKind}`}>{trend}</div>}
      </div>
    </div>
  );
}

function Kpis() {
  const totalPower = ROOMS.reduce((s, r) => s + r.powerKw, 0);
  const totalCap   = ROOMS.reduce((s, r) => s + r.powerCapKw, 0);
  const uUsed = ROOMS.reduce((s, r) => s + r.uUsed, 0);
  const uTot  = ROOMS.reduce((s, r) => s + r.uTotal, 0);
  const uFreePct = ((uTot - uUsed) / uTot * 100);
  const critN = ALERTS_LIVE.filter(a => a.sev === "crit").length;
  const warnN = ALERTS_LIVE.filter(a => a.sev === "warn").length;
  const tk = TICKETS_TODAY;

  return (
    <div className="noc-kpis">
      <KpiXL
        kind="ok"
        label="PUE 24h"
        value="1.42"
        sub="goal < 1.45 · Tier III"
        trend="▼ -0.03"
        trendKind="down-good"
        sbykData={[1.48, 1.46, 1.47, 1.45, 1.44, 1.46, 1.45, 1.44, 1.43, 1.42, 1.43, 1.42]}
        sbykColor="var(--noc-ok)"
        live
      />
      <KpiXL
        kind="info"
        label="Draw. totale"
        value={fmt2(totalPower)}
        unit="kW"
        sub={<><b>{((totalPower / totalCap) * 100).toFixed(0)}%</b> capacity · {totalCap} kW max</>}
        trend="▲ +4.2 kW"
        trendKind="up-bad"
        sbykData={[340, 348, 352, 358, 362, 365, 368, 370, 369, 372, 371, totalPower]}
        sbykColor="var(--noc-info)"
        live
      />
      <KpiXL
        kind="accent"
        label="Capacity U dispo"
        value={(uTot - uUsed)}
        unit="U"
        sub={<><b>{uFreePct.toFixed(0)}%</b> free · {uTot} U total</>}
        trend="▼ -8 U / 30j"
        trendKind="down-bad"
      />
      <KpiXL
        kind="warn"
        label="Open tickets"
        value={tk.open + tk.inProgress}
        sub={<>en cours <b>{tk.inProgress}</b> · resolved aujourd'hui <b>{tk.doneToday}</b></>}
        trend="▲ +2"
        trendKind="up-bad"
      />
      <KpiXL
        kind="crit"
        label="Active alerts"
        value={critN + warnN}
        sub={<>criticals <b style={{color: "var(--noc-crit)"}}>{critN}</b> · warnings <b style={{color: "var(--noc-warn)"}}>{warnN}</b> · MTTA 4 min</>}
        trend="▲ +3"
        trendKind="up-bad"
        live
      />
    </div>
  );
}

// ---------- Rooms card ----------
function RoomsCard() {
  return (
    <div className="noc-card noc-rooms">
      <div className="noc-card-head">
        <div className="noc-card-title">Rooms · load / capacity / temperature</div>
        <div className="noc-card-meta">refresh · <b>10s</b></div>
      </div>
      <div className="noc-rooms-grid">
        {ROOMS.map(r => {
          const pRatio = r.powerKw / r.powerCapKw;
          const uRatio = r.uUsed / r.uTotal;
          const pColor = ratioColor(pRatio);
          const uColor = ratioColor(uRatio);
          const tempCrit = r.tempHot > 30;
          const tempWarn = r.tempHot > 28;
          return (
            <div key={r.id} className={`noc-room ${r.status}`}>
              <div className="noc-room-id">
                <div className="noc-room-name">{r.name}</div>
                <div className="noc-room-sub">{r.sub}</div>
                <div className={`noc-room-status ${r.status}`}>
                  <span className="d"/>
                  {r.status === "ok" ? "Nameinal" : r.status === "warn" ? "Vigilance" : "Critical"}
                </div>
              </div>

              <div className="noc-gauges">
                <div className="noc-gauge">
                  <div className="noc-gauge-head">
                    <span className="lbl">Load energy</span>
                    <span className="val">{fmt2(r.powerKw)}<span className="u">/ {r.powerCapKw} kW</span></span>
                  </div>
                  <div className="noc-gauge-bar">
                    <div className="fill" style={{ width: `${pRatio * 100}%`, background: pColor }}/>
                    <div className="threshold" style={{ left: `${(r.powerThresholdKw / r.powerCapKw) * 100}%` }}/>
                  </div>
                </div>
                <div className="noc-gauge">
                  <div className="noc-gauge-head">
                    <span className="lbl">Occupation U</span>
                    <span className="val">{r.uUsed}<span className="u">/ {r.uTotal} U</span></span>
                  </div>
                  <div className="noc-gauge-bar">
                    <div className="fill" style={{ width: `${uRatio * 100}%`, background: uColor }}/>
                  </div>
                </div>
                <div className="noc-sbyk">
                  <Sbyk data={r.sbyk} color={pColor} height={26}/>
                </div>
              </div>

              <div className="noc-room-side">
                <div className="noc-room-stat">
                  <div className="k">Cold aisle</div>
                  <div className="v">{fmt2(r.tempCold)}<span className="u">°C</span></div>
                </div>
                <div className={`noc-room-stat ${tempCrit ? "crit" : tempWarn ? "warn" : ""}`}>
                  <div className="k">Hot aisle</div>
                  <div className="v">{fmt2(r.tempHot)}<span className="u">°C</span></div>
                </div>
                <div className="noc-room-stat">
                  <div className="k">Racks OK</div>
                  <div className="v" style={{color: "var(--noc-ok)"}}>{r.racks.ok}</div>
                </div>
                <div className={`noc-room-stat ${r.racks.crit ? "crit" : r.racks.warn ? "warn" : ""}`}>
                  <div className="k">Racks alert</div>
                  <div className="v">{r.racks.warn + r.racks.crit}</div>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ---------- Tickets card ----------
function TicketsCard() {
  const tk = TICKETS_TODAY;
  const max = Math.max(...tk.bars.flat());
  return (
    <div className="noc-card noc-tickets">
      <div className="noc-card-head">
        <div className="noc-card-title">Tickets · 7 jours</div>
        <div className="noc-card-meta">SLA met · <b>96%</b></div>
      </div>
      <div className="noc-tk-summary">
        <div className="item open">
          <div className="k">Opens</div>
          <div className="v">{tk.open}</div>
        </div>
        <div className="item">
          <div className="k">In progress</div>
          <div className="v">{tk.inProgress}</div>
        </div>
        <div className="item done">
          <div className="k">Faits aujourd'hui</div>
          <div className="v">{tk.doneToday}</div>
        </div>
      </div>

      <div className="noc-tk-bars">
        {tk.bars.map(([o, c], i) => (
          <div key={i} className={`noc-tk-bar ${i === tk.bars.length - 1 ? "today" : ""}`}>
            <span className="opened" style={{ height: `${(o / max) * 70}%` }} title={`${o} opens`}/>
            <span className="closed" style={{ height: `${(c / max) * 70}%` }} title={`${c} closeds`}/>
            <span className="day">{tk.days[i]}</span>
          </div>
        ))}
      </div>
      <div style={{display: "flex", gap: 14, fontSize: 10, fontFamily: "var(--mono)", color: "var(--noc-dim)", marginTop: 22}}>
        <span><span style={{display: "inline-block", width: 8, height: 8, background: "var(--noc-warn)", marginRight: 6, borderRadius: 1}}/>OUVERTS</span>
        <span><span style={{display: "inline-block", width: 8, height: 8, background: "var(--noc-ok)", marginRight: 6, borderRadius: 1}}/>FERMÉS</span>
      </div>

      <div className="noc-tk-list">
        {tk.top.map(t => (
          <div key={t.id} className={`noc-tk-item ${t.pri}`}>
            <div className="pri"/>
            <div style={{minWidth: 0}}>
              <div className="noc-tk-item-title">{t.title}</div>
              <div className="noc-tk-item-meta">Hall {t.room} · {t.progress}% · due aujourd'hui</div>
              <div className="noc-tk-item-progress"><div style={{width: `${t.progress}%`}}/></div>
            </div>
            <div className="noc-tk-item-id">#{t.id}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- Alerts card ----------
function AlertsCard() {
  return (
    <div className="noc-card noc-alerts">
      <div className="noc-card-head">
        <div className="noc-card-title">Alerts · live feed</div>
        <div className="noc-card-meta">stream · <b style={{color: "var(--noc-ok)"}}>● active</b></div>
      </div>
      <div className="noc-alerts-list">
        {ALERTS_LIVE.slice(0, 6).map(a => (
          <div key={a.id} className={`noc-alert ${a.sev}`}>
            <div className={`noc-alert-sev ${a.sev}`}>{a.sev === "crit" ? "CRIT" : a.sev === "warn" ? "WARN" : "INFO"}</div>
            <div style={{minWidth: 0}}>
              <div className="noc-alert-msg">{a.msg}</div>
              <div className="noc-alert-meta">{a.id} · {a.src}</div>
            </div>
            <div className="noc-alert-time">
              <div className="t">{a.at}</div>
              <div>{a.ago}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- Power & cooling ----------
function PowerCard() {
  return (
    <div className="noc-card noc-power">
      <div className="noc-card-head">
        <div className="noc-card-title">Energy & recoldissement</div>
        <div className="noc-card-meta">redondance · <b>N+1 ✓</b></div>
      </div>

      <div className="noc-power-flow">
        <div className="noc-power-node ok">
          <div className="ico">⚡</div>
          <div className="lbl">Network ENEDIS</div>
          <div className="val">412<span className="u">kW</span></div>
          <div className="state ok">ONLINE</div>
        </div>
        <div className="noc-flow-arrow"/>
        <div className="noc-power-node ok">
          <div className="ico">▣</div>
          <div className="lbl">UPSs</div>
          <div className="val">98<span className="u">%</span></div>
          <div className="state ok">CHARGÉS · 12 min</div>
        </div>
        <div className="noc-flow-arrow"/>
        <div className="noc-power-node">
          <div className="ico">⛁</div>
          <div className="lbl">Genset</div>
          <div className="val">100<span className="u">%</span></div>
          <div className="state standby">STANDBY · 4200 L</div>
        </div>
      </div>

      <div className="noc-power-bars">
        <div className="noc-power-bar">
          <div className="lbl">Phase L1</div>
          <div className="pb"><div className="fill" style={{width: "68%", background: "var(--noc-ok)"}}/><div className="marker" style={{left: "85%"}}/></div>
          <div className="v">141 A</div>
        </div>
        <div className="noc-power-bar">
          <div className="lbl">Phase L2</div>
          <div className="pb"><div className="fill" style={{width: "82%", background: "var(--noc-warn)"}}/><div className="marker" style={{left: "85%"}}/></div>
          <div className="v">170 A</div>
        </div>
        <div className="noc-power-bar">
          <div className="lbl">Phase L3</div>
          <div className="pb"><div className="fill" style={{width: "61%", background: "var(--noc-ok)"}}/><div className="marker" style={{left: "85%"}}/></div>
          <div className="v">126 A</div>
        </div>
        <div className="noc-power-bar">
          <div className="lbl">CRAC-1</div>
          <div className="pb"><div className="fill" style={{width: "72%", background: "var(--noc-info)"}}/></div>
          <div className="v">72%</div>
        </div>
        <div className="noc-power-bar">
          <div className="lbl">CRAC-2</div>
          <div className="pb"><div className="fill" style={{width: "78%", background: "var(--noc-info)"}}/></div>
          <div className="v">78%</div>
        </div>
        <div className="noc-power-bar">
          <div className="lbl">CRAC-3</div>
          <div className="pb"><div className="fill" style={{width: "0%"}}/></div>
          <div className="v" style={{color: "var(--noc-mute)"}}>STANDBY</div>
        </div>
      </div>
    </div>
  );
}

// ---------- Ticker ----------
function Ticker() {
  // duplicate so the loop is seamless
  const stream = [...TICKER_EVENTS, ...TICKER_EVENTS];
  return (
    <footer className="noc-ticker">
      <div className="tag">LIVE</div>
      <div className="noc-ticker-track">
        {stream.map((e, i) => (
          <span key={i}>
            <span className="ti-time">{e.t}</span>
            <span className={`ti-sev ${e.sev}`}>{e.sev.toUpperCase()}</span>
            <span>{e.text}</span>
            <span style={{color: "var(--noc-mute)"}}>·</span>
          </span>
        ))}
      </div>
    </footer>
  );
}

// ---------- Main ----------
function VueWallboard() {
  // Slight live tick to make values shimmer
  const [, setTick] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setTick(x => x + 1), 5000);
    return () => clearInterval(t);
  }, []);

  return (
    <div className="noc" data-screen-label="Wallboard NOC">
      <Header/>
      <Kpis/>
      <div className="noc-body">
        <RoomsCard/>
        <TicketsCard/>
        <AlertsCard/>
        <div style={{gridColumn: "2 / span 2"}}>
          <PowerCard/>
        </div>
      </div>
      <Ticker/>
    </div>
  );
}

window.VueWallboard = VueWallboard;
