// PERSONA PLATFORM — Pub/sub store (PnStore) + extended enterprise data.
// Wraps PERSONA_DATA with mutable clone, lifecycle events, cross-platform bridge, and a React hook.
(function () {
  if (!window.PERSONA_DATA) { console.warn('PersonaStore: PERSONA_DATA not loaded'); return; }

  // ── Pub/sub bus ─────────────────────────────────────────────────────────
  const PnBus = {
    _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] || []).slice().forEach(fn => { try { fn(data); } catch (e) { console.error(e); } });
      (this._subs['*']   || []).slice().forEach(fn => { try { fn(topic, data); } catch (e) { console.error(e); } });
      try { window.dispatchEvent(new CustomEvent('arbiter:persona.' + topic, { detail: data })); } catch (e) {}
    },
  };

  // ── Mutable clone of seed data ──────────────────────────────────────────
  const clone = JSON.parse(JSON.stringify(window.PERSONA_DATA));

  const todayISO = () => new Date().toISOString().slice(0, 10);
  const nowStamp = () => new Date().toISOString().slice(0, 16).replace('T', ' ');

  // Saved filter views
  clone.savedViews = [
    { id: 'SV-1', name: 'Critical Defendants',     filter: { type: 'Defendant', risk: 'Critical' }, system: true },
    { id: 'SV-2', name: 'Cooperating Witnesses',   filter: { type: 'Witness',   tagIncludes: 'cooperator' }, system: true },
    { id: 'SV-3', name: 'Opposing Counsel',        filter: { tagIncludes: 'opposing' }, system: true },
    { id: 'SV-4', name: 'Psych-Modeled Subjects',  filter: { psych: true }, system: true },
  ];

  // Consent / privacy record per profile
  clone.consent = clone.people.reduce((acc, p) => {
    const official = p.type === 'Judge' || p.type === 'Agent';
    acc[p.id] = {
      personId: p.id,
      piiScope: official ? 'Public Official' : p.type === 'Attorney' ? 'Counsel-Privileged' : 'Restricted',
      gdprApplicable: false,
      retentionYears: 7,
      lastReview: p.lastUpdated,
      signedRelease: (p.tags || []).some(t => /cooperat/i.test(t)) || (p.roles || []).some(r => /cooperat/i.test(r)),
      privilegeFlags: p.type === 'Attorney' ? ['attorney-client', 'work-product'] : [],
    };
    return acc;
  }, {});

  // Chain-of-custody audit log (seeded with profile creation records)
  clone.auditLog = clone.people.map(p => ({
    id: `AU-${p.id}`,
    personId: p.id,
    action: 'Profile Ingested',
    actor: 'System',
    ts: `${p.lastUpdated} 09:00`,
    detail: `${p.type} profile indexed with risk=${p.risk}`,
  }));

  // Risk trend — 8-point stable synthetic series per profile
  clone.riskTrend = clone.people.reduce((acc, p) => {
    const target = p.risk === 'Critical' ? 88 : p.risk === 'High' ? 68 : p.risk === 'Medium' ? 45 : 22;
    const series = [];
    let v = Math.max(10, target - 22);
    for (let i = 0; i < 7; i++) {
      v += Math.round(Math.sin(i * 0.9 + p.id.charCodeAt(3)) * 6) + Math.round((target - v) * 0.18);
      series.push(Math.max(5, Math.min(100, Math.round(v))));
    }
    series.push(target);
    acc[p.id] = series;
    return acc;
  }, {});

  // Conflict-of-interest / ethical wall flags
  const hasOpposing = (p) =>
    (p.tags || []).some(t => /opposing/i.test(t)) ||
    (p.roles || []).some(r => /opposing/i.test(r));
  clone.conflicts = [];
  clone.people.filter(hasOpposing).forEach(op => {
    const opMatters = new Set(op.matters);
    clone.people.forEach(other => {
      if (other.id === op.id) return;
      const shared = other.matters.filter(m => opMatters.has(m));
      if (shared.length && (other.type === 'Defendant' || other.type === 'Witness')) {
        clone.conflicts.push({
          id: `COI-${op.id}-${other.id}`,
          severity: other.type === 'Defendant' ? 'High' : 'Medium',
          category: 'Matter Overlap',
          summary: `${op.name} (opposing counsel) shares matter ${shared.join(', ')} with ${other.name} (${other.type})`,
          personIds: [op.id, other.id],
          matters: shared,
          status: 'Active',
          loggedAt: todayISO(),
        });
      }
    });
  });
  // Add detainee-witness adjacency flag
  clone.people.filter(p => p.status === 'Detained').forEach(d => {
    const adjacent = clone.associations.filter(a => a.source === d.id || a.target === d.id);
    adjacent.forEach(a => {
      const otherId = a.source === d.id ? a.target : a.source;
      const other = clone.people.find(x => x.id === otherId);
      if (other && other.type === 'Witness') {
        clone.conflicts.push({
          id: `COI-DET-${d.id}-${other.id}`,
          severity: 'Critical',
          category: 'Witness Tampering Risk',
          summary: `Detained subject ${d.name} has direct association with witness ${other.name}`,
          personIds: [d.id, other.id],
          matters: d.matters,
          status: 'Active',
          loggedAt: todayISO(),
        });
      }
    });
  });

  // Cohorts
  clone.cohorts = [
    { id: 'CH-1', name: 'High-Neuroticism Defendants', tag: 'high-neuroticism',
      members: clone.people.filter(p => p.psych && p.type === 'Defendant' && p.psych.ocean.n >= 60).map(p => p.id) },
    { id: 'CH-2', name: 'Low-Conscientiousness Risk',  tag: 'low-conscientiousness',
      members: clone.people.filter(p => p.psych && p.psych.ocean.c <= 35).map(p => p.id) },
    { id: 'CH-3', name: 'Detained Subjects',            tag: 'detained',
      members: clone.people.filter(p => p.status === 'Detained').map(p => p.id) },
    { id: 'CH-4', name: 'Cooperating Subjects',         tag: 'cooperator',
      members: clone.people.filter(p =>
        (p.tags || []).some(t => /cooperat/i.test(t)) ||
        (p.roles || []).some(r => /cooperat/i.test(r))
      ).map(p => p.id) },
  ];

  // Witness-prep playbook templates (consumed by prep checklist generator)
  clone.prepTemplates = {
    'sunk-cost':    ['Frame questions to avoid triggering escalation of commitment', 'Anchor to fresh evidence, not prior statements'],
    'loss-aversion':['Open with what subject retains if cooperative', 'Avoid framing that emphasizes losses'],
    'conflict-avoidance': ['Use empathetic opening, build rapport first', 'Defer confrontation questions to middle of session'],
    'anchoring':    ['Ask open-ended questions before any numeric priming', 'Rotate counsel/interviewer to break anchor'],
    'pride':        ['Acknowledge subject expertise early', 'Avoid questioning domain credentials'],
    'confirmation-bias': ['Present disconfirming evidence in ordered sequence', 'Use hypothetical reframes'],
    '_default':     ['Establish rapport in first 10 minutes', 'Record baseline speech cadence before substantive questions'],
  };

  // ── Store API ───────────────────────────────────────────────────────────
  const PnStore = {
    data: clone,
    bus: PnBus,

    recomputeKpis() {
      const d = this.data;
      d.kpis.total         = d.people.length;
      d.kpis.psychAssessed = d.people.filter(p => p.psych).length;
      d.kpis.defendants    = d.people.filter(p => p.type === 'Defendant').length;
      d.kpis.witnesses     = d.people.filter(p => p.type === 'Witness').length;
      d.kpis.highRisk      = d.people.filter(p => p.risk === 'Critical' || p.risk === 'High').length;
      d.kpis.judges        = d.people.filter(p => p.type === 'Judge').length;
      d.kpis.agents        = d.people.filter(p => p.type === 'Agent').length;
    },

    _audit(personId, action, detail, actor = 'J. Saadein') {
      this.data.auditLog.unshift({
        id: `AU-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
        personId, action, actor, detail, ts: nowStamp(),
      });
    },

    // Profile CRUD ---------------------------------------------------------
    createProfile({ name, type, risk = 'Medium', organization = '', title = '', notes = '', matters = [], tags = [] }) {
      const idx = this.data.people.length + 1;
      const id = `PE-${String(idx).padStart(3, '0')}`;
      const person = {
        id, name, type, status: 'Active', risk,
        organization, title, notes,
        matters: matters.length ? matters : ['Unassigned'],
        tags,
        aliases: [], roles: [type.toLowerCase()], counsel: [],
        dob: '', lastUpdated: todayISO(), psych: null,
      };
      this.data.people.push(person);
      this.data.consent[id] = {
        personId: id, piiScope: 'Restricted', gdprApplicable: false, retentionYears: 7,
        lastReview: todayISO(), signedRelease: false, privilegeFlags: [],
      };
      const target = risk === 'Critical' ? 88 : risk === 'High' ? 68 : risk === 'Medium' ? 45 : 22;
      this.data.riskTrend[id] = [target - 15, target - 10, target - 12, target - 6, target - 8, target - 3, target - 4, target];
      this._audit(id, 'Profile Created', `New ${type} profile "${name}" ingested`);
      this.recomputeKpis();
      PnBus.emit('profile.created', { person });
      return person;
    },

    updatePerson(id, patch) {
      const p = this.data.people.find(x => x.id === id);
      if (!p) return null;
      Object.assign(p, patch);
      p.lastUpdated = todayISO();
      this._audit(id, 'Profile Updated', `Fields: ${Object.keys(patch).join(', ')}`);
      this.recomputeKpis();
      PnBus.emit('profile.updated', { person: p });
      return p;
    },

    // Psych assessment -----------------------------------------------------
    logAssessment(personId, { assessedBy, ocean, vulnerabilities = [], biases = [], deception = [], interrogation = '' }) {
      const p = this.data.people.find(x => x.id === personId);
      if (!p) return null;
      p.psych = { assessedBy, assessedDate: todayISO(), ocean, vulnerabilities, biases, deception, interrogation };
      p.lastUpdated = todayISO();
      this._audit(personId, 'Psych Assessment Logged', `Big Five assessed by ${assessedBy}`);
      this.recomputeKpis();
      PnBus.emit('psych.assessed', { person: p });
      return p;
    },

    // CRM touchpoints ------------------------------------------------------
    logTouchpoint({ personId, channel, direction = 'outbound', subject, note = '', actor = 'J. Saadein' }) {
      const row = { id: `COMM-${Date.now()}`, personId, channel, direction, subject, note, actor, ts: nowStamp() };
      this.data.crmComms.unshift(row);
      const rec = this.data.crm[personId];
      if (rec) { rec.engagement = Math.min(100, (rec.engagement || 0) + 5); rec.lastTouch = row.ts; }
      this._audit(personId, 'Touchpoint Logged', `${channel}: ${subject}`);
      PnBus.emit('touchpoint.logged', { row });
      return row;
    },

    // CRM tasks ------------------------------------------------------------
    createTask({ personId, title, due, priority = 'Normal', assignee = 'J. Saadein' }) {
      const row = { id: `TA-${Date.now()}`, personId, title, due, priority, assignee, status: 'Open', created: todayISO() };
      this.data.crmTasks.unshift(row);
      this._audit(personId, 'Task Created', title);
      PnBus.emit('task.created', { row });
      return row;
    },
    completeTask(taskId) {
      const t = this.data.crmTasks.find(x => x.id === taskId);
      if (!t) return null;
      t.status = 'Completed'; t.completedAt = todayISO();
      this._audit(t.personId, 'Task Completed', t.title);
      PnBus.emit('task.updated', { row: t });
      return t;
    },

    // Saved views ----------------------------------------------------------
    saveView(name, filter) {
      const v = { id: `SV-${Date.now()}`, name, filter, system: false };
      this.data.savedViews.push(v);
      PnBus.emit('view.saved', v);
      return v;
    },
    deleteView(id) {
      const idx = this.data.savedViews.findIndex(v => v.id === id && !v.system);
      if (idx < 0) return;
      this.data.savedViews.splice(idx, 1);
      PnBus.emit('view.deleted', { id });
    },

    // Bulk tagging ---------------------------------------------------------
    bulkTag(personIds, tag) {
      personIds.forEach(id => {
        const p = this.data.people.find(x => x.id === id);
        if (p && !p.tags.includes(tag)) { p.tags.push(tag); this._audit(id, 'Tag Applied', `#${tag}`); }
      });
      PnBus.emit('bulk.tagged', { personIds, tag });
    },

    // Engagement decay -----------------------------------------------------
    decayEngagement() {
      const now = Date.now();
      Object.values(this.data.crm).forEach(c => {
        if (!c.lastTouch) return;
        const age = (now - new Date(c.lastTouch).getTime()) / (1000 * 60 * 60 * 24);
        const penalty = Math.max(0, Math.floor(age / 7));
        c.engagement = Math.max(0, (c.engagement || 0) - penalty);
      });
      PnBus.emit('engagement.decayed', {});
    },

    // Influence centrality (degree + 1-hop propagation) --------------------
    influenceScores() {
      const d = this.data;
      const deg = {}; d.people.forEach(p => deg[p.id] = 0);
      d.associations.forEach(a => { deg[a.source] = (deg[a.source] || 0) + 1; deg[a.target] = (deg[a.target] || 0) + 1; });
      const score = { ...deg };
      d.associations.forEach(a => { score[a.source] += deg[a.target] * 0.5; score[a.target] += deg[a.source] * 0.5; });
      return d.people.map(p => ({ person: p, degree: deg[p.id], influence: Math.round(score[p.id] * 10) / 10 }))
        .sort((a, b) => b.influence - a.influence);
    },

    // Witness-prep checklist generator -------------------------------------
    prepChecklist(personId) {
      const p = this.data.people.find(x => x.id === personId);
      if (!p || !p.psych) return null;
      const items = [];
      const addItems = (key) => {
        const tpl = this.data.prepTemplates[key] || [];
        tpl.forEach(t => items.push({ source: key, text: t }));
      };
      (p.psych.biases || []).forEach(b => addItems(b.toLowerCase().replace(/\s+/g, '-')));
      (p.psych.vulnerabilities || []).forEach(v => addItems(v.toLowerCase().replace(/\s+/g, '-')));
      addItems('_default');
      if (p.psych.ocean.n >= 70) items.push({ source: 'neuroticism', text: 'Schedule session before 11am — stress reactivity peaks later in day' });
      if (p.psych.ocean.a <= 30) items.push({ source: 'agreeableness', text: 'Avoid direct challenge in first 20 minutes — subject is confrontation-prone' });
      if (p.psych.ocean.e <= 30) items.push({ source: 'extraversion', text: 'Allow long pauses — subject processes internally' });
      this._audit(personId, 'Prep Checklist Generated', `${items.length} preparation items`);
      return items;
    },

    // Court-admissible dossier export --------------------------------------
    exportDossier(personId) {
      const p = this.data.people.find(x => x.id === personId);
      if (!p) return null;
      const pkg = {
        generatedAt: new Date().toISOString(),
        generatedBy: 'J. Saadein',
        profile: p,
        psych: p.psych || null,
        associations: this.data.associations.filter(a => a.source === p.id || a.target === p.id),
        documents: this.data.documents.filter(d => d.personId === p.id),
        auditChain: this.data.auditLog.filter(l => l.personId === p.id),
        consent: this.data.consent[p.id] || null,
        conflicts: this.data.conflicts.filter(c => c.personIds.includes(p.id)),
        citations: p.psych
          ? ['Goldberg L.R. (1993) — Big Five structure of personality', 'Fisher & Geiselman (1992) — Cognitive Interview Technique', 'FRE 702 — Testimony by expert witnesses']
          : ['FRE 401 — Relevance'],
      };
      this._audit(personId, 'Dossier Exported', 'Court-admissible package generated');
      PnBus.emit('dossier.exported', { personId, pkg });
      return pkg;
    },

    // COI resolution -------------------------------------------------------
    resolveConflict(id, resolution = 'Reviewed — ethical wall in place') {
      const c = this.data.conflicts.find(x => x.id === id);
      if (!c) return;
      c.status = 'Resolved'; c.resolution = resolution; c.resolvedAt = todayISO();
      PnBus.emit('conflict.resolved', { conflict: c });
    },
  };

  // ── Cross-platform bridge ───────────────────────────────────────────────
  // SignDesk envelope completed → auto-log eSignature touchpoint on matched person
  window.addEventListener('arbiter:signdesk.envelope.completed', (ev) => {
    const env = ev && ev.detail && (ev.detail.envelope || ev.detail);
    if (!env) return;
    const signers = env.signers || env.recipients || [];
    signers.forEach(s => {
      const nm = (s.name || s.fullName || '').trim();
      if (!nm) return;
      const match = PnStore.data.people.find(p => p.name === nm || (p.aliases || []).includes(nm));
      if (match) {
        PnStore.logTouchpoint({
          personId: match.id,
          channel: 'eSignature',
          direction: 'inbound',
          subject: `Signed: ${env.title || env.subject || env.id}`,
          note: `SignDesk envelope ${env.id || '—'} completed`,
          actor: 'SignDesk',
        });
      }
    });
  });

  // Doc platform review → audit trail entry on any person linked to the doc's matter
  window.addEventListener('arbiter:doc.reviewed', (ev) => {
    const doc = ev && ev.detail && (ev.detail.doc || ev.detail);
    if (!doc) return;
    const matterIds = doc.matters || (doc.matter ? [doc.matter] : []);
    if (!matterIds.length) return;
    PnStore.data.people.forEach(p => {
      if (p.matters.some(m => matterIds.includes(m))) {
        PnStore._audit(p.id, 'Document Reviewed', `${doc.title || doc.id} reviewed (Doc platform)`);
      }
    });
    PnBus.emit('doc.referenced', { doc });
  });

  // ── React hook ──────────────────────────────────────────────────────────
  function usePnStore(topics) {
    const [, force] = React.useReducer(x => x + 1, 0);
    React.useEffect(() => {
      const list = topics && topics.length ? topics : ['*'];
      const unsubs = list.map(t => PnBus.on(t, () => force()));
      return () => unsubs.forEach(u => u());
    }, []);
    return PnStore.data;
  }

  PnStore.recomputeKpis();
  window.__pnBus = PnBus;
  window.PnStore = PnStore;
  window.usePnStore = usePnStore;
})();
