window.BriefingCharts = (function () {
  var charts = {};
  var typewriterTimer = null;

  function destroyAll() {
    Object.keys(charts).forEach(function (k) {
      if (charts[k]) { charts[k].destroy(); charts[k] = null; }
    });
  }

  function parseContent(content) {
    var parts = (content || '').split(/\n---\n/);
    var ai = parts[0] || '';
    var summary = '', actions = [], longTerm = [];
    var sm = ai.match(/##\s*Samenvatting\s*\n([\s\S]*?)(?=##\s*Actiepunten|##\s*Lange termijn|$)/i);
    if (sm) summary = sm[1].trim().replace(/\*\*/g, '');
    var am = ai.match(/##\s*Actiepunten[^\n]*\n([\s\S]*?)(?=##\s*Lange termijn|$)/i);
    if (am) actions = am[1].split('\n').map(function (l) { return l.replace(/^[-*]\s*/, '').trim(); }).filter(Boolean);
    var lm = ai.match(/##\s*Lange termijn[^\n]*\n([\s\S]*)/i);
    if (lm) longTerm = lm[1].split('\n').map(function (l) { return l.replace(/^[-*]\s*/, '').trim(); }).filter(Boolean);
    if (!summary && ai.trim()) summary = ai.trim().slice(0, 800).replace(/\*\*/g, '');
    return { summary: summary, actions: actions, longTerm: longTerm };
  }

  function typewriter(el, text, speed) {
    if (!el) return;
    if (typewriterTimer) clearInterval(typewriterTimer);
    el.textContent = '';
    if (!text) { el.textContent = 'Klik «Genereer dagrapport» voor je persoonlijke Herman briefing.'; return; }
    var i = 0;
    typewriterTimer = setInterval(function () {
      if (i < text.length) { el.textContent += text.charAt(i); i++; }
      else clearInterval(typewriterTimer);
    }, speed || 8);
  }

  function countUp(el, end, prefix, suffix) {
    if (!el) return;
    prefix = prefix || ''; suffix = suffix || '';
    var start = 0, dur = 600, t0 = performance.now();
    function step(t) {
      var p = Math.min(1, (t - t0) / dur);
      var v = Math.round(start + (end - start) * p);
      el.textContent = prefix + v.toLocaleString('nl-NL') + suffix;
      if (p < 1) requestAnimationFrame(step);
    }
    requestAnimationFrame(step);
  }

  function chartColors() {
    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)',
      gray: 'rgba(159, 176, 196, 0.85)', grid: 'rgba(159, 176, 196, 0.15)', text: '#c8d4e0',
    };
  }

  function renderPipeline(canvas, stats) {
    if (!canvas || typeof Chart === 'undefined') return;
    var rows = stats.deals_by_stage || [];
    var c = chartColors();
    if (charts.pipeline) charts.pipeline.destroy();
    charts.pipeline = new Chart(canvas, {
      type: 'bar',
      data: { labels: rows.map(function (r) { return r.stage || '?'; }), datasets: [{ label: 'EUR', data: rows.map(function (r) { return Number(r.total) || 0; }), backgroundColor: c.gold, borderRadius: 6 }] },
      options: { responsive: true, plugins: { legend: { display: false }, title: { display: true, text: 'Pipeline per stage', color: c.text } },
        scales: { y: { ticks: { color: c.text, callback: function (v) { return '€' + v.toLocaleString('nl-NL'); } }, grid: { color: c.grid } }, x: { ticks: { color: c.text }, grid: { display: false } } } },
    });
  }

  function renderSentiment(canvas, stats) {
    if (!canvas || typeof Chart === 'undefined') return;
    var files = stats.nas_files || [], 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;
    var c = chartColors();
    if (charts.sentiment) charts.sentiment.destroy();
    charts.sentiment = new Chart(canvas, {
      type: 'doughnut',
      data: { labels: ['Positief', 'Neutraal', 'Negatief'], datasets: [{ data: [counts.positive, counts.neutral, counts.negative], backgroundColor: [c.green, c.gray, c.red], borderWidth: 0 }] },
      options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { color: c.text } }, title: { display: true, text: 'NAS sentiment', color: c.text } } },
    });
  }

  function renderWords(canvas, stats) {
    if (!canvas || typeof Chart === 'undefined') return;
    var rows = (stats.top_words || []).slice(0, 8), c = chartColors();
    if (charts.words) charts.words.destroy();
    charts.words = new Chart(canvas, {
      type: 'bar',
      data: { labels: rows.map(function (r) { return r.lemma; }), datasets: [{ data: rows.map(function (r) { return Number(r.total) || 0; }), backgroundColor: c.cyan, borderRadius: 6 }] },
      options: { indexAxis: 'y', responsive: true, plugins: { legend: { display: false }, title: { display: true, text: 'Top woorden NAS', color: c.text } },
        scales: { x: { ticks: { color: c.text }, grid: { color: c.grid } }, y: { ticks: { color: c.text }, grid: { display: false } } } },
    });
  }

  function renderAgents(canvas, stats) {
    if (!canvas || typeof Chart === 'undefined') return;
    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), c = chartColors();
    if (charts.agents) charts.agents.destroy();
    charts.agents = new Chart(canvas, {
      type: 'polarArea',
      data: { labels: labels, datasets: [{ data: labels.map(function (k) { return map[k]; }), backgroundColor: [c.gold, c.cyan, c.green, c.red, c.gray] }] },
      options: { responsive: true, plugins: { legend: { position: 'bottom', labels: { color: c.text } }, title: { display: true, text: 'Agent activiteit', color: c.text } },
        scales: { r: { ticks: { display: false }, grid: { color: c.grid } } } },
    });
  }

  function eqBars() {
    return '<div class="hm-eq"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>';
  }

  function sparklineSvg(values, trend) {
    if (!values || !values.length) return '';
    var min = Math.min.apply(null, values), max = Math.max.apply(null, values);
    var range = max - min || 1;
    var pts = values.map(function (v, i) {
      var x = (i / (values.length - 1 || 1)) * 100;
      var y = 100 - ((v - min) / range) * 80 - 10;
      return x.toFixed(1) + ',' + y.toFixed(1);
    }).join(' ');
    var color = trend === 'down' ? '#fb7185' : '#4ade80';
    return '<svg class="hm-spark" viewBox="0 0 100 100" preserveAspectRatio="none"><polyline fill="none" stroke="' + color + '" stroke-width="3" points="' + pts + '"/></svg>';
  }

  function stockEqBars(trend) {
    var cls = trend === 'down' ? ' hm-eq-down' : '';
    return '<div class="hm-eq' + cls + '"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>';
  }

  function renderStocksMini(container, stats) {
    if (!container) return;
    var stocks = (stats.market_stocks || []).slice(0, 4);
    var summary = stats.market_summary || {};
    if (!stocks.length) {
      container.innerHTML = '<a href="/beurs" class="btn btn-sm">Beurs openen →</a>';
      return;
    }
    container.innerHTML = stocks.map(function (s) {
      var pct = Number(s.change_pct || 0);
      return '<a href="/beurs" class="beurs-mini-chip ' + (pct >= 0 ? 'up' : 'down') + '">' +
        '<strong>' + (s.symbol || s.name) + '</strong> ' +
        (pct >= 0 ? '+' : '') + pct.toFixed(2) + '%</a>';
    }).join('') + '<small style="display:block;margin-top:0.35rem;color:#64748b">Gem. ' +
      (summary.avg_change_pct || 0) + '% · <a href="/beurs">alle koersen →</a></small>';
  }

  function renderStocks(container, stats) {
    if (!container) return;
    var stocks = stats.market_stocks || [];
    var summary = stats.market_summary || {};
    var meta = document.getElementById('market-updated-at');
    if (meta) {
      var avg = summary.avg_change_pct;
      meta.textContent = stocks.length ? ('Gem. ' + (avg >= 0 ? '+' : '') + Number(avg || 0).toFixed(2) + '% · ' + (summary.quote_count || stocks.length) + ' quotes') : 'Beurs data laden…';
    }
    if (!stocks.length) {
      container.innerHTML = '<p class="empty-state">Beursdata tijdelijk niet beschikbaar — probeer Live data opnieuw.</p>';
      return;
    }
    container.innerHTML = stocks.map(function (s) {
      var pct = Number(s.change_pct || 0);
      var up = pct >= 0;
      var price = s.price != null ? Number(s.price).toFixed(2) : '—';
      var cur = s.currency || 'EUR';
      return '<div class="hm-stock-card hm-stock-' + (s.trend || (up ? 'up' : 'down')) + '">' +
        '<div class="hm-stock-head"><div><strong>' + (s.symbol || '') + '</strong><small>' + (s.name || '') + '</small></div>' +
        '<span class="hm-stock-pct ' + (up ? 'up' : 'down') + '">' + (up ? '▲' : '▼') + ' ' + Math.abs(pct).toFixed(2) + '%</span></div>' +
        '<div class="hm-stock-price">' + price + ' <small>' + cur + '</small></div>' +
        '<div class="hm-stock-chain">' + (s.chain || s.market || '') + '</div>' +
        sparklineSvg(s.sparkline || [], s.trend) + stockEqBars(s.trend) + '</div>';
    }).join('');
  }

  function rssTeaserHtml(stats) {
    var n = stats.rss_items || (stats.rss_live || []).length || 0;
    return '<p class="hm-rss-teaser">' + n + ' RSS artikelen beschikbaar. ' +
      '<a href="/?tab=rss">Open RSS tab →</a></p>';
  }

  function renderFoodHighlights(container, stats) {
    if (!container) return;
    container.innerHTML = rssTeaserHtml(stats);
  }

  function renderRegulations(container, stats) {
    if (!container) return;
    var items = stats.regulation_highlights || [];
    if (!items.length) {
      container.innerHTML = '<p class="empty-state">Regelgeving feeds — klik RSS refresh in Retail 360</p>';
      return;
    }
    container.innerHTML = items.map(function (r) {
      var cat = r.category === 'cbs' ? 'CBS' : 'REG';
      return '<div class="hm-highlight-item"><span class="hm-cat-badge hm-cat-' + (r.category || 'reg') + '">' + cat + '</span>' +
        '<a href="' + (r.link || '#') + '" target="_blank" rel="noopener"><strong>' + (r.title || '') + '</strong></a>' +
        '<small>' + (r.feed_name || '') + '</small></div>';
    }).join('');
  }

  function renderTrends(canvas, stats) {
    if (!canvas || typeof Chart === 'undefined') return;
    var rows = stats.market_trends || [];
    var c = chartColors();
    if (charts.trends) charts.trends.destroy();
    if (!rows.length) return;
    charts.trends = new Chart(canvas, {
      type: 'bar',
      data: {
        labels: rows.map(function (r) { return (r.trend_name || '?').slice(0, 18); }),
        datasets: [{
          label: 'Kans %',
          data: rows.map(function (r) { return Math.round(Number(r.opportunity_score || 0) * 100); }),
          backgroundColor: [c.green, c.cyan, c.gold, c.purple || '#a855f7'],
          borderRadius: 6,
        }],
      },
      options: {
        responsive: true,
        plugins: { legend: { display: false }, title: { display: true, text: 'Markt trend scores', color: c.text } },
        scales: {
          y: { max: 100, ticks: { color: c.text, callback: function (v) { return v + '%'; } }, grid: { color: c.grid } },
          x: { ticks: { color: c.text, maxRotation: 45 }, grid: { display: false } },
        },
      },
    });
  }

  function kpiValue(id, stats) {
    var summary = stats.market_summary || {};
    var best = summary.best_performer || {};
    var trendCount = (stats.trending_food || stats.food_market_highlights || []).length;
    switch (id) {
      case 'pipeline': return '€' + Math.round(stats.pipeline_eur || 0).toLocaleString('nl-NL');
      case 'clients_active': return (stats.clients_active || 0) + ' / ' + (stats.clients_total || stats.clients || 0);
      case 'clients_total': return String(stats.clients_total || stats.clients || 0);
      case 'crm_partnerships': return String(stats.crm_partnerships || 0);
      case 'supermarkets': return (stats.supermarkets || 0).toLocaleString('nl-NL');
      case 'wholesalers': return String(stats.wholesalers || 0);
      case 'trending_food': return String(trendCount || 0);
      case 'rss_items': return String(stats.rss_items || (stats.rss_live || []).length || 0);
      case 'rss_bookmarks': return String((stats.rss_bookmarks || []).length || stats.rss_bookmarks_count || 0);
      case 'pending_approvals': return String(stats.pending_approvals || 0);
      case 'deals': return String(stats.deals || 0);
      case 'products': return String(stats.products || 0);
      case 'suppliers': return String(stats.suppliers || 0);
      case 'nas_docs': return String(stats.nas_docs || 0);
      case 'promo_campaigns': return String(stats.promo_campaigns || 0);
      case 'market_best': return best.symbol ? (best.symbol + ' ' + Number(best.change_pct || 0).toFixed(1) + '%') : '—';
      default: return '—';
    }
  }

  function kpiPct(id, stats) {
    var summary = stats.market_summary || {};
    var trendCount = (stats.trending_food || stats.food_market_highlights || []).length;
    switch (id) {
      case 'pipeline': return '72%';
      case 'clients_active':
        return Math.min(95, Math.round(((stats.clients_active || 0) / Math.max(stats.clients_total || 1, 1)) * 100)) + '%';
      case 'crm_partnerships': return '45%';
      case 'supermarkets': return '88%';
      case 'trending_food': return Math.min(95, trendCount * 10) + '%';
      case 'rss_items': return Math.min(95, ((stats.rss_items || 0) / 10)) + '%';
      case 'pending_approvals': return '30%';
      case 'market_best': return Math.min(95, Math.abs(Number(summary.avg_change_pct || 0)) * 10) + '%';
      default: return '50%';
    }
  }

  function renderKpis(container, stats, selectedKpis) {
    if (!container) return;
    var meta = (window.DashboardLayout && window.DashboardLayout.KPI_META) || {};
    var order = selectedKpis || window._dashboardKpis ||
      (window.DashboardLayout && window.DashboardLayout.DEFAULT_KPIS) ||
      ['pipeline', 'clients_active', 'crm_partnerships', 'supermarkets', 'trending_food', 'pending_approvals'];
    var items = order.map(function (id) {
      var m = meta[id] || { label: id, sub: '', icon: '▪', color: '#94a3b8' };
      return {
        label: m.label, sub: m.sub, icon: m.icon, color: m.color || '#94a3b8',
        pct: kpiPct(id, stats), val: kpiValue(id, stats), link: m.link,
      };
    });
    if (!items.length) {
      container.innerHTML = '<p class="empty-state">Geen KPI\'s geselecteerd — klik <strong>Dashboard instellen</strong>.</p>';
      return;
    }
    container.className = 'hm-neo-kpi-row';
    container.innerHTML = items.map(function (it) {
      var inner = '<div class="hm-neo-kpi"><div class="hm-neo-kpi-top">' +
        '<div class="hm-neo-ring" style="--ring-color:' + it.color + ';--ring-pct:' + it.pct + '"><div class="hm-neo-ring-inner">' + it.icon + '</div></div>' +
        '<div><div class="hm-neo-kpi-label">' + it.label + '</div><div class="hm-neo-kpi-sub">' + it.sub + '</div></div></div>' +
        '<div class="hm-neo-kpi-value">' + it.val + '</div>' + eqBars() + '</div>';
      return it.link ? '<a href="' + it.link + '" class="hm-neo-kpi-link">' + inner + '</a>' : inner;
    }).join('');
  }

  function renderRssFeed(container, stats) {
    if (!container) return;
    var items = stats.rss_live || stats.trending_food || stats.food_market_highlights || [];
    var count = stats.rss_items || items.length;
    var head = '<div class="hm-rss-head"><span class="hm-live-dot"></span> ' + count + ' items in database' +
      ' · <button type="button" class="btn btn-sm" id="btn-rss-refresh-dash">↻ RSS ophalen</button>' +
      ' · <a href="/marketing">Marketing Hub →</a></div>';
    if (!items.length) {
      container.innerHTML = head + '<p class="empty-state">Geen RSS items — klik <strong>RSS ophalen</strong> of ga naar <a href="/marketing">Marketing Hub</a>.</p>';
      var btn = container.querySelector('#btn-rss-refresh-dash');
      if (btn) btn.addEventListener('click', function () {
        if (window._refreshRssDash) window._refreshRssDash();
      });
      return;
    }
    container.innerHTML = head + '<div class="hm-rss-list">' + items.slice(0, 20).map(function (r) {
      var when = (r.published_at || '').substring(0, 16).replace('T', ' ');
      var cat = (r.category || 'feed').toUpperCase();
      return '<a href="' + (r.link || '#') + '" target="_blank" rel="noopener" class="hm-rss-item">' +
        '<span class="hm-rss-cat">' + cat + '</span>' +
        '<span class="hm-rss-body"><strong>' + (r.title || '') + '</strong>' +
        '<small>' + (r.feed_name || 'RSS') + (when ? ' · ' + when : '') + '</small></span></a>';
    }).join('') + '</div>';
    var refreshBtn = container.querySelector('#btn-rss-refresh-dash');
    if (refreshBtn) refreshBtn.addEventListener('click', function () {
      if (window._refreshRssDash) window._refreshRssDash();
    });
  }

  function renderRetail(container, stats) {
    if (!container) return;
    container.innerHTML = rssTeaserHtml(stats);
  }

  function renderMilestones(container, stats) {
    if (!container) return;
    var ms = stats.milestones_pending || [];
    if (!ms.length) {
      container.innerHTML = '<p class="empty-state">Nog geen milestones — voeg toe via <a href="/retail">Retail 360 → Sales tab</a></p>';
      return;
    }
    container.innerHTML = ms.map(function (m) {
      return '<div class="milestone-item"><span class="milestone-dot"></span><div><strong>' + (m.title || '') + '</strong><br><small>' + (m.chain || '') + ' ' + (m.store_name || '') + '</small></div></div>';
    }).join('');
  }

  function renderExecutiveSummary(container, stats) {
    if (!container) return;
    var items = [
      { icon: '🤝', label: 'Actieve klanten', val: (stats.clients_active || 0) + ' van ' + (stats.clients_total || stats.clients || 0), link: '/clients' },
      { icon: '💰', label: 'Pipeline', val: '€' + Math.round(stats.pipeline_eur || 0).toLocaleString('nl-NL'), link: '/deals' },
      { icon: '🏪', label: 'CRM partnerships', val: stats.crm_partnerships || 0, link: '/retail' },
      { icon: '🛒', label: 'Supermarkten DB', val: (stats.supermarkets || 0).toLocaleString('nl-NL'), link: '/retail' },
      { icon: '📦', label: 'Groothandels', val: stats.wholesalers || 0, link: '/retail' },
      { icon: '✓', label: 'Goedkeuringen open', val: stats.pending_approvals || 0, link: '/' },
      { icon: '📁', label: 'Actieve promo\'s', val: stats.promo_campaigns || '—', link: '/marketing?tab=reclame' },
      { icon: '📊', label: 'NAS documenten', val: stats.nas_docs || 0, link: '/documents' },
    ];
    var trending = (stats.trending_food || stats.food_market_highlights || []).length;
    var rssN = stats.rss_items || (stats.rss_live || []).length || trending;
    var ms = (stats.milestones_pending || []).slice(0, 3);
    var html = '<div class="hm-exec-grid">' + items.map(function (it) {
      return '<a href="' + it.link + '" class="hm-exec-item"><span class="hm-exec-icon">' + it.icon + '</span>' +
        '<div><strong>' + it.label + '</strong><div class="hm-exec-val">' + it.val + '</div></div></a>';
    }).join('') + '</div>';
    if (rssN) {
      html += '<p class="hm-rss-teaser" style="margin-top:1rem">' + rssN + ' RSS feeds — <a href="/?tab=rss">bekijk in RSS tab →</a></p>';
    }
    if (ms.length) {
      html += '<h4 style="margin:1rem 0 0.5rem;font-size:0.8rem;color:#94a3b8">Open milestones</h4><ul class="hm-exec-list">';
      ms.forEach(function (m) {
        html += '<li>' + (m.title || '') + ' · ' + (m.chain || '') + ' ' + (m.store_name || '') + '</li>';
      });
      html += '</ul>';
    }
    var pending = stats.pending_approval_requests || [];
    if (pending.length) {
      html += '<h4 style="margin:1rem 0 0.5rem;font-size:0.8rem;color:#f59e0b">⏳ Open goedkeuringen</h4><ul class="hm-exec-list">';
      pending.forEach(function (p) {
        html += '<li><strong>@' + (p.agent_key || '') + '</strong> · ' + (p.title || '') + '</li>';
      });
      html += '</ul>';
    }
    html += '<p class="hm-exec-footer" style="margin-top:1rem;font-size:0.8rem;color:#64748b">' +
      '<a href="http://10.4.7.18:3001/aissa/foodlinkk-command-center" target="_blank" rel="noopener">Gitea</a> · ' +
      '<a href="/ops">IT Ops</a> · <a href="/packaging">Packaging</a> · ' +
      '<a href="/marketing?tab=publish">Automatisering</a> · ' +
      '<a href="/marketing">Marketing Hub</a> · <a href="/analytics">Analytics</a></p>';
    container.innerHTML = html;
  }

  function renderText(root, content, createdAt) {
    if (!root) return;
    var parsed = parseContent(content);
    var meta = document.getElementById('briefing-meta');
    if (meta && createdAt) meta.textContent = 'Laatst bijgewerkt: ' + String(createdAt).substring(0, 19).replace('T', ' ');
    typewriter(document.getElementById('briefing-summary-text'), parsed.summary, 8);
    var actEl = document.getElementById('briefing-actions-list');
    if (actEl) actEl.innerHTML = parsed.actions.length ? parsed.actions.map(function (a) { return '<li>' + a + '</li>'; }).join('') : '<li>Genereer dagrapport voor actiepunten</li>';
    var longEl = document.getElementById('briefing-longterm-list');
    if (longEl) longEl.innerHTML = parsed.longTerm.length ? parsed.longTerm.map(function (a) { return '<li>' + a + '</li>'; }).join('') : '<li>Halal kant-en-klaar partnerships schalen</li>';
  }

  function renderLive(root, stats, vizMode, kpiSelection) {
    if (!root || !stats) return;
    var mode = vizMode || window._dashboardVizMode || 'neo-bars';
    var kpis = kpiSelection || window._dashboardKpis;
    renderKpis(document.getElementById('briefing-kpis'), stats, kpis);
    renderFoodHighlights(document.getElementById('briefing-food-highlights'), stats);
    renderExecutiveSummary(document.getElementById('briefing-executive-summary'), stats);
    renderRetail(document.getElementById('briefing-retail'), stats);
    renderMilestones(document.getElementById('briefing-milestones'), stats);
    var actEl = document.getElementById('briefing-activity-log');
    if (actEl) {
      var log = stats.activity_log || [];
      actEl.innerHTML = log.length ? log.slice(0, 12).map(function (e) { return '<li>' + e + '</li>'; }).join('')
        : '<li class="muted">Nog geen agent-acties vandaag.</li>';
    }
    renderPipeline(document.getElementById('chart-pipeline'), stats);
    renderWords(document.getElementById('chart-words'), stats);
    if (window.VizEngine) {
      VizEngine.renderSentiment(mode, document.getElementById('chart-sentiment'), document.getElementById('viz-sentiment-alt'), stats);
      VizEngine.renderAgents(mode, document.getElementById('chart-agents'), document.getElementById('viz-agents-alt'), stats);
    } else {
      renderSentiment(document.getElementById('chart-sentiment'), stats);
      renderAgents(document.getElementById('chart-agents'), stats);
    }
  }

  function render(root, stats, content, createdAt, vizMode) {
    renderLive(root, stats, vizMode);
    renderText(root, content, createdAt);
  }

  return {
    render: render, renderLive: renderLive, renderText: renderText,
    renderExecutiveSummary: renderExecutiveSummary, renderRssFeed: renderRssFeed,
    renderKpis: renderKpis, destroyAll: destroyAll,
  };
})();
