(function (global) {
  var MODES = [
    { id: 'neo-bars', label: 'Neo staafdiagram' },
    { id: 'neo-rings', label: 'Neo ringen' },
    { id: 'neo-equalizer', label: 'Neo equalizer' },
    { id: 'neo-cards', label: 'Neo kaarten' },
    { id: 'neo-table', label: 'Neo tabel' },
  ];

  var charts = {};

  function destroy(key) {
    if (charts[key]) {
      charts[key].destroy();
      charts[key] = null;
    }
  }

  function colors() {
    return {
      gold: 'rgba(252, 211, 77, 0.9)', cyan: 'rgba(56, 189, 248, 0.9)',
      green: 'rgba(74, 222, 128, 0.9)', red: 'rgba(251, 113, 133, 0.9)',
      purple: 'rgba(168, 85, 247, 0.9)', gray: 'rgba(159, 176, 196, 0.85)',
      grid: 'rgba(159, 176, 196, 0.15)', text: '#c8d4e0',
    };
  }

  function eqBars(counts, cls) {
    var max = Math.max.apply(null, counts.concat([1]));
    return '<div class="hm-eq viz-eq ' + (cls || '') + '">' +
      counts.map(function (v) {
        var h = Math.max(18, Math.round((v / max) * 92));
        return '<span style="height:' + h + '%"></span>';
      }).join('') + '</div>';
  }

  function findPanel(canvas, alt) {
    var el = (canvas && canvas.closest('.page-viz-panel')) || (alt && alt.closest('.page-viz-panel'));
    return el || null;
  }

  function applyPanelLayout(canvas, alt, mode) {
    var panel = findPanel(canvas, alt);
    if (!panel) return;
    var isCanvas = mode === 'neo-bars' || mode === 'neo-rings';
    panel.classList.toggle('viz-mode-chart', isCanvas);
    panel.classList.toggle('viz-mode-alt', !isCanvas);
    panel.classList.toggle('viz-mode-rings', mode === 'neo-rings');
  }

  function useHorizontal(labels, opts) {
    if (opts && opts.horizontal !== undefined) return opts.horizontal;
    return (labels || []).length >= 6;
  }

  function renderBars(canvas, labels, values, opts) {
    if (!canvas || typeof Chart === 'undefined') return;
    opts = opts || { key: 'chart' };
    var c = colors();
    var horiz = useHorizontal(labels, opts);
    destroy(opts.key);
    charts[opts.key] = new Chart(canvas, {
      type: 'bar',
      data: {
        labels: labels,
        datasets: [{ data: values, backgroundColor: opts.color || c.cyan, borderRadius: 6, barThickness: horiz ? 'flex' : undefined, maxBarThickness: horiz ? 28 : 48 }],
      },
      options: {
        indexAxis: horiz ? 'y' : 'x',
        responsive: true,
        maintainAspectRatio: false,
        layout: { padding: { top: 4, right: 8, bottom: 4, left: 4 } },
        plugins: { legend: { display: false }, title: { display: !!opts.title, text: opts.title, color: c.text, padding: { bottom: 8 } } },
        scales: {
          y: horiz
            ? { ticks: { color: c.text, autoSkip: false, font: { size: 11 } }, grid: { color: c.grid } }
            : { ticks: { color: c.text }, grid: { color: c.grid }, beginAtZero: true },
          x: horiz
            ? { ticks: { color: c.text }, grid: { display: false }, beginAtZero: true }
            : { ticks: { color: c.text, maxRotation: 45, minRotation: 0, autoSkip: false, font: { size: 10 } }, grid: { display: false } },
        },
      },
    });
    requestAnimationFrame(function () {
      if (charts[opts.key]) charts[opts.key].resize();
    });
  }

  function renderRings(canvas, labels, values, key, title) {
    if (!canvas || typeof Chart === 'undefined') return;
    var c = colors();
    destroy(key);
    charts[key] = new Chart(canvas, {
      type: 'doughnut',
      data: {
        labels: labels,
        datasets: [{ data: values, backgroundColor: [c.green, c.gray, c.red, c.gold, c.cyan, c.purple], borderWidth: 0 }],
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        cutout: '62%',
        layout: { padding: 4 },
        plugins: {
          legend: { position: 'bottom', labels: { color: c.text, boxWidth: 10, padding: 8, font: { size: 10 } } },
          title: { display: !!title, text: title, color: c.text, font: { size: 11 } },
        },
      },
    });
    requestAnimationFrame(function () {
      if (charts[key]) charts[key].resize();
    });
  }

  function renderCards(container, rows) {
    if (!container) return;
    container.innerHTML = '<div class="viz-cards">' + rows.map(function (r) {
      return '<div class="viz-card"><span class="viz-card-label">' + r.label + '</span><strong class="viz-card-val">' + r.value + '</strong></div>';
    }).join('') + '</div>';
  }

  function renderTable(container, rows) {
    if (!container) return;
    container.innerHTML = '<table class="data-table viz-table"><thead><tr><th>Item</th><th>Waarde</th></tr></thead><tbody>' +
      rows.map(function (r) { return '<tr><td>' + r.label + '</td><td>' + r.value + '</td></tr>'; }).join('') +
      '</tbody></table>';
  }

  function renderEqualizer(container, rows, cls) {
    if (!container) return;
    container.innerHTML = rows.map(function (r) {
      return '<div class="viz-eq-row"><span>' + r.label + '</span><strong>' + r.value + '</strong></div>';
    }).join('') + eqBars(rows.map(function (r) { return Number(r.raw) || 0; }), cls);
  }

  function renderWidget(mode, spec) {
    var canvas = spec.canvas;
    var alt = spec.altContainer;
    applyPanelLayout(canvas, alt, mode);
    if (mode === 'neo-bars' && canvas) {
      if (alt) alt.innerHTML = '';
      canvas.style.display = '';
      renderBars(canvas, spec.labels, spec.values, spec.chartOpts || { key: spec.key });
      return;
    }
    if (mode === 'neo-rings' && canvas) {
      if (alt) alt.innerHTML = '';
      canvas.style.display = '';
      renderRings(canvas, spec.labels, spec.values, spec.key, spec.title);
      return;
    }
    if (canvas) canvas.style.display = 'none';
    if (!alt) return;
    if (mode === 'neo-equalizer') renderEqualizer(alt, spec.rows, spec.eqClass);
    else if (mode === 'neo-cards') renderCards(alt, spec.rows);
    else if (mode === 'neo-table') renderTable(alt, spec.rows);
    else {
      if (canvas) { canvas.style.display = ''; renderBars(canvas, spec.labels, spec.values, spec.chartOpts || { key: spec.key }); }
    }
  }

  global.VizEngine = {
    MODES: MODES,
    renderWidget: renderWidget,
    destroyAll: function () { Object.keys(charts).forEach(destroy); },
    renderSentiment: function (mode, canvas, alt, stats, widgetMode) {
      var m = widgetMode || mode;
      var files = stats.nas_files || [];
      var counts = { positive: 0, neutral: 0, negative: 0 };
      files.forEach(function (f) {
        var s = (f.sentiment_label || 'neutral').toLowerCase();
        if (counts[s] !== undefined) counts[s]++;
      });
      if (!files.length) counts.neutral = 1;
      renderWidget(m, {
        canvas: canvas, altContainer: alt, key: 'sentiment',
        labels: ['Positief', 'Neutraal', 'Negatief'],
        values: [counts.positive, counts.neutral, counts.negative],
        title: 'NAS sentiment',
        rows: [
          { label: 'Positief', value: counts.positive, raw: counts.positive },
          { label: 'Neutraal', value: counts.neutral, raw: counts.neutral },
          { label: 'Negatief', value: counts.negative, raw: counts.negative },
        ],
        eqClass: 'hm-eq-purple',
      });
    },
    renderAgents: function (mode, canvas, alt, stats, widgetMode) {
      var m = widgetMode || mode;
      var map = {};
      (stats.recent_events || []).forEach(function (e) {
        var a = e.agent_name || 'other';
        map[a] = (map[a] || 0) + 1;
      });
      var labels = Object.keys(map);
      var values = labels.map(function (k) { return map[k]; });
      if (!labels.length) { labels = ['geen']; values = [0]; }
      renderWidget(m, {
        canvas: canvas, altContainer: alt, key: 'agents',
        labels: labels, values: values, title: 'Agent activiteit',
        chartOpts: { key: 'agents', color: colors().gold },
        rows: labels.map(function (l, i) { return { label: l, value: values[i], raw: values[i] }; }),
        eqClass: 'hm-eq-lime',
      });
    },
    renderFromRows: function (mode, canvas, alt, key, title, rows, eqClass, chartColor) {
      var labels = rows.map(function (r) { return r.label; });
      var values = rows.map(function (r) { return Number(r.raw) || 0; });
      renderWidget(mode, {
        canvas: canvas, altContainer: alt, key: key,
        labels: labels, values: values, title: title,
        chartOpts: { key: key, color: chartColor || colors().cyan },
        rows: rows,
        eqClass: eqClass || 'hm-eq-cyan',
      });
    },
  };
})(window);
