/**
 * Hermes Neo Command Center
 */
function hermesControl() {
  const PA_SITES = ['Airbnb', 'Booking.com', 'DuckDuckGo', 'HolidayCheck'];

  /** Canonical team — never duplicate role as name */
  const ROSTER = [
    { chat_id: 8859782446, role: 'CEO', name: 'Aïssa' },
    { chat_id: 789036463, role: 'CTO', name: 'Mo' },
  ];

  return {
    tab: 'feed',
    live: true,
    stats: { conversations: 0, messages: 0, edges: 0, embeddings: 0, inbound: 0, outbound: 0 },
    conversations: [],
    messages: [],
    users: [],
    agentEvents: [],
    selectedChatId: null,
    graphChatFilter: '',
    searchQuery: '',
    searchResults: [],
    searchRan: false,
    graphNetwork: null,
    pollTimer: null,
    paPollTimer: null,
    paPolling: false,
    paLive: { status: 'idle', query: '', slots: [] },
    paScreenshotTs: Date.now(),
    hermesOnline: false,
    hermesStatus: {},
    actionBusy: false,
    actionMsg: '',
    chartDirection: null,
    chartAgents: null,

    get teamRoster() {
      const byId = {};
      (this.users || []).forEach(u => { byId[u.chat_id] = u; });
      (this.conversations || []).forEach(c => {
        if (!byId[c.chat_id]) byId[c.chat_id] = c;
        else {
          byId[c.chat_id].message_count = c.message_count || byId[c.chat_id].message_count;
        }
      });
      return ROSTER.map(r => ({
        ...r,
        online: !!(byId[r.chat_id]?.online),
        pa_mode: !!(byId[r.chat_id]?.pa_mode),
        message_count: byId[r.chat_id]?.message_count || 0,
      }));
    },

    get paLiveUser() {
      const cid = this.paLive.chat_id;
      if (!cid) return '';
      const m = ROSTER.find(r => r.chat_id === cid);
      return m ? `${m.role} — ${m.name}` : this.paLive.user_name || '';
    },

    get paSlots() {
      const slots = this.paLive.slots || [];
      if (slots.length >= 4) return slots;
      const byLabel = {};
      slots.forEach(s => { byLabel[s.label] = s; });
      return PA_SITES.map(label => byLabel[label] || {
        label, status: 'idle', has_screenshot: false,
      });
    },

    rosterPerson(chatId) {
      return ROSTER.find(r => r.chat_id === Number(chatId)) || null;
    },

    msgLabel(msg) {
      const p = this.rosterPerson(msg.chat_id);
      if (p) return `${p.role} (${p.name})`;
      if (msg.user_role && msg.user_name) return `${msg.user_role} (${msg.user_name})`;
      return msg.user_role || msg.chat_id || '?';
    },

    async init() {
      const hash = (window.location.hash || '').replace('#', '');
      if (['feed', 'pa', 'graph', 'search', 'control'].includes(hash)) this.tab = hash;
      await this.refreshStats();
      await this.refreshConversations();
      await this.refreshUsers();
      await this.refreshFeed();
      await this.refreshPaLive();
      setTimeout(() => this.initCharts(), 200);
      this.pollTimer = setInterval(() => {
        if (this.tab === 'feed' && this.live) this.refreshFeed(true);
      }, 5000);
      this.paPollTimer = setInterval(() => {
        if (this.tab === 'pa' || this.paLive.status === 'running') this.refreshPaLive(true);
      }, 2000);
      window.addEventListener('hashchange', () => {
        const h = (window.location.hash || '').replace('#', '');
        if (['feed', 'pa', 'graph', 'search', 'control'].includes(h)) this.tab = h;
      });
    },

    initCharts() {
      if (typeof Chart === 'undefined') return;
      const neoColors = ['#00e5ff', '#ff2d95', '#b8ff3c', '#ff9f43', '#a855f7', '#ffd700'];
      Chart.defaults.color = '#64748b';
      Chart.defaults.borderColor = 'rgba(0,229,255,0.08)';

      const dirEl = document.getElementById('hm-chart-direction');
      if (dirEl && !this.chartDirection) {
        this.chartDirection = new Chart(dirEl, {
          type: 'doughnut',
          data: {
            labels: ['Inbound', 'Outbound', 'Vectors'],
            datasets: [{
              data: [1, 1, 1],
              backgroundColor: ['#00e5ff', '#a855f7', '#b8ff3c'],
              borderWidth: 0,
              hoverOffset: 8,
            }],
          },
          options: {
            responsive: true,
            maintainAspectRatio: false,
            cutout: '62%',
            plugins: {
              legend: { position: 'right', labels: { boxWidth: 12, padding: 10, color: '#94a3b8' } },
            },
          },
        });
      }

      const agEl = document.getElementById('hm-chart-agents');
      if (agEl && !this.chartAgents) {
        this.chartAgents = new Chart(agEl, {
          type: 'bar',
          data: {
            labels: ['herman', 'browser', 'marketing'],
            datasets: [{
              label: 'events',
              data: [0, 0, 0],
              backgroundColor: 'rgba(0, 229, 255, 0.55)',
              borderColor: '#00e5ff',
              borderWidth: 1,
              borderRadius: 4,
            }],
          },
          options: {
            responsive: true,
            maintainAspectRatio: false,
            scales: {
              y: { beginAtZero: true, grid: { color: 'rgba(255,255,255,0.04)' }, ticks: { stepSize: 1 } },
              x: { grid: { display: false } },
            },
            plugins: { legend: { display: false } },
          },
        });
      }
      this.updateCharts();
    },

    updateCharts() {
      const s = this.stats;
      if (this.chartDirection) {
        this.chartDirection.data.datasets[0].data = [
          Math.max(s.inbound || 0, 0),
          Math.max(s.outbound || 0, 0),
          Math.max(s.embeddings || 0, 0),
        ];
        this.chartDirection.update('none');
      }
      if (this.chartAgents) {
        const counts = {};
        (this.agentEvents || []).forEach(ev => {
          const n = (ev.agent_name || 'other').toLowerCase();
          counts[n] = (counts[n] || 0) + 1;
        });
        const labels = Object.keys(counts).slice(0, 8);
        if (!labels.length) labels.push('herman');
        this.chartAgents.data.labels = labels;
        this.chartAgents.data.datasets[0].data = labels.map(l => counts[l] || 0);
        this.chartAgents.update('none');
      }
    },

    setTab(t) {
      this.tab = t;
      history.replaceState(null, '', t === 'feed' ? '/hermes' : '/hermes#' + t);
      if (t === 'graph') setTimeout(() => this.loadGraph(), 100);
      if (t === 'control') { this.refreshStats(); this.refreshUsers(); }
      if (t === 'pa') { this.paPolling = true; this.refreshPaLive(); }
    },

    formatTime(iso) {
      if (!iso) return '';
      try {
        return new Date(iso).toLocaleString('nl-NL', { dateStyle: 'short', timeStyle: 'short' });
      } catch { return iso; }
    },

    paStatusLabel() {
      const m = { idle: 'Idle', running: 'Zoekt…', comparing: 'Vergelijkt…', done: 'Klaar', failed: 'Mislukt' };
      return m[this.paLive.status] || this.paLive.status || 'Idle';
    },

    slotStatusLabel(s) {
      const m = { idle: 'Idle', waiting: 'Wacht', loading: 'Bezig', completed: 'Klaar', failed: 'Fout' };
      return m[s] || s || 'Idle';
    },

    slotScreenshotUrl(label) {
      if (!label) return '';
      return `/api/admin/hermes/pa/live/${encodeURIComponent(label)}/screenshot.jpg?t=${this.paScreenshotTs}`;
    },

    async selectChat(chatId) {
      this.selectedChatId = chatId;
      await this.refreshFeed();
    },

    async refreshStats() {
      try {
        const data = await Cockpit.api('/hermes/stats');
        this.stats = data.stats || this.stats;
        this.agentEvents = data.agent_events || [];
        this.updateCharts();
      } catch (e) { console.warn('stats', e); }
    },

    async refreshUsers() {
      try {
        const data = await Cockpit.api('/hermes/users');
        this.users = data.users || [];
      } catch (e) { console.warn('users', e); }
    },

    async refreshConversations() {
      try {
        const data = await Cockpit.api('/hermes/conversations');
        this.conversations = data.items || [];
      } catch (e) { console.warn('conversations', e); }
    },

    async refreshFeed(quiet) {
      try {
        let path = '/hermes/feed?limit=80';
        if (this.selectedChatId) path += '&chat_id=' + this.selectedChatId;
        const data = await Cockpit.api(path);
        this.messages = data.items || [];
        if (!quiet) await this.refreshStats();
      } catch (e) { console.warn('feed', e); }
    },

    async refreshPaLive(quiet) {
      try {
        const data = await Cockpit.api('/hermes/pa/live');
        this.paLive = data;
        this.paScreenshotTs = Date.now();
        if (data.hermes) {
          this.hermesOnline = data.hermes.online !== false;
          this.hermesStatus = data.hermes;
        }
      } catch (e) {
        if (!quiet) console.warn('pa live', e);
      }
    },

    async loadGraph() {
      try {
        let data;
        if (this.graphChatFilter) {
          data = await Cockpit.api('/hermes/graph/' + this.graphChatFilter + '?limit=80');
        } else {
          data = await Cockpit.api('/hermes/graph?limit=100');
        }
        this.renderGraph(data);
      } catch (e) {
        Cockpit.toast('Graph laden mislukt: ' + e.message, 'error');
      }
    },

    renderGraph(data) {
      const el = document.getElementById('hermes-graph');
      if (!el || typeof vis === 'undefined') return;
      const nodes = new vis.DataSet((data.nodes || []).map(n => ({
        id: n.id,
        label: this.truncate(n.label || n.id, 40),
        color: n.direction === 'in'
          ? { background: '#164e63', border: '#00e5ff' }
          : { background: '#4c1d95', border: '#a855f7' },
        font: { color: '#e8edf5', size: 11 },
      })));
      const edges = new vis.DataSet((data.edges || []).map(e => ({
        id: 'e' + e.id, from: e.from, to: e.to,
        label: e.type || '', arrows: 'to',
        color: { color: '#ff9f43' },
      })).filter(e => e.to));
      if (this.graphNetwork) this.graphNetwork.destroy();
      this.graphNetwork = new vis.Network(el, { nodes, edges }, {
        physics: { stabilization: true },
        interaction: { hover: true },
      });
    },

    truncate(s, n) {
      s = String(s || '');
      return s.length > n ? s.slice(0, n) + '…' : s;
    },

    async runSearch() {
      if (!this.searchQuery || this.searchQuery.length < 2) {
        Cockpit.toast('Minimaal 2 tekens', 'warn');
        return;
      }
      this.searchRan = true;
      try {
        const data = await Cockpit.api('/hermes/search', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ query: this.searchQuery, chat_id: this.selectedChatId || null, limit: 15 }),
        });
        this.searchResults = data.results || [];
      } catch (e) {
        Cockpit.toast('Zoeken mislukt: ' + e.message, 'error');
      }
    },

    async runAction(action) {
      this.actionBusy = true;
      this.actionMsg = '';
      try {
        const data = await Cockpit.api('/hermes/actions/' + action, { method: 'POST' });
        this.actionMsg = data.output || '✅ Actie uitgevoerd';
        Cockpit.toast(this.actionMsg.slice(0, 80), 'success');
        await this.refreshStats();
      } catch (e) {
        this.actionMsg = '❌ ' + e.message;
        Cockpit.toast(this.actionMsg, 'error');
      } finally {
        this.actionBusy = false;
      }
    },
  };
}
