// CALENDAR STORE — mutable state, pub/sub, APIs (pattern: DiscoveryStore)
(function () {
  const clone = (x) => JSON.parse(JSON.stringify(x));

  const state = {
    deadlines:        clone(window.DOCKET_DEADLINES || []),
    attorneys:        clone(window.ATTORNEYS || []),
    rules:            clone(window.COURT_RULES || []),
    sol:              clone(window.SOL_TRACKER || []),
    rulePacks:        clone(window.JURISDICTION_RULE_PACKS || []),
    holidays:         clone(window.COURT_HOLIDAYS || []),
    standingOrders:   clone(window.JUDGE_STANDING_ORDERS || []),
    cascadeRuns:      clone(window.CASCADE_RUNS || []),
    pacerEntries:     clone(window.PACER_ENTRIES || []),
    serviceOfProcess: clone(window.SERVICE_OF_PROCESS || []),
    motions:          clone(window.MOTIONS || []),
    continuances:     clone(window.CONTINUANCES || []),
    hearingPrep:      clone(window.HEARING_PREP || []),
    witnessAvail:     clone(window.WITNESS_AVAILABILITY || []),
    escalationRules:  clone(window.ESCALATION_RULES || []),
    clientReports:    clone(window.CLIENT_REPORTS || []),
    workloadForecast: clone(window.WORKLOAD_FORECAST || []),
    conflictChecks:   clone(window.CONFLICT_CHECKS || []),
    expertDisclosures: clone(window.EXPERT_DISCLOSURES || []),
    eventTemplates:   clone(window.EVENT_TEMPLATES || []),
    defensibilityAudit: clone(window.DEFENSIBILITY_AUDIT || []),
  };

  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:cal.' + topic, { detail: data })); } catch {}
    },
  };

  const audit = (deadlineId, event, actor, reason, evidence) => {
    const entry = { id: 'DA-' + (state.defensibilityAudit.length + 1), deadlineId, event, actor: actor || 'System', at: new Date().toISOString(), reason: reason || '', evidence: evidence || '' };
    state.defensibilityAudit.push(entry);
    bus.emit('audit.logged', entry);
    return entry;
  };

  // ── Deadlines ────────────────────────────────────────────────────────
  const addDeadline = (d) => {
    const id = d.id || 'DL-' + (state.deadlines.length + 100);
    const entry = { id, status: 'upcoming', priority: 'medium', chainParent: null, chainChildren: [], notes: '', ...d };
    state.deadlines.push(entry);
    audit(id, 'created', d.createdBy, d.reason || 'Manual add');
    bus.emit('deadline.added', entry);
    return entry;
  };

  const updateDeadline = (id, patch, reason) => {
    const idx = state.deadlines.findIndex(d => d.id === id);
    if (idx < 0) return null;
    const before = state.deadlines[idx];
    const after  = { ...before, ...patch };
    state.deadlines[idx] = after;
    audit(id, patch.date && patch.date !== before.date ? 'extended' : 'status', patch.updatedBy, reason || '', patch.evidence || '');
    bus.emit('deadline.updated', { id, before, after });
    return after;
  };

  // ── Rule-based cascade engine ───────────────────────────────────────
  const runCascade = ({ matter, matterId, trigger, triggerDate, jurisdiction, ranBy }) => {
    const pack = state.rulePacks.find(p => p.name === jurisdiction) || null;
    const generated = [];
    // Simplified cascade: if trigger is "Discovery Cutoff" → MSJ opp, MIL, pretrial, pretrial brief, trial
    const tpl = {
      'Discovery Cutoff': [
        { offsetDays: 0,   label: 'MSJ opposition',      type: 'brief',  rule: 'FRCP 56(c)' },
        { offsetDays: 18,  label: 'Motions in limine',   type: 'motion', rule: 'Local Rule 56.1' },
        { offsetDays: 19,  label: 'Pretrial conference', type: 'hearing',rule: 'FRCP 16' },
        { offsetDays: 32,  label: 'Pretrial brief',      type: 'brief',  rule: 'Local Rule' },
      ],
      'Trial Date': [
        { offsetDays: -90, label: 'Expert disclosure',   type: 'court-deadline', rule: 'FRCP 26(a)(2)(D)' },
        { offsetDays: -60, label: 'Rebuttal expert',     type: 'court-deadline', rule: 'FRCP 26(a)(2)(D)(ii)' },
        { offsetDays: -30, label: 'Motions in limine',   type: 'motion', rule: 'Local Rule' },
        { offsetDays: -14, label: 'Final pretrial',      type: 'hearing',rule: 'FRCP 16(e)' },
      ],
      'Complaint Filed': [
        { offsetDays: 21, label: 'Answer due',           type: 'response', rule: 'FRCP 12(a)(1)' },
        { offsetDays: 90, label: 'Initial disclosures',  type: 'disclosure', rule: 'FRCP 26(a)(1)' },
      ],
    }[trigger] || [];
    const base = new Date(triggerDate);
    tpl.forEach(t => {
      const d = new Date(base);
      d.setDate(d.getDate() + t.offsetDays);
      generated.push(addDeadline({
        matter, matterId,
        date: d.toISOString().slice(0, 10),
        label: t.label, type: t.type, priority: 'high', status: 'upcoming',
        assignee: ranBy || 'M. Kirkland',
        rule: t.rule,
        createdBy: ranBy || 'Cascade Engine',
        reason: `Cascade from ${trigger}`,
      }));
    });
    const run = { id: 'CAS-' + (state.cascadeRuns.length + 1), matter, trigger, triggerDate, jurisdiction, generated: generated.length, ranAt: new Date().toISOString(), ranBy: ranBy || 'System' };
    state.cascadeRuns.push(run);
    bus.emit('cascade.ran', { run, generated });
    return { run, generated };
  };

  // ── PACER ingest ─────────────────────────────────────────────────────
  const promotePacer = (pcId, deadlinePayload) => {
    const entry = state.pacerEntries.find(p => p.id === pcId);
    if (!entry) return null;
    const dl = addDeadline({ ...deadlinePayload, matter: entry.matter, createdBy: 'PACER sync', reason: 'Docket ingest ' + entry.entry });
    entry.promotedToDeadline = true;
    entry.deadlineId = dl.id;
    bus.emit('pacer.promoted', { entry, deadline: dl });
    return dl;
  };

  const ingestPacer = (id) => {
    const entry = state.pacerEntries.find(p => p.id === id);
    if (entry) { entry.ingested = true; bus.emit('pacer.ingested', entry); }
    return entry;
  };

  // ── Service of process ───────────────────────────────────────────────
  const logService = (sop) => {
    const entry = { id: 'SOP-' + (state.serviceOfProcess.length + 1), status: 'pending', daysLate: 0, answerFiled: null, proof: '', ...sop };
    state.serviceOfProcess.push(entry);
    bus.emit('service.logged', entry);
    return entry;
  };

  // ── Motions ──────────────────────────────────────────────────────────
  const fileMotion = (m) => {
    const entry = { id: 'MO-' + (state.motions.length + 1), status: 'filed', filed: new Date().toISOString().slice(0, 10), ...m };
    state.motions.push(entry);
    bus.emit('motion.filed', entry);
    return entry;
  };

  const setMotionStatus = (id, status, ruling) => {
    const m = state.motions.find(x => x.id === id);
    if (m) { m.status = status; if (ruling) m.ruling = ruling; bus.emit('motion.updated', m); }
    return m;
  };

  // ── Continuances ─────────────────────────────────────────────────────
  const requestContinuance = (c) => {
    const entry = { id: 'CT-' + (state.continuances.length + 1), status: 'pending', ...c };
    state.continuances.push(entry);
    bus.emit('continuance.requested', entry);
    return entry;
  };

  const ruleOnContinuance = (id, status, impact) => {
    const c = state.continuances.find(x => x.id === id);
    if (!c) return null;
    c.status = status; c.impact = impact || c.impact;
    bus.emit('continuance.ruled', c);
    return c;
  };

  // ── Hearing prep ─────────────────────────────────────────────────────
  const updatePrep = (id, prepDone) => {
    const h = state.hearingPrep.find(x => x.id === id);
    if (h) { h.prepDone = prepDone; bus.emit('prep.updated', h); }
    return h;
  };

  // ── Witness availability ─────────────────────────────────────────────
  const scheduleWitness = (id, date) => {
    const w = state.witnessAvail.find(x => x.id === id);
    if (w) { w.scheduled = date; bus.emit('witness.scheduled', w); }
    return w;
  };

  // ── Conflict check ───────────────────────────────────────────────────
  const runConflictCheck = ({ attempt, proposed, attorney }) => {
    const overlaps = state.deadlines.filter(d => d.assignee === attorney && d.date === proposed);
    const severity = overlaps.length ? 'block' : 'info';
    const conflict = overlaps.length ? overlaps.map(d => d.label).join('; ') : 'No conflicts detected';
    const check = { id: 'CC-' + (state.conflictChecks.length + 1), attempt, proposed, attorney, conflict, severity, suggestion: overlaps.length ? 'Move ±3 days' : '', resolved: false };
    state.conflictChecks.push(check);
    bus.emit('conflict.checked', check);
    return check;
  };

  // ── Escalation / reports ─────────────────────────────────────────────
  const sendClientReport = (id) => {
    const r = state.clientReports.find(x => x.id === id);
    if (r) { r.status = 'sent'; r.lastSent = new Date().toISOString().slice(0, 10); bus.emit('report.sent', r); }
    return r;
  };

  const toggleEscalation = (id) => {
    const e = state.escalationRules.find(x => x.id === id);
    if (e) { e.enabled = !e.enabled; bus.emit('escalation.toggled', e); }
    return e;
  };

  // ── Critical path analysis ───────────────────────────────────────────
  const criticalPath = (matterId) => {
    const items = state.deadlines.filter(d => d.matterId === matterId);
    const sorted = items.slice().sort((a, b) => a.date.localeCompare(b.date));
    return sorted.map(d => ({ id: d.id, label: d.label, date: d.date, priority: d.priority, parent: d.chainParent }));
  };

  // ── SOL getters ─────────────────────────────────────────────────────
  const solByStatus = () => {
    const buckets = { Urgent: [], Monitor: [], Safe: [] };
    state.sol.forEach(s => { (buckets[s.status] = buckets[s.status] || []).push(s); });
    return buckets;
  };

  // ── Cross-platform bridges ───────────────────────────────────────────
  window.addEventListener('arbiter:dc.production.shipped', (ev) => {
    const p = ev.detail || {};
    if (p && p.matter) {
      audit(null, 'bridge.discovery.production', 'System', 'Production shipped from Discovery', p.id || '');
    }
  });

  window.addEventListener('arbiter:jx.rulepack.updated', (ev) => {
    const p = ev.detail || {};
    bus.emit('rulepack.external.updated', p);
  });

  window.addEventListener('arbiter:matter.opened', (ev) => {
    bus.emit('matter.focus', ev.detail || {});
  });

  const API = {
    state, bus, audit,
    addDeadline, updateDeadline,
    runCascade,
    ingestPacer, promotePacer,
    logService,
    fileMotion, setMotionStatus,
    requestContinuance, ruleOnContinuance,
    updatePrep,
    scheduleWitness,
    runConflictCheck,
    sendClientReport, toggleEscalation,
    criticalPath, solByStatus,
  };

  window.CalendarStore = API;

  window.useCalStore = (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;
  };
})();
