// CRUCIBLE — Cross-tab event bus + reactive store hook.
// Mirrors the pattern of window.useRiskStore / window.RiskStore.
//
// Topics:
//   argument.created   — new argument node added to graph
//   argument.updated   — node label/strength changed
//   argument.removed   — node removed
//   argument.linked    — edge added between nodes
//   argument.unlinked  — edge removed
//   argument.attacked  — Adversary tab simulated an attack
//   argument.hardened  — node strength bumped via remediation
//   recon.viewed       — opposing-counsel dossier opened
//   citation.added     — Authority pinned to a node
//   brief.forked       — Brief Bank template forked
//
// Usage from any Crucible component:
//   const s = window.useCrucibleStore(['argument.updated']);
//   // s = { ran: <count>, …window.CRUCIBLE_DATA }

(function () {
  const { useState, useEffect } = React;
  const subs = new Map();   // topic -> Set<fn>

  function on(topic, fn) {
    if (!subs.has(topic)) subs.set(topic, new Set());
    subs.get(topic).add(fn);
    return () => subs.get(topic)?.delete(fn);
  }
  function emit(topic, payload) {
    (subs.get(topic) || []).forEach(fn => { try { fn(payload); } catch {} });
    // also fan out to a global so Arbiter telemetry can see every event
    if (window.Arbiter?.track) window.Arbiter.track('crucible.bus', { topic });
  }

  function useCrucibleStore(topics = []) {
    const [ran, setRan] = useState(0);
    useEffect(() => {
      const offs = topics.map(t => on(t, () => setRan(r => r + 1)));
      return () => offs.forEach(off => off?.());
    }, [topics.join(',')]);
    return Object.assign({ ran }, window.CRUCIBLE_DATA || {});
  }

  window.CrucibleStore = {
    bus: { on, emit },
    on, emit,
    // convenience action emitters used by the UI
    addArgumentNode: (node)       => emit('argument.created', { node }),
    updateArgumentNode: (id, patch)=> emit('argument.updated', { id, patch }),
    removeArgumentNode: (id)      => emit('argument.removed', { id }),
    linkArgumentNodes: (from, to) => emit('argument.linked',  { from, to }),
    unlinkArgumentNodes: (id)     => emit('argument.unlinked',{ id }),
    runAttack: (argId)            => emit('argument.attacked', { argId }),
    hardenArgument: (id, delta)   => emit('argument.hardened', { id, delta }),
    viewRecon: (counselId)        => emit('recon.viewed', { counselId }),
    addCitation: (nodeId, cite)   => emit('citation.added', { nodeId, cite }),
    forkBrief: (briefId)          => emit('brief.forked', { briefId }),
  };
  window.useCrucibleStore = useCrucibleStore;
})();
