/* daygig-dashboard.js — the panels that turn the dashboard from a summary
 * into something worth opening every morning.
 *
 * Three additions, all built from endpoints that already existed:
 *   · a six-month revenue / expense / net chart, drawn as inline SVG
 *   · what needs attention — filing deadlines and stock at its reorder point
 *   · which products actually earn their shelf space
 *
 * No chart library. The whole app ships with zero third-party dependencies
 * and this is not the place to break that.
 */
(function () {
  'use strict';

  var MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

  function esc(s) {
    return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
    });
  }

  function money(n) {
    var v = Number(n || 0);
    var s = Math.abs(v).toLocaleString('en-US', {
      minimumFractionDigits: 0, maximumFractionDigits: 0,
    });
    return (v < 0 ? '−$' : '$') + s;
  }

  function money2(n) {
    var v = Number(n || 0);
    return (v < 0 ? '−$' : '$') + Math.abs(v).toLocaleString('en-US', {
      minimumFractionDigits: 2, maximumFractionDigits: 2,
    });
  }

  function getJSON(url) {
    return fetch(url, { headers: { Accept: 'application/json' } })
      .then(function (r) { return r.ok ? r.json() : null; })
      .catch(function () { return null; });
  }

  function monthWindows(count) {
    var out = [];
    var now = new Date();
    for (var i = count - 1; i >= 0; i--) {
      var start = new Date(now.getFullYear(), now.getMonth() - i, 1);
      var end = new Date(now.getFullYear(), now.getMonth() - i + 1, 0);
      out.push({
        label: MONTH[start.getMonth()],
        year: start.getFullYear(),
        from: iso(start),
        to: iso(end),
      });
    }
    return out;
  }

  function iso(dt) {
    return dt.getFullYear() + '-' +
      String(dt.getMonth() + 1).padStart(2, '0') + '-' +
      String(dt.getDate()).padStart(2, '0');
  }

  // ── Six-month trend ────────────────────────────────────────────────────
  function renderTrend(months, series) {
    var W = 720, H = 210, padL = 8, padR = 8, padB = 34, padT = 12;
    var innerW = W - padL - padR;
    var innerH = H - padT - padB;
    var max = 0;
    series.forEach(function (m) {
      max = Math.max(max, m.revenue, m.expenses);
    });
    if (max <= 0) max = 1;
    // Round the ceiling up so the gridline labels are readable numbers.
    var step = Math.pow(10, Math.floor(Math.log10(max)));
    var ceil = Math.ceil(max / step) * step;
    if (ceil / max > 1.9) ceil = Math.ceil((max * 1.15) / (step / 2)) * (step / 2);

    var slot = innerW / months.length;
    var barW = Math.min(26, slot * 0.3);
    var gap = 5;
    var svg = ['<svg viewBox="0 0 ' + W + ' ' + H + '" width="100%" height="' + H +
      '" preserveAspectRatio="none" role="img" aria-label="Revenue and expenses, last six months">'];

    // Gridlines
    for (var g = 0; g <= 3; g++) {
      var gy = padT + innerH - (innerH * g) / 3;
      svg.push('<line x1="' + padL + '" y1="' + gy.toFixed(1) + '" x2="' + (W - padR) +
        '" y2="' + gy.toFixed(1) + '" stroke="var(--border)" stroke-width="1" ' +
        (g === 0 ? '' : 'stroke-dasharray="2 4" ') + '/>');
      if (g > 0) {
        svg.push('<text x="' + padL + '" y="' + (gy - 5).toFixed(1) +
          '" font-size="10" fill="var(--text-dim)" font-family="var(--mono)">' +
          money((ceil * g) / 3) + '</text>');
      }
    }

    series.forEach(function (m, i) {
      var cx = padL + slot * i + slot / 2;
      var rH = Math.max(1, (m.revenue / ceil) * innerH);
      var eH = Math.max(1, (m.expenses / ceil) * innerH);
      var base = padT + innerH;
      svg.push('<rect x="' + (cx - barW - gap / 2).toFixed(1) + '" y="' + (base - rH).toFixed(1) +
        '" width="' + barW.toFixed(1) + '" height="' + rH.toFixed(1) +
        '" rx="2" fill="var(--accent)" opacity="0.9"><title>' +
        esc(months[i].label) + ' revenue ' + money2(m.revenue) + '</title></rect>');
      svg.push('<rect x="' + (cx + gap / 2).toFixed(1) + '" y="' + (base - eH).toFixed(1) +
        '" width="' + barW.toFixed(1) + '" height="' + eH.toFixed(1) +
        '" rx="2" fill="#4c5442"><title>' +
        esc(months[i].label) + ' expenses ' + money2(m.expenses) + '</title></rect>');
      svg.push('<text x="' + cx.toFixed(1) + '" y="' + (H - 13) +
        '" text-anchor="middle" font-size="11" fill="var(--text-dim)" ' +
        'font-family="var(--mono)">' + esc(months[i].label) + '</text>');
    });

    svg.push('</svg>');

    var totalRev = series.reduce(function (a, m) { return a + m.revenue; }, 0);
    var totalExp = series.reduce(function (a, m) { return a + m.expenses; }, 0);
    var net = totalRev - totalExp;

    return '' +
      '<div class="dash-trend-head">' +
      '<div class="dash-trend-figs">' +
      '<div><span class="dtf-label">Revenue</span><span class="dtf-val">' + money(totalRev) + '</span></div>' +
      '<div><span class="dtf-label">Expenses</span><span class="dtf-val">' + money(totalExp) + '</span></div>' +
      '<div><span class="dtf-label">Net</span><span class="dtf-val ' +
      (net >= 0 ? 'pos' : 'neg') + '">' + money(net) + '</span></div>' +
      '</div>' +
      '<div class="dash-legend">' +
      '<span><i class="lg lg-rev"></i>Revenue</span>' +
      '<span><i class="lg lg-exp"></i>Expenses</span>' +
      '</div>' +
      '</div>' +
      '<div class="dash-chart">' + svg.join('') + '</div>';
  }

  function loadTrend() {
    var host = document.getElementById('dashTrend');
    if (!host) return;
    var months = monthWindows(6);
    Promise.all(months.map(function (m) {
      return getJSON('/api/reports/pl?date_from=' + m.from + '&date_to=' + m.to);
    })).then(function (results) {
      var series = results.map(function (r) {
        if (!r) return { revenue: 0, expenses: 0 };
        var rev = (r.total_income_cents != null ? r.total_income_cents : 0) / 100;
        var cogs = (r.total_cogs_cents != null ? r.total_cogs_cents : 0) / 100;
        var exp = (r.total_opex_cents != null ? r.total_opex_cents : 0) / 100;
        return { revenue: rev, expenses: cogs + exp };
      });
      if (!series.some(function (m) { return m.revenue || m.expenses; })) {
        host.innerHTML = '<div class="empty-state">' +
          '<div class="es-icon" data-icon="chart" data-icon-size="28"></div>' +
          '<div class="es-msg">Nothing posted in the last six months yet.</div></div>';
        if (window.dgIconify) window.dgIconify(host);
        return;
      }
      host.innerHTML = renderTrend(months, series);
    });
  }

  // ── Needs attention ────────────────────────────────────────────────────
  function daysUntil(dateStr) {
    if (!dateStr) return null;
    var d = new Date(dateStr + 'T00:00:00');
    var now = new Date();
    now.setHours(0, 0, 0, 0);
    return Math.round((d - now) / 86400000);
  }

  function loadAttention() {
    var host = document.getElementById('dashAttention');
    if (!host) return;
    Promise.all([
      getJSON('/api/compliance/deadlines'),
      getJSON('/api/inventory/low-stock'),
    ]).then(function (res) {
      var deadlines = ((res[0] || {}).deadlines || []).filter(function (d) {
        return d.is_active && ['upcoming', 'in_progress', 'missed'].indexOf(d.status) !== -1;
      }).sort(function (a, b) {
        return String(a.due_date).localeCompare(String(b.due_date));
      }).slice(0, 4);
      var low = ((res[1] || {}).alerts || []).slice(0, 3);

      var rows = [];
      deadlines.forEach(function (d) {
        var n = daysUntil(d.due_date);
        var tone = n == null ? '' : n < 0 ? 'neg' : n <= 14 ? 'warn' : '';
        var when = n == null ? '' : n < 0 ? Math.abs(n) + 'd overdue'
          : n === 0 ? 'due today' : 'in ' + n + 'd';
        rows.push('<li class="att-row">' +
          '<span class="att-ico" data-icon="calendar" data-icon-size="15"></span>' +
          '<span class="att-body"><span class="att-title">' + esc(d.title) + '</span>' +
          '<span class="att-sub">' + esc(d.deadline_type_label || 'Filing') + '</span></span>' +
          '<span class="att-when ' + tone + '">' + esc(when) + '</span></li>');
      });
      low.forEach(function (p) {
        rows.push('<li class="att-row">' +
          '<span class="att-ico" data-icon="box" data-icon-size="15"></span>' +
          '<span class="att-body"><span class="att-title">' + esc(p.name) + '</span>' +
          '<span class="att-sub">' + esc(p.sku) + ' · reorder at ' + p.reorder_point + '</span></span>' +
          '<span class="att-when warn">' + p.on_hand + ' left</span></li>');
      });

      host.innerHTML = rows.length
        ? '<ul class="att-list">' + rows.join('') + '</ul>'
        : '<div class="empty-state" style="padding:28px 12px;">' +
          '<div class="es-icon" data-icon="compliance" data-icon-size="26"></div>' +
          '<div class="es-msg">Nothing needs attention.</div></div>';
      if (window.dgIconify) window.dgIconify(host);
    });
  }

  // ── Product margins ────────────────────────────────────────────────────
  function loadMargins() {
    var host = document.getElementById('dashMargins');
    if (!host) return;
    getJSON('/api/reports/product-profitability').then(function (r) {
      var products = ((r || {}).products || [])
        .filter(function (p) { return p.units_sold > 0; })
        .sort(function (a, b) { return b.gross_profit - a.gross_profit; })
        .slice(0, 6);
      if (!products.length) {
        // A contractor or landlord has no product catalog, so the whole card
        // is noise rather than an empty state worth showing.
        var card = host.closest('.card');
        if (card) card.style.display = 'none';
        return;
      }
      var shown = host.closest('.card');
      if (shown) shown.style.display = '';
      var top = products[0].gross_profit || 1;
      host.innerHTML = '<ul class="marg-list">' + products.map(function (p) {
        var pct = Math.max(3, Math.round((p.gross_profit / top) * 100));
        return '<li class="marg-row">' +
          '<div class="marg-head">' +
          '<span class="marg-name">' + esc(p.name) + '</span>' +
          '<span class="marg-profit">' + money2(p.gross_profit) + '</span>' +
          '</div>' +
          '<div class="marg-bar"><i style="width:' + pct + '%"></i></div>' +
          '<div class="marg-meta">' + p.units_sold + ' sold · ' +
          money2(p.revenue) + ' revenue · ' + p.margin_pct + '% margin</div>' +
          '</li>';
      }).join('') + '</ul>';
    });
  }

  function refresh() {
    if (!document.getElementById('dashTrend')) return;
    loadTrend();
    loadAttention();
    loadMargins();
  }

  window.dgDashboardPanels = refresh;

  document.addEventListener('DOMContentLoaded', function () {
    setTimeout(refresh, 400);
  });
})();
