/**
 * pres/charts — theme-styled chart wrapper.
 *
 * The agent provides data in a simple shape; we resolve colours,
 * gridlines, and label typography from the active theme and palette,
 * then return a `(chartType, data, opts)` triple that the archetype
 * passes to `slide.addChart(...)`.
 *
 * Supported shapes:
 *   { type: 'bar' | 'column' | 'line' | 'area',  categories: [...], series: [{name, data:[...]}, ...] }
 *   { type: 'pie' | 'donut',                     data: [{ label, value }, ...] }
 *
 * Theme decides:
 *   - colour sequence (from palettes.CHART_SERIES[paletteName])
 *   - gridline visibility + colour
 *   - data-label font + size + colour
 *   - legend placement + typography
 *   - donut hole size
 */
import { CHART_SERIES } from '../palettes.js';

function colorsFor(resolved) {
  return CHART_SERIES[resolved.palette.name] || [
    resolved.palette.primary,
    resolved.palette.accent,
    resolved.palette.subtle,
  ];
}

/**
 * Resolve a chart spec to (chartType, data, opts) that pptxgenjs
 * `slide.addChart` accepts. Returns `null` when the spec is malformed
 * so the archetype can show a fallback panel instead.
 *
 * Note: `chartType` is returned as a string identifier (e.g. 'bar',
 * 'donut'). The archetype maps the string → `pptx.ChartType[...]`
 * because the ChartType enum is only available on a pptxgenjs instance.
 */
export function resolveChart(spec, resolved) {
  if (!spec || !spec.type) return null;
  const t = String(spec.type).toLowerCase();
  const colors = colorsFor(resolved);
  const family = resolved.theme.family;
  const typo = resolved.typography;

  const baseOpts = {
    chartColors: colors,
    showLegend: spec.showLegend !== false,
    legendPos: 'r',
    legendFontFace: typo.caption.fontFace,
    legendFontSize: typo.caption.fontSize,
    legendColor: resolved.palette.text,

    catAxisLineShow: family === 'data',
    valAxisLineShow: family === 'data',
    catAxisLabelFontFace: typo.caption.fontFace,
    catAxisLabelFontSize: typo.caption.fontSize,
    catAxisLabelColor: resolved.palette.subtle,
    valAxisLabelFontFace: typo.caption.fontFace,
    valAxisLabelFontSize: typo.caption.fontSize,
    valAxisLabelColor: resolved.palette.subtle,

    showValue: false,
    dataLabelFontFace: typo.caption.fontFace,
    dataLabelFontSize: typo.caption.fontSize,
    dataLabelColor: resolved.palette.text,

    // Gridline policy: editorial = none, tech = light, data = visible.
    valGridLine: family === 'editorial'
      ? { style: 'none' }
      : family === 'tech'
        ? { color: resolved.palette.subtle, size: 0.5, transparency: 70 }
        : { color: resolved.palette.subtle, size: 0.5, transparency: 30 },
    catGridLine: { style: 'none' },
  };

  if (t === 'pie' || t === 'donut') {
    const items = Array.isArray(spec.data) ? spec.data : [];
    const data = [{
      name: spec.name || 'Series',
      labels: items.map(d => String(d.label ?? '')),
      values: items.map(d => Number(d.value) || 0),
    }];
    const opts = {
      ...baseOpts,
      showPercent: spec.showPercent !== false,
      holeSize: t === 'donut' ? (spec.holeSize ?? 60) : 0,
      dataLabelPosition: t === 'donut' ? 'outEnd' : 'bestFit',
    };
    return { type: t === 'donut' ? 'doughnut' : 'pie', data, opts };
  }

  // bar / column / line / area: same data shape.
  const categories = Array.isArray(spec.categories) ? spec.categories : [];
  const series = Array.isArray(spec.series) ? spec.series : [];
  const data = series.map(s => ({
    name: s.name || 'Series',
    labels: categories.map(c => String(c)),
    values: (s.data || []).map(v => Number(v) || 0),
  }));

  const opts = { ...baseOpts };
  if (t === 'bar') {
    opts.barDir = 'bar';
    opts.barGrouping = spec.stacked ? 'stacked' : 'clustered';
  } else if (t === 'column') {
    opts.barDir = 'col';
    opts.barGrouping = spec.stacked ? 'stacked' : 'clustered';
  } else if (t === 'line') {
    opts.lineDataSymbol = 'circle';
    opts.lineDataSymbolSize = 5;
    opts.lineSize = 2.5;
  } else if (t === 'area') {
    opts.fill = colors[0];
  }
  // pptxgenjs uses 'bar' for both bar + column (direction differs).
  const pptxType = (t === 'column' || t === 'bar') ? 'bar' : t;
  return { type: pptxType, data, opts };
}
