// MATTER-LEVEL WAR ROOM v2 — Mutable state, pub/sub, mutation APIs
(function () {
  const clone = (x) => JSON.parse(JSON.stringify(x));
  const seed = window.MATTER_WR_DATA || {};

  const state = {
    motions:              clone(seed.motions || []),
    motionsInLimine:      clone(seed.motionsInLimine || []),
    discoveryRequests:    clone(seed.discoveryRequests || []),
    tar:                  clone(seed.tar || {}),
    privilegeLog:         clone(seed.privilegeLog || []),
    depositions:          clone(seed.depositions || []),
    experts:              clone(seed.experts || []),
    crossExam:            clone(seed.crossExam || []),
    narrative:            clone(seed.narrative || {}),
    mockTrial:            clone(seed.mockTrial || {}),
    courtroomOps:         clone(seed.courtroomOps || {}),
    authentications:      clone(seed.authentications || []),
    parallelProceedings:  clone(seed.parallelProceedings || []),
    regulatory:           clone(seed.regulatory || []),
    media:                clone(seed.media || {}),
    precedents:           clone(seed.precedents || []),
    damagesModel:         clone(seed.damagesModel || {}),
    settlementTree:       clone(seed.settlementTree || {}),
    budget:               clone(seed.budget || {}),
    coverage:             clone(seed.coverage || {}),
    auditLog:             [],
  };

  const bus = {
    _subs: {},
    on(topic, fn) {
      (this._subs[topic] = this._subs[topic] || []).push(fn);
      return () => { this._subs[topic] = (this._subs[topic] || []).filter(f => f !== fn); };
    },
    emit(topic, data) {
      (this._subs[topic] || []).forEach(fn => { try { fn(data); } catch (e) { console.error(e); } });
      (this._subs['*'] || []).forEach(fn => { try { fn({ topic, data }); } catch (e) { console.error(e); } });
      try { window.dispatchEvent(new CustomEvent('arbiter:mw.' + topic, { detail: data })); } catch {}
    },
  };

  const audit = (action, user, detail, ref) => {
    const entry = { ts: new Date().toISOString(), user: user || 'Trial Team', action, detail: detail || '', ref: ref || null };
    state.auditLog.unshift(entry);
    bus.emit('audit.logged', entry);
    return entry;
  };

  // ── MW1. Motion decisions ──
  const advanceMotion = (id, nextStatus, user) => {
    const m = state.motions.find(x => x.id === id);
    if (!m) return null;
    const prev = m.status;
    m.status = nextStatus;
    audit('motion.status', user, `${m.title}: ${prev} → ${nextStatus}`, id);
    bus.emit('motion.status', m);
    return m;
  };

  // ── MW2. Motion-in-Limine ──
  const forecastMil = (id, newOdds, user) => {
    const mil = state.motionsInLimine.find(x => x.id === id);
    if (!mil) return null;
    const prev = mil.grantOdds;
    mil.grantOdds = newOdds;
    audit('mil.forecast', user, `${mil.issue}: ${prev}% → ${newOdds}%`, id);
    bus.emit('mil.forecast', mil);
    return mil;
  };

  // ── MW3. Discovery meet-and-confer ──
  const logMeetAndConfer = (id, user) => {
    const r = state.discoveryRequests.find(x => x.id === id);
    if (!r) return null;
    r.metAndConferHeld = true;
    audit('discovery.mc', user, `Met and conferred on ${r.id}`, id);
    bus.emit('discovery.mc', r);
    return r;
  };
  const advanceDiscoveryCompleteness = (id, pct, user) => {
    const r = state.discoveryRequests.find(x => x.id === id);
    if (!r) return null;
    r.completenessPct = pct;
    audit('discovery.complete', user, `${r.id} → ${pct}%`, id);
    bus.emit('discovery.complete', r);
    return r;
  };

  // ── MW4. TAR round training ──
  const runTarRound = (user) => {
    const nextRound = state.tar.rounds.length + 1;
    const last = state.tar.rounds[state.tar.rounds.length - 1] || { precision: 50, recall: 40, trained: 0 };
    const newRound = {
      round: nextRound,
      trained: last.trained + 4500,
      precision: Math.min(95, last.precision + 3),
      recall: Math.min(92, last.recall + 4),
    };
    state.tar.rounds.push(newRound);
    state.tar.precisionPct = newRound.precision;
    state.tar.recallPct = newRound.recall;
    state.tar.f1 = (2 * newRound.precision * newRound.recall) / (newRound.precision + newRound.recall) / 100;
    audit('tar.round', user, `TAR round ${nextRound}: P=${newRound.precision}% R=${newRound.recall}%`);
    bus.emit('tar.round', newRound);
    return newRound;
  };

  // ── MW5. Privilege dispute ──
  const disputePrivilege = (id, user) => {
    const p = state.privilegeLog.find(x => x.id === id);
    if (!p) return null;
    p.disputed = true;
    audit('privilege.dispute', user, `Dispute raised on ${p.id} (${p.custodian})`, id);
    bus.emit('privilege.dispute', p);
    return p;
  };

  // ── MW6. Deposition goal tracking ──
  const recordDepoGoalHit = (id, goalIndex, user) => {
    const d = state.depositions.find(x => x.id === id);
    if (!d) return null;
    d.goalsHit = Math.min((d.goalsHit || 0) + 1, d.goals.length);
    audit('depo.goal', user, `${d.deponent} — goal ${goalIndex + 1} hit`, id);
    bus.emit('depo.goal', d);
    return d;
  };

  // ── MW7. Expert retention ──
  const retainExpert = (id, retainer, user) => {
    const e = state.experts.find(x => x.id === id);
    if (!e) return null;
    e.retainer = retainer;
    e.reportStatus = 'draft';
    audit('expert.retain', user, `${e.name} retained @ ${window.mw.money(retainer)}`, id);
    bus.emit('expert.retain', e);
    return e;
  };

  // ── MW8. Cross-exam rehearsal ──
  const rehearseCross = (id, newScore, user) => {
    const c = state.crossExam.find(x => x.id === id);
    if (!c) return null;
    const prev = c.controlScore;
    c.controlScore = newScore;
    audit('cross.rehearse', user, `${c.witness} — ${c.topic}: ${prev}% → ${newScore}%`, id);
    bus.emit('cross.rehearse', c);
    return c;
  };

  // ── MW10. Mock trial addition ──
  const addMockPanel = (user) => {
    state.mockTrial.panels += 1;
    state.mockTrial.totalRespondents += state.mockTrial.jurorsPerPanel;
    audit('mock.panel', user, `Mock panel #${state.mockTrial.panels} scheduled`);
    bus.emit('mock.panel', state.mockTrial);
    return state.mockTrial;
  };

  // ── MW11. Courtroom checklist ──
  const advanceChecklistItem = (idx, user) => {
    const list = state.courtroomOps.checklist;
    if (!list[idx]) return null;
    const item = list[idx];
    item.status = item.status === 'pending' ? 'in-progress' : 'done';
    audit('courtroom.item', user, `${item.item} → ${item.status}`);
    bus.emit('courtroom.item', item);
    return item;
  };

  // ── MW12. Authentication path ──
  const advanceAuthentication = (exhibit, nextStatus, user) => {
    const a = state.authentications.find(x => x.exhibit === exhibit);
    if (!a) return null;
    const prev = a.status;
    a.status = nextStatus;
    audit('auth.status', user, `${a.exhibit}: ${prev} → ${nextStatus}`, exhibit);
    bus.emit('auth.status', a);
    return a;
  };

  // ── MW13. Parallel proceedings ──
  const updateParallel = (id, nextStatus, user) => {
    const p = state.parallelProceedings.find(x => x.id === id);
    if (!p) return null;
    const prev = p.status;
    p.status = nextStatus;
    audit('parallel.status', user, `${p.forum}: ${prev} → ${nextStatus}`, id);
    bus.emit('parallel.status', p);
    return p;
  };

  // ── MW14. Regulatory escalation ──
  const advanceRegulatory = (id, nextStage, user) => {
    const r = state.regulatory.find(x => x.id === id);
    if (!r) return null;
    const prev = r.stage;
    r.stage = nextStage;
    audit('reg.stage', user, `${r.agency}: ${prev} → ${nextStage}`, id);
    bus.emit('reg.stage', r);
    return r;
  };

  // ── MW17. Damages Monte Carlo ──
  const runMonteCarlo = (user) => {
    // Simple synthetic re-roll — jitter the EV ±8%
    const jitter = 1 + (Math.random() * 0.16 - 0.08);
    state.damagesModel.evUsd = Math.round(state.damagesModel.evUsd * jitter);
    state.damagesModel.monteCarloRuns += 1000;
    audit('damages.mc', user, `Re-ran MC: EV → ${window.mw.money(state.damagesModel.evUsd)}`);
    bus.emit('damages.mc', state.damagesModel);
    return state.damagesModel;
  };

  // ── MW18. Settlement offer modeling ──
  const modelSettlementOffer = (offerUsd, user) => {
    const settleNode = state.settlementTree.nodes.find(n => n.id === 'settle-now');
    if (settleNode) settleNode.ev = offerUsd;
    state.settlementTree.summary.settleNowEv = offerUsd;
    audit('settle.model', user, `Modeled settle offer ${window.mw.money(offerUsd)}`);
    bus.emit('settle.model', state.settlementTree);
    return state.settlementTree;
  };

  // ── MW19. Budget draw ──
  const drawLitigationFinance = (amount, user) => {
    const lf = state.budget.litigationFinance;
    const avail = lf.undrawnUsd;
    const draw = Math.min(amount, avail);
    lf.drawnUsd += draw;
    lf.undrawnUsd -= draw;
    state.budget.remaining += draw;
    audit('budget.draw', user, `Drew ${window.mw.money(draw)} from ${lf.provider}`);
    bus.emit('budget.draw', lf);
    return lf;
  };

  // ── MW20. Coverage action ──
  const tenderToCarrier = (policyId, user) => {
    const p = state.coverage.policies.find(x => x.id === policyId);
    if (!p) return null;
    p.coverageStatus = 'tendered';
    audit('coverage.tender', user, `Tendered to ${p.carrier}`, policyId);
    bus.emit('coverage.tender', p);
    return p;
  };

  // ── Cross-platform bridges ──
  const pushMotionToCalendar = ({ motionId, milestone, dueDate }) => {
    const entry = { source: 'matterWarRoom', motionId, milestone, dueDate, ts: new Date().toISOString() };
    audit('calendar.push', 'System', `→ Calendar: ${milestone} on ${dueDate}`);
    bus.emit('calendar.push', entry);
    try { window.dispatchEvent(new CustomEvent('arbiter:mw.calendar.push', { detail: entry })); } catch {}
    return entry;
  };
  const pushPrivilegeToRulebook = ({ privId, basis }) => {
    const entry = { source: 'matterWarRoom', privId, basis, ts: new Date().toISOString() };
    audit('rulebook.push', 'System', `→ Rulebook: privilege ${privId}`);
    bus.emit('rulebook.push', entry);
    try { window.dispatchEvent(new CustomEvent('arbiter:mw.rulebook.push', { detail: entry })); } catch {}
    return entry;
  };
  const pushBudgetToBilling = ({ phase, spendUsd }) => {
    const entry = { source: 'matterWarRoom', phase, spendUsd, ts: new Date().toISOString() };
    audit('billing.push', 'System', `→ Billing: ${phase} ${window.mw.money(spendUsd)}`);
    bus.emit('billing.push', entry);
    try { window.dispatchEvent(new CustomEvent('arbiter:mw.billing.push', { detail: entry })); } catch {}
    return entry;
  };

  // ── Listeners ──
  window.addEventListener('arbiter:ba.matter.budget.changed', (ev) => {
    audit('billing.inbound', 'System', `Billing updated matter budget: ${ev.detail?.delta || '?'}`);
  });
  window.addEventListener('arbiter:calendar.deadline.changed', (ev) => {
    audit('calendar.inbound', 'System', `Calendar shifted deadline: ${ev.detail?.eventId || '?'}`);
  });

  // ── Aggregations ──
  const criticalMotions     = () => state.motions.filter(m => m.priority === 'critical' || m.priority === 'high').length;
  const overdueDiscovery    = () => state.discoveryRequests.filter(r => r.status === 'overdue').length;
  const privilegeExposure   = () => state.privilegeLog.reduce((s, p) => s + (p.disputed ? p.waiverRisk : 0), 0);
  const depositionGoalsPct  = () => {
    const total = state.depositions.reduce((s, d) => s + d.goals.length, 0);
    const hit = state.depositions.reduce((s, d) => s + (d.goalsHit || 0), 0);
    return total ? Math.round(100 * hit / total) : 0;
  };
  const activeParallelCount = () => state.parallelProceedings.filter(p => p.status === 'active' || p.status === 'preliminary').length;
  const regulatoryExposure  = () => state.regulatory.reduce((s, r) => s + r.likelihood * ((r.penaltyRange[1] + r.disgorgementRange[1]) / 2), 0);
  const coverageTowerUsd    = () => state.coverage.policies.reduce((s, p) => s + p.limit, 0);
  const burnRuntimeMonths   = () => state.budget.remaining / (state.budget.burnRatePerMonth || 1);
  const damagesEv           = () => state.damagesModel.evUsd;
  const trialVsSettleDelta  = () => state.settlementTree.summary.trialEvNet - state.settlementTree.summary.settleNowEv;

  const API = {
    state, bus, audit,
    advanceMotion, forecastMil,
    logMeetAndConfer, advanceDiscoveryCompleteness, runTarRound,
    disputePrivilege,
    recordDepoGoalHit, retainExpert, rehearseCross,
    addMockPanel, advanceChecklistItem, advanceAuthentication,
    updateParallel, advanceRegulatory,
    runMonteCarlo, modelSettlementOffer, drawLitigationFinance, tenderToCarrier,
    pushMotionToCalendar, pushPrivilegeToRulebook, pushBudgetToBilling,
    criticalMotions, overdueDiscovery, privilegeExposure, depositionGoalsPct,
    activeParallelCount, regulatoryExposure, coverageTowerUsd, burnRuntimeMonths,
    damagesEv, trialVsSettleDelta,
  };

  window.MatterWarRoomStore = API;

  window.useMatterWarRoomStore = (topics) => {
    const topicList = Array.isArray(topics) ? topics : [topics || '*'];
    const [, force] = React.useReducer(x => x + 1, 0);
    React.useEffect(() => {
      const offs = topicList.map(t => bus.on(t, () => force()));
      return () => offs.forEach(off => off());
    }, []);
    return state;
  };
})();
