/* SkyOps Core — the intelligence layer. Not a chat: an always-on loop that
   SENSES every signal (detections, SCADA, weather, work orders, field, fleet, warranty, commercial),
   CORRELATES them into situations with a causal hypothesis and € impact,
   DECIDES (proposes actions with rationale, evidence and confidence), ACTS per autonomy level,
   and LEARNS from every human accept / override. Every module reads and writes the same decision store. */

const { useState: uSCO, useEffect: uECO, useMemo: uMCO } = React;

const CORE_DOMAINS = {
  review: ["Review triage", "eye"], maintenance: ["Maintenance", "flag"], warranty: ["Warranty", "shield"],
  planning: ["Planning", "crosshair"], fleet: ["Fleet & crew", "drone"], commercial: ["Commercial", "tag"],
};
const CORE_LEVELS = [["suggest", "Suggest"], ["act", "Act & notify"], ["auto", "Autonomous"]];
const CORE_TODAY = "2026-04-17";

const coreStore = {
  v: (() => { try { return { dec: {}, autonomy: { review: "suggest", maintenance: "suggest", warranty: "suggest", planning: "suggest", fleet: "act", commercial: "suggest" }, log: [], ...JSON.parse(localStorage.getItem("skyops_core_v1") || "{}") }; } catch { return { dec: {}, autonomy: {}, log: [] }; } })(),
  subs: new Set(),
  set(fn) { this.v = fn(this.v); try { localStorage.setItem("skyops_core_v1", JSON.stringify(this.v)); } catch {} this.subs.forEach(s => s(this.v)); },
};
function useCore() { const [v, setV] = uSCO(coreStore.v); uECO(() => { coreStore.subs.add(setV); return () => coreStore.subs.delete(setV); }, []); return v; }

/* ── SENSE: signal inventory across modules ─────────────────── */
function coreSignals() {
  const D = window.DETECTIONS || [], W = window.woStore?.list || [], R = window.resStore?.data || { drones: [], people: [] };
  return [
    ["Detections", D.length, "inspection AI", "crosshair"], ["SCADA events", (window.ALERTS || []).length * 37, "Bentek · 7 sites", "zap"],
    ["Weather", 168, "Meteomatics · 7-day", "globe"], ["Work orders", W.length, "CMMS", "flag"],
    ["Field reports", (window.faQ?.v.obs || []).length, "technicians", "phone"], ["Fleet & crew", R.drones.length + R.people.length, "status · certs", "drone"],
    ["Warranty", (window.wcStore?.list || []).length, "claims", "shield"], ["Market", 24, "OMIE spot · hourly", "tag"],
  ];
}

/* ── CORRELATE + DECIDE: situations and proposed decisions ───── */
function coreModel() {
  const D = window.DETECTIONS || [], W = window.woStore?.list || [], S = window.SITES || [];
  const R = window.resStore?.data || { drones: [], people: [] };
  const site = (id) => S.find(s => s.id === id) || {};
  const pend = D.filter(d => d.review === "pending");
  const easy = pend.filter(d => d.confidence >= 92 && d.temporal === "PERSISTENT");
  const noise = pend.filter(d => d.confidence < 62 && d.severity === "low");
  const hot = D.filter(d => d.kind === "hot_cell" || d.kind === "activated_bypass");
  const wcEl = window.wcEligible ? window.wcEligible("pt-ev-03").filter(x => x.covered) : [];
  const wcN = wcEl.length, wcV = wcEl.reduce((a, x) => a + x.value, 0);
  const wo412 = W.find(w => w.id === "WO-2026-0412");
  const T = window.TM && window.TM.data;
  const tPid = T ? (T.pidSeries[3] + T.PID_THRESHOLD) * 1200 : 0;
  const tHail = T ? T.counts[2].bypass * 3000 : 0;
  const tDrain = T ? Math.round(T.audits[0].recovered) : 0;
  const tHotN = T ? T.missed.length : 0;
  const cast = R.people.find(p => p.name === "J. Castaño");
  const castCert = cast && cast.certs.find(c => c[0].startsWith("EASA"));
  const sit = [
    { id: "SIT-01", siteId: "pt-ev-03", sev: "critical", title: "Combiner CMB-04 · INV-08 fuse failure", cause: "SCADA string-current drop on 14 strings at 07:12, thermal shows uniform warm strings and one offline string at the same combiner — consistent with a blown string fuse, not module defects.",
      signals: [["SCADA", "14 strings · current −100% since 07:12"], ["Detection", "OBS-04204 offline string · conf 94%"], ["Weather", "irradiance 958 W/m² · no shading cause"], ["History", "same CMB had fuse swap 2025-09"]], impact: 380, unit: "€/day", conf: 0.91 },
    { id: "SIT-02", siteId: "pt-ev-03", sev: "high", title: "Manufacturing-defect pattern in module batch LRP2311", cause: `${wcN} warranty-eligible module defects (hot cell, bypass diode, cracking, delamination, PID) share the LRP2311 serial batch and have persisted 3 cycles. The same batch was credited by LONGi in WC-2026-005 — this is a manufacturing defect, claimable.`,
      signals: [["Detections", `${wcN} eligible MODULE defects`], ["Asset registry", "serial batch LRP2311"], ["Temporal", "persistent since 2025-10"], ["Warranty", "WC-2026-005 credited · same batch"]], impact: wcV, unit: "€ recoverable", conf: 0.86 },
    { id: "SIT-03", siteId: "es-mu-02", sev: "medium", title: "Soiling loss accelerating · Lorca", cause: "Soiling index rose 1.9 → 4.6% in 21 dry days. Spot price is above the 30-day average this week, so each day of delay costs more than the wash.",
      signals: [["Satellite", "soiling index 4.6% · +2.7 pts"], ["Weather", "0 mm rain · 21 days · none forecast"], ["Market", "OMIE €71/MWh vs €52 avg"], ["SCADA", "PR −3.1% vs clean baseline"]], impact: 4100, unit: "€ loss avoided", conf: 0.82 },
    { id: "SIT-04", siteId: "es-zr-07", sev: "high", title: "Stuck tracker block before wind event", cause: "Rows 14–27 are stuck at 38° tilt. Gusts of 19 m/s are forecast Thursday 14:00 — above the stow limit. A stuck block cannot stow.",
      signals: [["SCADA", "TCU-B fault · rows 14–27 · 38°"], ["Weather", "gusts 19 m/s · Thu 14:00"], ["Work order", "WO-2026-0421 in progress"], ["Asset", "NEXTracker NX Horizon"]], impact: 62000, unit: "€ asset at risk", conf: 0.88 },
    { id: "SIT-05", siteId: "es-zr-07", sev: "medium", title: "Pilot certification lapses mid-mission", cause: `J. Castaño leads the Zaragoza re-fly but his EASA A2 CofC expires ${castCert ? castCert[1] : "soon"}. T. Aragón is certified, available and thermography Level 2.`,
      signals: [["Crew", `EASA A2 · ${castCert ? castCert[1] : "—"}`], ["Inspection", "MIC-2026-04-031 · capture 41%"], ["Fleet", "ASI-07 deployed · Zaragoza"]], impact: 0, unit: "compliance", conf: 0.95 },
    { id: "SIT-06", siteId: "es-ab-01", sev: "high", title: "Albacete processing failure threatens SLA", cause: "SfM failed on sector 4 (GPS drift > 4 m). Report is due in 2 working days. Re-running with the 6 ground control points from the last cycle resolves drift in 9 of 10 past cases.",
      signals: [["Pipeline", "SfM · insufficient tie points · sector 4"], ["GNSS", "drift 4.2 m · sortie 6"], ["Commercial", "SLA ≤ 5 wd · 3 used"], ["History", "GCP re-run fixed 9/10"]], impact: 4890, unit: "€ invoice at risk", conf: 0.84 },
    ...(T ? [
    { id: "SIT-07", siteId: "pt-ev-03", sev: "high", src: "temporal", title: "PID front spreading from string S-01-09", cause: `Temporal intelligence: PID-affected panels grew ${T.pidSeries.join(" → ")} over four cycles, a radial front around one inverter. At this rate block S-01 crosses the ${T.PID_THRESHOLD}-panel string-isolation threshold in ~${T.qToCliff} quarters.`,
      signals: [["Temporal", `${T.pidSeries.join(" → ")} panels · 4 cycles`], ["Forecast", `threshold in ~${T.qToCliff} qtrs`], ["Spatial", "radial front · INV-01"], ["Similar sites", "11 Iberian sites · anti-PID halted spread in 9"]], impact: tPid, unit: "€/yr at stake", conf: 0.91 },
    { id: "SIT-08", siteId: "pt-ev-03", sev: "medium", src: "temporal", title: "Hail damage · bypass diodes rows 2–4", cause: `${T.counts[2].bypass} bypass-diode activations appeared after the 14 Nov 2025 hailstorm, all inside the storm path (94% spatial overlap). External event, so it falls under the property insurance policy, not the manufacturer warranty.`,
      signals: [["Temporal", `${T.counts[2].bypass} new bypass activations Q4 25 → Q1 26`], ["Weather", "WX-07 · hail 22 mm · 2025-11-14"], ["Spatial", "94% inside storm path"], ["Policy", "property damage · deductible €1,000"]], impact: tHail, unit: "€ recoverable", conf: 0.88 },
    { id: "SIT-09", siteId: "pt-ev-03", sev: "medium", src: "temporal", title: "Re-soiling at rows 9–10 is a drainage defect", cause: `WO-118 cleared most soiling, but rows 9–10 re-soiled within 4 weeks at the spot where the 19 Mar rain pooled. Another wash will not hold until runoff is fixed.`,
      signals: [["Action audit", "WO-118 · partial"], ["Weather", "WX-09 · 41 mm / 24 h"], ["Temporal", "re-soiled within 4 weeks"]], impact: tDrain, unit: "€/yr", conf: 0.84 },
    ] : []),
  ];
  let dec = [
    { id: "DEC-R1", dom: "review", sit: null, siteId: "pt-ev-03", title: `Accept ${easy.length} detection${easy.length === 1 ? "" : "s"} that match${easy.length === 1 ? "es" : ""} confirmed signatures`, why: `All ≥ 92% confidence, persistent across cycles and previously accepted by a reviewer. Saves ≈ ${Math.round(easy.length * 0.6)} min of review.`, impact: 0, conf: 0.97, action: { type: "accept_dets", ids: easy.map(d => d.id) }, n: easy.length },
    { id: "DEC-R2", dom: "review", sit: null, siteId: "pt-ev-03", title: `Reject ${noise.length} low-confidence low-severity detection${noise.length === 1 ? "" : "s"} as noise`, why: "Confidence < 62%, severity low, no SCADA or temporal corroboration. Reviewers rejected 88% of similar detections last cycle.", impact: 0, conf: 0.81, action: { type: "reject_dets", ids: noise.map(d => d.id) }, n: noise.length },
    { id: "DEC-M1", dom: "maintenance", sit: "SIT-01", siteId: "pt-ev-03", title: "Expedite WO-2026-0412 to today · R. Pardal", why: "R. Pardal holds HV authorisation, is 12 km from site and free after 11:00. Every day costs €380.", impact: 380 * 2, conf: 0.91, action: { type: "wo_patch", id: "WO-2026-0412", patch: { prio: "P1", due: CORE_TODAY, status: wo412 && wo412.status === "open" ? "assigned" : (wo412 ? wo412.status : "assigned") } } },
    { id: "DEC-W1", dom: "warranty", sit: "SIT-02", siteId: "pt-ev-03", title: `Open warranty claim · ${wcN} module${wcN === 1 ? "" : "s"}, batch LRP2311`, why: "Same batch already credited once (WC-2026-005). Estimated approval likelihood 86% with IR + RGB + temporal history.", impact: wcV, conf: 0.86, action: { type: "warranty", siteId: "pt-ev-03", items: wcN, value: wcV, serials: wcEl.map(x => x.serial) }, n: wcN },
    { id: "DEC-M2", dom: "maintenance", sit: "SIT-03", siteId: "es-mu-02", title: "Bring Lorca wash forward to this week · CleanTech Iberia", why: "€4,100 loss avoided vs €2,400 wash cost (payback 0.6). CleanTech SLA is 5 working days — book now.", impact: 1700, conf: 0.82, action: { type: "wo_new", wo: { siteId: "es-mu-02", title: "Robotic wash — soiling 4.6%", loc: "All blocks", type: "Cleaning", prio: "P2", assignee: "CleanTech Iberia (contractor)", cost: 2400, rar: 4100 } } },
    { id: "DEC-M3", dom: "maintenance", sit: "SIT-04", siteId: "es-zr-07", title: "Manual stow rows 14–27 before Thursday 12:00", why: "Prevents structural damage in a 19 m/s gust event. S. Lima (tracker skills) is on WO-2026-0421 already.", impact: 62000, conf: 0.88, action: { type: "wo_new", wo: { siteId: "es-zr-07", title: "Manual stow rows 14–27 — wind event Thu", loc: "Rows 14–27 · TCU-B", type: "Tracker", prio: "P1", assignee: "S. Lima · O&M crew B", cost: 600, rar: 62000 } } },
    { id: "DEC-F1", dom: "fleet", sit: "SIT-05", siteId: "es-zr-07", title: "Swap lead pilot on MIC-2026-04-031 to T. Aragón", why: "Keeps the mission compliant after J. Castaño's certificate lapses. Renewal reminder sent to J. Castaño.", impact: 0, conf: 0.95, action: { type: "mic_patch", id: "MIC-2026-04-031", patch: { lead: "T. Aragón" } } },
    { id: "DEC-P1", dom: "planning", sit: "SIT-06", siteId: "es-ab-01", title: "Re-run Albacete sector 4 with ground control points", why: "Fixes GPS drift in 9/10 past cases; finishes in ≈ 40 min and protects the €4,890 invoice SLA.", impact: 4890, conf: 0.84, action: { type: "note" } },
    { id: "DEC-P2", dom: "planning", sit: null, siteId: "pt-ev-03", title: "Fly only zones with open defects in the Q3 re-check", why: "Zones Z01–Z02 hold 92% of open defects. Flying 2 of 4 zones halves flight time with no loss of verification coverage.", impact: 1350, conf: 0.79, action: { type: "note" } },
    ...(T ? [
    { id: "DEC-T1", dom: "maintenance", sit: "SIT-07", src: "temporal", siteId: "pt-ev-03", title: "Energise anti-PID box on INV-01", why: `Halts the PID front before block S-01 hits the isolation threshold (~${T.qToCliff} qtrs). €4,800 one-off vs ${coreEur(tPid)}/yr at stake.`, impact: tPid, conf: 0.86, action: { type: "wo_new", wo: { siteId: "pt-ev-03", title: "Install & energise anti-PID box — INV-01", loc: "Block S-01 · INV-01", type: "Electrical", prio: "P1", assignee: "R. Pardal", cost: 4800, rar: tPid, due: "2026-05-15" } } },
    { id: "DEC-T2", dom: "maintenance", sit: null, src: "temporal", siteId: "pt-ev-03", title: `Replace the ${tHotN} hot-cell modules left out of WO-131`, why: `Persisted at 86% probability after WO-131. Leaving them cost ${coreEur(T.missedCost)}/yr; one mobilisation covers all.`, impact: T.missedCost, conf: 0.81, n: tHotN, action: { type: "wo_new", wo: { siteId: "pt-ev-03", title: `Replace ${tHotN} persistent hot-cell modules`, loc: "Block S-01 · see temporal F5", type: "Module replace", prio: "P2", assignee: "R. Pardal", cost: tHotN * 346, rar: T.missedCost } } },
    { id: "DEC-T3", dom: "maintenance", sit: "SIT-09", src: "temporal", siteId: "pt-ev-03", title: "Re-grade drainage swale at rows 9–10 before the next wash", why: "Runoff re-soils these rows within 4 weeks of any wash. Fix the cause once (€6,500) instead of re-washing every quarter.", impact: tDrain, conf: 0.84, action: { type: "wo_new", wo: { siteId: "pt-ev-03", title: "Re-grade drainage swale — rows 9–10", loc: "Rows 9–10 · cols 18–24", type: "Vegetation", prio: "P3", assignee: "Unassigned", cost: 6500, rar: tDrain } } },
    { id: "DEC-T4", dom: "warranty", sit: "SIT-08", src: "temporal", siteId: "pt-ev-03", title: `File hail insurance claim · ${T.counts[2].bypass} modules, rows 2–4`, why: "External event (WX-07) — not a manufacturer defect. Temporal history proves the damage appeared only after 14 Nov inside the storm path.", impact: tHail, conf: 0.88, action: { type: "insurance", siteId: "pt-ev-03", items: T.counts[2].bypass, value: tHail } },
    ] : []),
    { id: "DEC-C1", dom: "commercial", sit: null, siteId: "es-ca-05", title: "Raise Cáceres quote rate to €19.5/ha", why: "Tracker site with 3 critical defects last cycle: review hours run 40% above average. At €18/ha projected margin is 21%, below the 30% floor.", impact: 3760, conf: 0.73, action: { type: "note" } },
  ];
  // Only propose what is still true in the record (decided items stay visible as history)
  const st = coreStore.v.dec;
  const mic031 = (window.INSPECTIONS || []).find(i => i.id === "MIC-2026-04-031");
  const valid = {
    "DEC-M1": wo412 && ["open", "assigned"].includes(wo412.status) && wo412.due > CORE_TODAY,
    "DEC-M2": !W.some(w => w.siteId === "es-mu-02" && w.type === "Cleaning" && !["done", "verified"].includes(w.status) && w.origin !== "DEC-M2"),
    "DEC-M3": !W.some(w => w.siteId === "es-zr-07" && /stow/i.test(w.title) && w.origin !== "DEC-M3"),
    "DEC-F1": mic031 && mic031.lead === "J. Castaño",
    "DEC-T1": !W.some(w => /anti-PID/i.test(w.title) && /INV-01/.test((w.loc || "") + w.title) && !["done", "verified"].includes(w.status) && w.origin !== "DEC-T1"),
    "DEC-T3": !W.some(w => /swale|drainage/i.test(w.title) && w.origin !== "DEC-T3"),
    "DEC-T4": !(window.wcStore?.list || []).some(x => x.kind === "insurance" && x.siteId === "pt-ev-03" && x.origin !== "DEC-T4"),
    "DEC-W1": !(window.wcStore?.list || []).some(x => x.origin === "DEC-W1" || (x.siteId === "pt-ev-03" && x.kind !== "insurance" && ["draft", "submitted", "review"].includes(x.status))),
  };
  dec = dec.filter(d => st[d.id] || ((d.n === undefined || d.n > 0) && valid[d.id] !== false));
  return { sit, dec };
}

/* ── ACT ─────────────────────────────────────────────────────── */
function coreExecute(d, by = "You") {
  const a = d.action; let ref = null;
  if (a.type === "accept_dets" || a.type === "reject_dets") {
    const st = a.type === "accept_dets" ? "accepted" : "rejected";
    (window.DETECTIONS || []).forEach(x => { if (a.ids.includes(x.id)) x.review = st; });
    window.dispatchEvent(new CustomEvent("skyops:dets", { detail: { ids: a.ids, review: st } }));
  }
  if (a.type === "wo_patch") ref = a.id;
  if (a.type === "wo_patch" && window.woStore) window.woStore.set(l => l.map(w => w.id === a.id ? { ...w, ...a.patch } : w));
  if (a.type === "wo_new" && window.woStore) { ref = window.woNextId(window.woStore.list); } if (a.type === "wo_new" && window.woStore) window.woStore.set(l => [{ id: ref, status: "assigned", created: CORE_TODAY, due: "2026-04-21", verifyMic: "next inspection", checklist: [], mic: "", obs: "—", origin: d.id, ...a.wo }, ...l]);
  if (a.type === "warranty" && window.wcStore) { ref = `WC-2026-0${11 + window.wcStore.list.length}`; } if (a.type === "warranty" && window.wcStore) window.wcStore.set(l => [{ id: ref, siteId: a.siteId, mfr: "LONGi Green Energy", model: "Longi Hi-MO5 LR5-72HPH-550M", ref: "—", status: "draft", created: CORE_TODAY, submitted: null, items: a.items, value: a.value, credited: 0, serials: a.serials, note: "Drafted by Argus · batch LRP2311", origin: d.id, evidence: { temporal: true } }, ...l]);
  if (a.type === "insurance" && window.wcStore) { ref = `IC-2026-0${String(21 + window.wcStore.list.filter(x => x.kind === "insurance").length)}`; window.wcStore.set(l => [{ id: ref, kind: "insurance", siteId: a.siteId, mfr: "Fidelidade · property policy PT-88412", model: "Hail · WX-07 · 2025-11-14", ref: "—", status: "draft", created: CORE_TODAY, submitted: null, items: a.items, value: a.value, credited: 0, note: "Drafted by Argus from Temporal intelligence (F3)", origin: d.id, evidence: { temporal: true, weather: true } }, ...l]); }
  if (a.type === "mic_patch") { const m = (window.INSPECTIONS || []).find(i => i.id === a.id); if (m) { Object.assign(m, a.patch); window.saveMicState && window.saveMicState(m); } }
  coreStore.set(v => ({ ...v, dec: { ...v.dec, [d.id]: { st: "done", by, ref, at: new Date().toISOString().slice(11, 16) } }, log: [{ at: new Date().toISOString().slice(11, 16), id: d.id, t: d.title, by }, ...v.log].slice(0, 40) }));
}
const coreDismiss = (d, reason) => coreStore.set(v => ({ ...v, dec: { ...v.dec, [d.id]: { st: "dismissed", reason, at: new Date().toISOString().slice(11, 16) } } }));

/* Autonomous domains act on load when confidence ≥ 0.9 */
function coreAutoRun() {
  const { dec } = coreModel(), v = coreStore.v;
  dec.filter(d => !v.dec[d.id] && v.autonomy[d.dom] === "auto" && d.conf >= 0.9).forEach(d => coreExecute(d, "Argus · autonomous"));
}

function useCoreModel() { const v = useCore(); window.useWOs && window.useWOs(); return uMCO(() => { const m = coreModel(); return { ...m, dec: m.dec.map(d => ({ ...d, state: v.dec[d.id] || null, level: v.autonomy[d.dom] })) }; }, [v]); }
const coreEur = (n) => "€" + Math.round(n).toLocaleString("en-US");

/* ── Shared inline UI ───────────────────────────────────────── */
function CoreMark({ small }) { return <span className={`core-mark ${small ? "sm" : ""}`}><i/>Argus</span>; }

function CoreDecision({ d, compact }) {
  const [why, setWhy] = uSCO(!compact);
  const done = d.state?.st === "done", dis = d.state?.st === "dismissed";
  const m = coreModel(); const s = d.sit && m.sit.find(x => x.id === d.sit);
  return (
    <div className={`core-dec ${done ? "done" : ""} ${dis ? "dis" : ""}`}>
      <div className="core-dec-hd">
        <span className="core-dom"><Icon name={CORE_DOMAINS[d.dom][1]} size={11}/>{CORE_DOMAINS[d.dom][0]}</span>
        <b>{d.title}</b>
        <span className="core-conf" title="Model confidence"><i style={{ width: d.conf * 100 + "%" }}/><em className="mono">{Math.round(d.conf * 100)}%</em></span>
      </div>
      {why && <div className="core-why">{d.why}{s && <div className="core-sig">{s.signals.map(([k, t]) => <span key={k}><b>{k}</b>{t}</span>)}</div>}</div>}
      <div className="core-dec-ft">
        {d.impact > 0 && <span className="mono core-imp">{coreEur(d.impact)}</span>}
        {compact && <button className="cm-link" onClick={() => setWhy(!why)}>{why ? "Hide reasoning" : "Why?"}</button>}
        <span className="grow"/>
        {done ? <span className="core-done"><Icon name="check_circle" size={12}/>{d.state.by === "You" ? "Approved" : "Executed by " + d.state.by} · {d.state.at}{d.state.ref && <button className="cm-link mono" style={{ marginLeft: 6 }} onClick={() => window.__inNav && window.__inNav.go(/^(WC|IC)/.test(d.state.ref) ? "warranty" : "workorders")}>→ {d.state.ref}</button>}</span>
          : dis ? <span className="sec" style={{ fontSize: 11 }}>Dismissed · feedback recorded</span>
          : <><button className="btn btn-ghost btn-xs" onClick={() => coreDismiss(d, "not useful")}>Dismiss</button><button className="btn btn-primary btn-xs" onClick={() => coreExecute(d)}><Icon name="check" size={11}/>Approve</button></>}
      </div>
    </div>
  );
}

/* Drop-in strip for any module: <CoreStrip dom="maintenance" siteId="…"/> */
function CoreStrip({ dom, siteId, title, limit = 3 }) {
  const { dec } = useCoreModel();
  const doms = Array.isArray(dom) ? dom : dom ? [dom] : null;
  const list = dec.filter(d => (!doms || doms.includes(d.dom)) && (!siteId || d.siteId === siteId)).sort((a, b) => (!!a.state - !!b.state) || b.impact - a.impact);
  const open = list.filter(d => !d.state);
  const [all, setAll] = uSCO(false);
  if (!list.length) return null;
  return (
    <div className="core-strip">
      <div className="core-strip-hd"><CoreMark/><b>{title || "Argus recommends"}</b><span className="sec">{open.length} open · {coreEur(open.reduce((a, d) => a + d.impact, 0))} impact</span><span className="grow"/>
</div>
      <div className="core-strip-l">{(all ? list : list.slice(0, limit)).map(d => <CoreDecision key={d.id} d={d} compact/>)}</div>
      {list.length > limit && <button className="cm-link core-more" onClick={() => setAll(!all)}>{all ? "Show less" : `Show ${list.length - limit} more`}</button>}
    </div>
  );
}

/* Per-detection explanation (Review) */
function CoreExplain({ det }) {
  const k = det.kind, dT = det.dT;
  const feats = [
    ["Thermal signature", k === "hot_cell" ? `single-cell hotspot · ΔT +${dT.toFixed(1)} °C · circular` : k === "activated_bypass" ? "1/3 module sub-string uniformly warm" : k === "offline_string" ? "whole string uniformly warm" : `pattern matches ${det.label.toLowerCase()}`],
    ["Corroboration", det.source === "SENSOR_CONTINUOUS" ? "SCADA current deviation on same string" : det.temporal === "PERSISTENT" ? "seen in previous cycles at same module" : "single source · this inspection"],
    ["Conditions", "irradiance 952 W/m² · wind 2.5 m/s · emissivity 0.85 — within IEC TS 62446-3"],
    ["Similar cases", `${12 + (det.confidence % 30)} past detections · ${Math.min(99, det.confidence + 2)}% confirmed by reviewers`],
  ];
  const sug = det.confidence >= 90 ? ["accept", "Accept"] : det.confidence < 62 ? ["reject", "Likely noise — reject"] : ["review", "Needs human judgement"];
  return (
    <div className="core-exp">
      <div className="core-exp-hd"><CoreMark small/><span>Why the model flagged this</span><span className="grow"/><span className={`core-sug core-sug-${sug[0]}`}>{sug[1]}</span></div>
      {feats.map(([a, b]) => <div key={a} className="core-exp-r"><span>{a}</span><b>{b}</b></div>)}
    </div>
  );
}

/* Topbar pulse — the nervous system is always visible */
function CorePulse() {
  const { sit, dec } = useCoreModel();
  const open = dec.filter(d => !d.state);
  return (
    <button className="core-pulse" onClick={() => window.agOpen ? window.agOpen({}) : (window.agStore && window.agStore.set(x => ({ ...x, open: true })))} title="Argus · open decisions">
      <span className="core-beat"/><span className="mono">{sit.length}</span><em>situations</em><span className="mono">{open.length}</span><em>decisions</em>
    </button>
  );
}

/* ── Core page — Sense → Correlate → Decide → Act → Learn ──── */
function CorePage({ go, setActiveSite }) {
  const v = useCore();
  const { sit, dec } = useCoreModel();
  const [selSit, setSelSit] = uSCO(null);
  const [tab, setTab] = uSCO("loop");
  const sig = coreSignals();
  const open = dec.filter(d => !d.state), done = dec.filter(d => d.state?.st === "done"), dis = dec.filter(d => d.state?.st === "dismissed");
  const site = (id) => (window.SITES || []).find(s => s.id === id);
  const shown = selSit ? dec.filter(d => d.sit === selSit) : open;
  const acc = Object.keys(CORE_DOMAINS).map(k => { const all = dec.filter(d => d.dom === k && d.state); const ok = all.filter(d => d.state.st === "done"); return [k, all.length, ok.length]; });
  return (
    <div className="page core">
      <div className="page-head">
        <div className="title"><div className="kicker">Intelligence · the system's nervous system</div><h1>Argus</h1>
          <div className="sub">Senses every signal, correlates them into situations, proposes decisions with evidence, acts within the autonomy you set, and learns from every override.</div></div>
      </div>

      <div className="core-loop">
        {[["Sense", `${sig.reduce((a, s) => a + s[1], 0).toLocaleString()} signals`, "8 channels · last 24 h"], ["Correlate", `${sit.length} situations`, `${sit.filter(s => s.sev === "critical").length} critical`], ["Decide", `${open.length} decisions`, `${coreEur(open.reduce((a, d) => a + d.impact, 0))} at stake`], ["Act", `${done.length} executed`, `${done.filter(d => d.state.by !== "You").length} autonomously`], ["Learn", `${dis.length} override${dis.length === 1 ? "" : "s"}`, "fed back to models"]].map(([a, b, c], i) => (
          <div key={a} className="core-step"><span className="caps">{i + 1} · {a}</span><b>{b}</b><em>{c}</em></div>))}
      </div>

      <div className="tabs" style={{ marginBottom: 12 }}>{[["loop", "Situations & decisions"], ["sense", "Signals"], ["autonomy", "Autonomy"], ["learn", "Learning & audit"]].map(([k, l]) => <button key={k} className={tab === k ? "on" : ""} onClick={() => setTab(k)}>{l}</button>)}</div>

      {tab === "loop" && <div className="core-2">
        <div className="core-sits">
          <div className="caps" style={{ marginBottom: 6 }}>Situations · correlated from multiple signals</div>
          {sit.map(s => (
            <button key={s.id} className={`core-sit ${selSit === s.id ? "on" : ""}`} onClick={() => setSelSit(selSit === s.id ? null : s.id)}>
              <div className="core-sit-hd"><span className={`al-sev al-sev-${s.sev}`}/><b>{s.title}</b></div>
              <span className="sec core-sit-s">{site(s.siteId)?.name} · {s.signals.length} signals · confidence {Math.round(s.conf * 100)}%</span>
              {selSit === s.id && <><p className="core-cause">{s.cause}</p><div className="core-sig">{s.signals.map(([k, t]) => <span key={k}><b>{k}</b>{t}</span>)}</div></>}
              {s.impact > 0 && <span className="mono core-imp">{coreEur(s.impact)} <em>{s.unit}</em></span>}
            </button>))}
        </div>
        <div className="core-decs">
          <div className="caps" style={{ marginBottom: 6 }}>{selSit ? `Decisions for ${selSit}` : "Decision queue · ranked by impact"}{selSit && <button className="cm-link" style={{ marginLeft: 8 }} onClick={() => setSelSit(null)}>Show all</button>}</div>
          {shown.sort((a, b) => b.impact - a.impact).map(d => <CoreDecision key={d.id} d={d}/>)}
          {shown.length === 0 && <div className="sec" style={{ fontSize: 12, padding: 20 }}>No open decisions. Argus keeps watching.</div>}
        </div>
      </div>}

      {tab === "sense" && <div className="core-sense">{sig.map(([n, c, src, ic]) => (
        <div key={n} className="core-sense-it card"><Icon name={ic} size={15}/><div><b>{n}</b><span className="sec">{src}</span></div><b className="mono">{c.toLocaleString()}</b></div>))}</div>}

      {tab === "autonomy" && <div className="card st-card" style={{ maxWidth: 900 }}>
        <div className="st-card-h">Autonomy per domain<span>Autonomous acts only when confidence ≥ 90%; every action is logged and reversible</span></div>
        {Object.entries(CORE_DOMAINS).map(([k, [l, ic]]) => (
          <div key={k} className="st-row"><div className="st-row-l"><b><Icon name={ic} size={12}/> {l}</b><span>{dec.filter(d => d.dom === k).length} decision types · {k === "warranty" || k === "commercial" ? "financial — human sign-off recommended" : "operational"}</span></div>
            <div className="st-row-c"><div className="ps-seg">{CORE_LEVELS.map(([lv, ll]) => <button key={lv} className={v.autonomy[k] === lv ? "on" : ""} onClick={() => { coreStore.set(x => ({ ...x, autonomy: { ...x.autonomy, [k]: lv } })); if (lv === "auto") setTimeout(coreAutoRun, 0); }}>{ll}</button>)}</div></div></div>))}
      </div>}

      {tab === "learn" && <div className="core-2">
        <div className="card st-card">
          <div className="st-card-h">Model performance<span>reviewer feedback · last 4 cycles</span></div>
          {[["Detection precision", "94.1%", "ai-v4.2 · thermal seg"], ["Classification accuracy", "89.6%", "19 anomaly classes"], ["Calibration error", "2.8%", "confidence vs reality"], ["Root-cause hit rate", "81.0%", "situations confirmed in the field"], ["Decision acceptance", `${dec.filter(d => d.state).length ? Math.round(done.length / dec.filter(d => d.state).length * 100) : 0}%`, `${done.length} approved · ${dis.length} dismissed`]].map(([a, b, c]) => (
            <div key={a} className="st-row"><div className="st-row-l"><b>{a}</b><span>{c}</span></div><div className="st-row-c"><b className="mono" style={{ fontSize: 15 }}>{b}</b></div></div>))}
          <div className="st-sub">Acceptance by domain</div>
          {acc.map(([k, n, ok]) => <div key={k} className="st-row"><div className="st-row-l"><b>{CORE_DOMAINS[k][0]}</b><span>{n} decided</span></div><div className="st-row-c"><b className="mono">{n ? Math.round(ok / n * 100) + "%" : "—"}</b></div></div>)}
        </div>
        <div className="card"><div className="card-hd">Audit trail<span className="sub">every Argus action</span></div>
          <div style={{ padding: "6px 14px 12px" }}>{v.log.length === 0 && <div className="sec" style={{ fontSize: 12, padding: 10 }}>No actions yet.</div>}
            {v.log.map((l, i) => <div key={i} className="dd-log dd-log-ok"><i/><span className="mono dd-log-d">{l.at}</span><span className="dd-log-t">{l.t}</span><span className="sec dd-log-b">{l.by}</span></div>)}</div></div>
      </div>}
    </div>
  );
}

setTimeout(coreAutoRun, 0);
Object.assign(window, { useCoreModel, coreExecuteDec: coreExecute, CorePage, CoreStrip, CoreExplain, CorePulse, CoreMark, coreStore, coreModel });
