window.beursHub = function () {
  return {
    tab: new URLSearchParams(location.search).get('tab') || 'beurs',
    busy: false,
    lastRefresh: '',
    listed: [],
    unlisted: [],
    summary: {},
    trends: { halal_meat_trends: [], top_dishes: [], market_trends: [] },
    concepts: [],
    events: [],
    platformStats: {},
    eventFilter: '',
    pollTimer: null,
    indicatorStyle: { left: '0%', width: '25%' },

    init() {
      this.updateIndicator();
      this.refreshAll();
      this.pollTimer = setInterval(() => {
        if (this.tab === 'events') this.loadEvents(false);
      }, 5000);
    },

    setTab(t) {
      this.tab = t;
      const url = new URL(location.href);
      url.searchParams.set('tab', t);
      history.replaceState({}, '', url);
      this.updateIndicator();
      if (t === 'trends' && !this.trends.halal_meat_trends?.length) this.loadTrends();
      if (t === 'concepten' && !this.concepts.length) this.loadConcepts();
      if (t === 'events') this.loadEvents();
    },

    updateIndicator() {
      const tabs = ['beurs', 'trends', 'concepten', 'events'];
      const i = tabs.indexOf(this.tab);
      const w = 100 / tabs.length;
      this.indicatorStyle = { left: (i * w) + '%', width: w + '%' };
    },

    sparkPoints(arr) {
      if (!arr || !arr.length) return '';
      const min = Math.min.apply(null, arr);
      const max = Math.max.apply(null, arr);
      const range = max - min || 1;
      return arr.map(function (v, idx) {
        var x = (idx / (arr.length - 1 || 1)) * 100;
        var y = 28 - ((v - min) / range) * 24;
        return x.toFixed(1) + ',' + y.toFixed(1);
      }).join(' ');
    },

    async refreshAll() {
      this.busy = true;
      try {
        await Promise.all([
          this.loadMarket(),
          this.loadTrends(),
          this.loadConcepts(),
          this.loadEvents(false),
        ]);
        this.lastRefresh = new Date().toLocaleString('nl-NL');
        if (typeof Cockpit !== 'undefined') Cockpit.toast('Beurs data bijgewerkt', 'success');
      } catch (e) {
        if (typeof Cockpit !== 'undefined') Cockpit.toast(e.message, 'error');
      }
      this.busy = false;
    },

    async loadMarket() {
      const d = await fetch('/api/retail/market/supermarkets').then(function (r) { return r.json(); });
      this.listed = d.listed || [];
      this.unlisted = d.unlisted_nl || [];
      this.summary = d.summary || {};
    },

    async loadTrends() {
      const d = await fetch('/api/retail/market/food-trends').then(function (r) { return r.json(); });
      this.trends = d;
    },

    async loadConcepts() {
      const d = await fetch('/api/retail/market/concepts?limit=6').then(function (r) { return r.json(); });
      this.concepts = d.concepts || [];
    },

    async loadEvents(toast) {
      var q = this.eventFilter ? '?limit=80&agent=' + encodeURIComponent(this.eventFilter) : '?limit=80';
      try {
        var r = await fetch('/api/live/platform' + q).then(function (x) { return x.json(); });
        this.events = r.events || [];
        this.platformStats = r.stats || {};
      } catch (e) {
        if (toast !== false && typeof Cockpit !== 'undefined') Cockpit.toast(e.message, 'error');
      }
    },
  };
};
