/* charts-forecast.jsx — Heatmap (cohort), HBar (horizontal bar list),
   GroupedBar (vs comparison), DualAxisChart (volume + workload). */

// ---------- Cohort heatmap (rows × cols of cells) ----------
// rows: [{ label, sublabel, total, cells: [{ value, label, tone? }] }]
// cols: [{ key, label }]
// max: number for color scaling (defaults max of all values)
function CohortGrid({ rows, cols, mode = 'percent', cellSize = 64, max, showRowMeta = true, accent = '#0b43ea' }) {
  const m = max ?? Math.max(...rows.flatMap(r => r.cells.map(c => c.value || 0)), 1);
  function shade(v) {
    if (v == null) return { bg: 'transparent', fg: 'var(--bx-text-muted)' };
    const t = Math.max(0.04, Math.min(1, v / m));
    // primary tint scale (lighter for low values)
    const alpha = 0.08 + t * 0.92;
    return {
      bg: `color-mix(in oklab, ${accent} ${Math.round(t * 100)}%, #ffffff)`,
      fg: t > 0.55 ? '#fff' : 'var(--bx-text-dark)',
      alpha,
    };
  }
  return (
    <div style={{ overflowX: 'auto' }}>
      <table style={{
        borderCollapse: 'separate', borderSpacing: 4,
        fontFamily: 'var(--bx-font-sans)', fontSize: 12,
      }}>
        <thead>
          <tr>
            {showRowMeta && <th style={{ padding: '6px 10px', textAlign: 'left' }}></th>}
            {showRowMeta && <th style={{ padding: '6px 10px', textAlign: 'left' }}></th>}
            {cols.map((c, i) => (
              <th key={i} style={{
                padding: '4px 6px', textAlign: 'center',
                fontSize: 10.5, fontWeight: 600, color: 'var(--bx-text-muted)',
                textTransform: 'uppercase', letterSpacing: '0.05em',
                minWidth: cellSize,
              }}>{c.label}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((r, ri) => (
            <tr key={ri}>
              {showRowMeta && (
                <td style={{ padding: '0 10px', whiteSpace: 'nowrap', verticalAlign: 'middle' }}>
                  <div style={{ display: 'flex', flexDirection: 'column' }}>
                    <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--bx-text-dark)' }}>{r.label}</span>
                    {r.sublabel && <span style={{ fontSize: 10.5, color: 'var(--bx-text-muted)' }}>{r.sublabel}</span>}
                  </div>
                </td>
              )}
              {showRowMeta && (
                <td style={{
                  padding: '0 10px', textAlign: 'right',
                  fontFamily: 'var(--bx-font-mono)', fontVariantNumeric: 'tabular-nums',
                  fontSize: 12, fontWeight: 600, color: 'var(--bx-text-body)',
                  whiteSpace: 'nowrap',
                }}>{r.total != null ? Number(r.total).toLocaleString('en-US') : ''}</td>
              )}
              {r.cells.map((c, ci) => {
                if (c.value == null) {
                  return <td key={ci} style={{ padding: 0 }}>
                    <div style={{ height: cellSize - 8, borderRadius: 6, background: 'transparent' }}/>
                  </td>;
                }
                const sh = shade(c.value);
                return (
                  <td key={ci} style={{ padding: 0, verticalAlign: 'middle' }}>
                    <div title={c.title} style={{
                      height: cellSize - 8, minWidth: cellSize - 8,
                      borderRadius: 8,
                      background: sh.bg,
                      color: sh.fg,
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                      flexDirection: 'column', gap: 1,
                      cursor: c.title ? 'help' : 'default',
                    }}>
                      <span style={{
                        fontSize: cellSize > 60 ? 13.5 : 12,
                        fontWeight: 700,
                        fontFamily: 'var(--bx-font-mono)',
                        fontVariantNumeric: 'tabular-nums',
                      }}>{c.label != null ? c.label : c.value}</span>
                      {c.sub && (
                        <span style={{ fontSize: 9.5, opacity: 0.75, fontFamily: 'var(--bx-font-mono)' }}>{c.sub}</span>
                      )}
                    </div>
                  </td>
                );
              })}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ---------- Horizontal bar list (e.g. customer ranking) ----------
// items: [{ label, value, valueLabel?, color?, sub? }]
function HBar({ items, max, height = 16, valueWidth = 60, labelWidth = 140, accent = '#0b43ea' }) {
  const m = max ?? Math.max(...items.map(i => i.value), 1);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {items.map((it, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{ width: labelWidth, minWidth: labelWidth, flexShrink: 0 }}>
            <div style={{ fontSize: 12.5, fontWeight: 500, color: 'var(--bx-text-dark)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{it.label}</div>
            {it.sub && <div style={{ fontSize: 10.5, color: 'var(--bx-text-muted)' }}>{it.sub}</div>}
          </div>
          <div style={{ flex: 1, minWidth: 0, height, background: 'var(--bx-surface-2)', borderRadius: 6, overflow: 'hidden', position: 'relative' }}>
            <div style={{
              height: '100%', width: ((it.value / m) * 100) + '%',
              background: it.color || accent, transition: 'width 240ms var(--bx-ease)',
              borderRadius: 6,
            }}/>
          </div>
          <div style={{
            width: valueWidth, minWidth: valueWidth, textAlign: 'right',
            fontFamily: 'var(--bx-font-mono)', fontVariantNumeric: 'tabular-nums',
            fontSize: 12, fontWeight: 600, color: 'var(--bx-text-dark)',
          }}>{it.valueLabel != null ? it.valueLabel : Number(it.value).toLocaleString('en-US')}</div>
        </div>
      ))}
    </div>
  );
}

// ---------- Grouped bars (now vs same-period last sale vs last year) ----------
// data: [{ label, groups: [{ key, value, color }] }]
function GroupedBar({ data, groupKeys, height = 220, xKey = 'label' }) {
  const ref = React.useRef(null);
  const w = useChartSize(ref);
  const [hover, setHover] = React.useState(null);
  const padding = { top: 16, right: 16, bottom: 32, left: 48 };
  const innerW = w - padding.left - padding.right;
  const innerH = height - padding.top - padding.bottom;
  const allVals = data.flatMap(d => groupKeys.map(g => d[g.key] || 0));
  const maxV = Math.max(...allVals, 1);
  const ticks = niceTicks(maxV, 4);
  const top = ticks[ticks.length - 1] || 1;
  const groupW = innerW / data.length;
  const barW = Math.min(18, (groupW * 0.78) / groupKeys.length);
  const x = (i) => padding.left + groupW * i + groupW / 2;
  const y = (v) => padding.top + innerH - (v / top) * innerH;

  return (
    <div ref={ref} style={{ width: '100%', position: 'relative' }}>
      <svg width={w} height={height} style={{ display: 'block' }}>
        {ticks.map(t => (
          <g key={t}>
            <line x1={padding.left} x2={w - padding.right} y1={y(t)} y2={y(t)}
              stroke="#ececec" strokeDasharray={t === 0 ? '0' : '3 3'}/>
            <text x={padding.left - 8} y={y(t) + 4} fontSize="10" fill="#99a1af" textAnchor="end"
              style={{ fontFamily: 'var(--bx-font-mono)' }}>
              {t >= 1000 ? (t / 1000).toFixed(t < 10000 ? 1 : 0) + 'k' : t}
            </text>
          </g>
        ))}
        {data.map((row, i) => (
          <g key={i} onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(null)}>
            {groupKeys.map((g, gi) => {
              const v = row[g.key] || 0;
              const cx = x(i) + (gi - (groupKeys.length - 1) / 2) * (barW + 2);
              const yT = y(v);
              return (
                <rect key={g.key} x={cx - barW / 2} y={yT} width={barW} height={Math.max(0, y(0) - yT)}
                  rx="2" fill={g.color}
                  opacity={hover === null || hover === i ? 1 : 0.5}/>
              );
            })}
            <text x={x(i)} y={height - 10} fontSize="10" fill="#99a1af" textAnchor="middle"
              style={{ fontFamily: 'var(--bx-font-sans)' }}>{row[xKey]}</text>
          </g>
        ))}
      </svg>
      {hover !== null && (
        <div style={{
          position: 'absolute', left: Math.min(w - 220, Math.max(0, x(hover) - 100)), top: 6,
          background: '#fff', border: '1px solid var(--bx-border-muted)',
          borderRadius: 8, padding: '8px 10px', boxShadow: 'var(--bx-shadow-pop)',
          pointerEvents: 'none', minWidth: 200, fontSize: 11.5,
        }}>
          <div style={{ fontWeight: 600, marginBottom: 4, color: 'var(--bx-text-heading)' }}>{data[hover][xKey]}</div>
          {groupKeys.map(g => (
            <div key={g.key} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ width: 8, height: 8, background: g.color, borderRadius: 2 }}></span>
              <span style={{ flex: 1 }}>{g.label}</span>
              <span style={{ fontFamily: 'var(--bx-font-mono)', fontVariantNumeric: 'tabular-nums', fontWeight: 600 }}>
                {(data[hover][g.key] || 0).toLocaleString('en-US')}
              </span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ---------- Volume bars + workload-unit overlay line ----------
function DualAxisChart({ data, height = 240, barKey = 'qty', lineKey = 'wlu',
  barLabel = 'Volume', lineLabel = 'Workload unit', xKey = 'date', barColor = '#0b43ea', lineColor = '#ff6467' }) {
  const ref = React.useRef(null);
  const w = useChartSize(ref);
  const [hover, setHover] = React.useState(null);
  const padding = { top: 16, right: 48, bottom: 32, left: 48 };
  const innerW = w - padding.left - padding.right;
  const innerH = height - padding.top - padding.bottom;

  const maxBar  = Math.max(...data.map(d => d[barKey] || 0), 1);
  const maxLine = Math.max(...data.map(d => d[lineKey] || 0), 1);
  const ticks = niceTicks(maxBar, 4);
  const topBar = ticks[ticks.length - 1] || 1;
  const lineTicks = niceTicks(maxLine, 4);
  const topLine = lineTicks[lineTicks.length - 1] || 1;
  const groupW = innerW / data.length;
  const barW = Math.min(18, groupW * 0.62);
  const x = (i) => padding.left + groupW * i + groupW / 2;
  const y = (v) => padding.top + innerH - (v / topBar) * innerH;
  const yL = (v) => padding.top + innerH - (v / topLine) * innerH;

  let linePath = '';
  data.forEach((row, i) => {
    if (row[lineKey] == null) return;
    linePath += (linePath ? ' L' : 'M') + x(i) + ' ' + yL(row[lineKey]);
  });

  return (
    <div ref={ref} style={{ width: '100%', position: 'relative' }}>
      <svg width={w} height={height} style={{ display: 'block', overflow: 'visible' }}
           onMouseLeave={() => setHover(null)}>
        {ticks.map(t => (
          <g key={t}>
            <line x1={padding.left} x2={w - padding.right} y1={y(t)} y2={y(t)}
              stroke="#ececec" strokeDasharray={t === 0 ? '0' : '3 3'}/>
            <text x={padding.left - 8} y={y(t) + 4} fontSize="10" fill="#99a1af" textAnchor="end"
              style={{ fontFamily: 'var(--bx-font-mono)' }}>
              {t >= 1000 ? (t / 1000).toFixed(t < 10000 ? 1 : 0) + 'k' : t}
            </text>
          </g>
        ))}
        {/* right axis ticks (workload) */}
        {lineTicks.map(t => (
          <text key={'l-' + t} x={w - padding.right + 8} y={yL(t) + 4} fontSize="10"
            fill={lineColor} textAnchor="start"
            style={{ fontFamily: 'var(--bx-font-mono)' }}>
            {t >= 1000 ? (t / 1000).toFixed(t < 10000 ? 1 : 0) + 'k' : t}
          </text>
        ))}
        {/* bars */}
        {data.map((row, i) => {
          const v = row[barKey] || 0;
          const tone = row.isFuture ? 0.55 : 1;
          return (
            <g key={i}>
              <rect x={x(i) - groupW / 2} y={padding.top} width={groupW} height={innerH}
                fill="transparent" onMouseEnter={() => setHover(i)}/>
              <rect x={x(i) - barW / 2} y={y(v)} width={barW} height={Math.max(0, y(0) - y(v))}
                rx="2" fill={barColor} opacity={tone}/>
              {row.dayType === 'MEGA_SALE' && (
                <circle cx={x(i)} cy={y(v) - 8} r="3" fill="#ff6467"/>
              )}
            </g>
          );
        })}
        {/* x labels: show ~10 ticks */}
        {data.map((row, i) => {
          if (i % Math.ceil(data.length / 10) !== 0 && i !== data.length - 1) return null;
          const lbl = row.label || row[xKey];
          return (
            <text key={'x' + i} x={x(i)} y={height - 14} fontSize="10" fill="#99a1af"
              textAnchor="middle" style={{ fontFamily: 'var(--bx-font-sans)' }}>
              {typeof lbl === 'string' && lbl.length > 5 ? lbl.slice(5) : lbl}
            </text>
          );
        })}
        {/* line */}
        <path d={linePath} stroke={lineColor} strokeWidth="2" fill="none"
          strokeLinejoin="round" strokeLinecap="round"/>
        {data.map((row, i) => row[lineKey] != null && (
          <circle key={'p' + i} cx={x(i)} cy={yL(row[lineKey])} r={hover === i ? 4 : 2.5}
            fill={lineColor} stroke="#fff" strokeWidth="1.5"/>
        ))}
        {/* hover marker */}
        {hover !== null && (
          <line x1={x(hover)} x2={x(hover)} y1={padding.top} y2={padding.top + innerH}
            stroke="#0b43ea" strokeWidth="1" strokeDasharray="2 2" opacity="0.4"/>
        )}
      </svg>
      {hover !== null && (
        <div style={{
          position: 'absolute', left: Math.min(w - 200, Math.max(0, x(hover) - 90)), top: 6,
          background: '#fff', border: '1px solid var(--bx-border-muted)',
          borderRadius: 8, padding: '8px 10px', boxShadow: 'var(--bx-shadow-pop)',
          pointerEvents: 'none', minWidth: 180, fontSize: 11.5, zIndex: 2,
        }}>
          <div style={{ fontWeight: 600, color: 'var(--bx-text-heading)', marginBottom: 4 }}>
            {data[hover].label || data[hover][xKey]}
            {data[hover].dayType && data[hover].dayType !== 'NORMAL' && (
              <span style={{ marginLeft: 6, fontSize: 10, color: 'var(--bx-text-muted)', fontWeight: 500 }}>
                · {data[hover].dayType}
              </span>
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 8, height: 8, background: barColor, borderRadius: 2 }}></span>
            <span style={{ flex: 1 }}>{barLabel}</span>
            <span style={{ fontFamily: 'var(--bx-font-mono)', fontWeight: 600 }}>{(data[hover][barKey] || 0).toLocaleString('en-US')}</span>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ width: 8, height: 2, background: lineColor, borderRadius: 2 }}></span>
            <span style={{ flex: 1 }}>{lineLabel}</span>
            <span style={{ fontFamily: 'var(--bx-font-mono)', fontWeight: 600 }}>{(data[hover][lineKey] || 0).toLocaleString('en-US')}</span>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------- MultiLine — multiple lines on same axes for warehouse trends ----------
function MultiLine({ data, lines, height = 220, xKey = 'date' }) {
  // wrapper around existing LineChart, kept for clarity
  return <LineChart data={data} lines={lines} height={height} xKey={xKey}/>;
}

// ---------- Donut (small) ----------
function Donut({ items, size = 120, thickness = 18, centerLabel, centerSub }) {
  const total = items.reduce((s, i) => s + i.value, 0) || 1;
  const r = size / 2;
  const inner = r - thickness;
  let acc = 0;
  function arc(start, end) {
    const a0 = (start / total) * Math.PI * 2 - Math.PI / 2;
    const a1 = (end / total) * Math.PI * 2 - Math.PI / 2;
    const x0 = r + Math.cos(a0) * r, y0 = r + Math.sin(a0) * r;
    const x1 = r + Math.cos(a1) * r, y1 = r + Math.sin(a1) * r;
    const xi0 = r + Math.cos(a1) * inner, yi0 = r + Math.sin(a1) * inner;
    const xi1 = r + Math.cos(a0) * inner, yi1 = r + Math.sin(a0) * inner;
    const large = (a1 - a0) > Math.PI ? 1 : 0;
    return `M${x0},${y0} A${r},${r} 0 ${large} 1 ${x1},${y1} L${xi0},${yi0} A${inner},${inner} 0 ${large} 0 ${xi1},${yi1} Z`;
  }
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size}>
        {items.map((it, i) => {
          const d = arc(acc, acc + it.value);
          acc += it.value;
          return <path key={i} d={d} fill={it.color}/>;
        })}
      </svg>
      {centerLabel && (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center', pointerEvents: 'none' }}>
          <div style={{ fontSize: 16, fontWeight: 700, color: 'var(--bx-text-heading)', fontFamily: 'var(--bx-font-mono)' }}>{centerLabel}</div>
          {centerSub && <div style={{ fontSize: 10.5, color: 'var(--bx-text-muted)' }}>{centerSub}</div>}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { CohortGrid, HBar, GroupedBar, DualAxisChart, MultiLine, Donut });
