/**
 * Theme Builder gallery specs (docs/chart-theming-scope.md §4.4).
 *
 * A fixed set of small, self-contained Vega-Lite specs the Theme Builder
 * renders side by side with the draft config, so an edit is previewed across
 * every chart surface a config styles. Every structured control should have a
 * live mirror here: titles + subtitles, axes/grids/ticks, facet headers, the
 * mark types (bar, line, area, point, arc), and each color family — categorical
 * (`range.category`), sequential (`range.heatmap` for rect, `range.ramp` for a
 * continuous legend), and diverging (`range.diverging`, a quantitative color
 * scale with a `domainMid`).
 *
 * The specs deliberately use BARE mark strings (`mark: 'point'`, not
 * `{ type: 'point', size: 80 }`): a property hard-coded in the spec overrides
 * the same key in the injected config, which would make the corresponding Marks
 * control a no-op in the preview. Add visual mark properties to the config (a
 * theme), never inline here. Two controls have no static mirror by nature — the
 * default chart SIZE (`view.continuousWidth/Height`: the cards are fixed-size
 * swatches) and TOOLTIPS (`mark.tooltip`: hover-only) — and `countTitle` has
 * none (no count aggregation in the samples). Inline data only, compact fixed
 * sizes — swatches, not analyses.
 */

import type { JsonObject } from './spec-config';

const SCHEMA = 'https://vega.github.io/schema/vega-lite/v6.json';

export interface ThemePreviewSpec {
  /** Stable key for React lists and test assertions. */
  id: string;
  /** What surface this card exercises (shown as the card caption). */
  caption: string;
  spec: JsonObject;
}

const bar: ThemePreviewSpec = {
  id: 'bar',
  caption: 'Bar — title, axes, grid',
  spec: {
    $schema: SCHEMA,
    title: 'Revenue by region',
    width: 200,
    height: 140,
    data: {
      values: [
        { region: 'North', revenue: 42 },
        { region: 'South', revenue: 61 },
        { region: 'East', revenue: 28 },
        { region: 'West', revenue: 55 },
        { region: 'Central', revenue: 47 },
      ],
    },
    mark: 'bar',
    encoding: {
      x: { field: 'region', type: 'nominal', axis: { labelAngle: 0 } },
      y: { field: 'revenue', type: 'quantitative' },
    },
  },
};

const line: ThemePreviewSpec = {
  id: 'line',
  caption: 'Line — subtitle, curve & markers',
  spec: {
    $schema: SCHEMA,
    title: { text: 'Signups over time', subtitle: 'Weekly, by plan' },
    width: 200,
    height: 140,
    data: {
      values: [
        { week: 1, plan: 'Free', n: 20 },
        { week: 2, plan: 'Free', n: 28 },
        { week: 3, plan: 'Free', n: 26 },
        { week: 4, plan: 'Free', n: 34 },
        { week: 1, plan: 'Pro', n: 8 },
        { week: 2, plan: 'Pro', n: 11 },
        { week: 3, plan: 'Pro', n: 17 },
        { week: 4, plan: 'Pro', n: 21 },
        { week: 1, plan: 'Team', n: 3 },
        { week: 2, plan: 'Team', n: 4 },
        { week: 3, plan: 'Team', n: 9 },
        { week: 4, plan: 'Team', n: 12 },
      ],
    },
    // Bare `mark: 'line'` — the curve, stroke width, and point markers come from
    // the draft config (the Marks panel's Lines & areas group), not the spec, so
    // those controls have a live mirror. Same for every card below.
    mark: 'line',
    encoding: {
      x: { field: 'week', type: 'quantitative', axis: { tickCount: 4 } },
      y: { field: 'n', type: 'quantitative' },
      color: { field: 'plan', type: 'nominal' },
    },
  },
};

const area: ThemePreviewSpec = {
  id: 'area',
  caption: 'Normalized area — palette, %',
  spec: {
    $schema: SCHEMA,
    width: 200,
    height: 140,
    data: {
      values: [
        { q: 1, channel: 'Web', v: 30 },
        { q: 2, channel: 'Web', v: 36 },
        { q: 3, channel: 'Web', v: 41 },
        { q: 4, channel: 'Web', v: 38 },
        { q: 1, channel: 'Store', v: 22 },
        { q: 2, channel: 'Store', v: 19 },
        { q: 3, channel: 'Store', v: 24 },
        { q: 4, channel: 'Store', v: 27 },
        { q: 1, channel: 'Partner', v: 12 },
        { q: 2, channel: 'Partner', v: 16 },
        { q: 3, channel: 'Partner', v: 14 },
        { q: 4, channel: 'Partner', v: 18 },
      ],
    },
    mark: 'area',
    encoding: {
      x: { field: 'q', type: 'quantitative', axis: { tickCount: 4 } },
      // `stack: 'normalize'` makes the y-axis a 0–100% scale, so its labels use
      // `config.normalizedNumberFormat` — the mirror for that Formats control.
      y: { field: 'v', type: 'quantitative', stack: 'normalize' },
      color: { field: 'channel', type: 'nominal' },
    },
  },
};

const scatter: ThemePreviewSpec = {
  id: 'scatter',
  caption: 'Points — size, shape, gradient legend',
  spec: {
    $schema: SCHEMA,
    width: 200,
    height: 140,
    data: {
      values: [
        { x: 4, y: 7, z: 12 },
        { x: 8, y: 3, z: 31 },
        { x: 12, y: 11, z: 45 },
        { x: 16, y: 6, z: 22 },
        { x: 20, y: 14, z: 60 },
        { x: 24, y: 9, z: 38 },
        { x: 28, y: 17, z: 74 },
        { x: 32, y: 12, z: 51 },
        { x: 36, y: 20, z: 88 },
      ],
    },
    // Bare `mark: 'point'` — size, shape, and fill come from the Marks panel's
    // Points group, so those controls have a mirror (a hard-coded size/filled
    // here would shadow them).
    mark: 'point',
    encoding: {
      x: { field: 'x', type: 'quantitative' },
      y: { field: 'y', type: 'quantitative' },
      color: { field: 'z', type: 'quantitative' },
    },
  },
};

const heatmap: ThemePreviewSpec = {
  id: 'heatmap',
  caption: 'Heatmap — sequential scale',
  spec: {
    $schema: SCHEMA,
    width: 200,
    height: 140,
    data: {
      values: ['Mon', 'Tue', 'Wed', 'Thu'].flatMap((day, d) =>
        ['AM', 'Noon', 'PM'].map((slot, s) => ({ day, slot, v: (d + 1) * (s + 2) * 3 })),
      ),
    },
    mark: 'rect',
    encoding: {
      x: { field: 'day', type: 'nominal', axis: { labelAngle: 0 } },
      y: { field: 'slot', type: 'nominal' },
      color: { field: 'v', type: 'quantitative' },
    },
  },
};

const diverging: ThemePreviewSpec = {
  id: 'diverging',
  caption: 'Diverging — scale around a midpoint',
  spec: {
    $schema: SCHEMA,
    title: 'Net change by topic',
    width: 200,
    height: 140,
    data: {
      values: [
        { topic: 'Cost', delta: -8 },
        { topic: 'Speed', delta: -3 },
        { topic: 'Help', delta: 1 },
        { topic: 'Look', delta: 6 },
        { topic: 'Value', delta: 11 },
      ],
    },
    mark: 'bar',
    encoding: {
      x: { field: 'topic', type: 'nominal', axis: { labelAngle: 0 } },
      y: { field: 'delta', type: 'quantitative' },
      // `domainMid` makes this a diverging color scale, so it reads from
      // `range.diverging` rather than `range.ramp`/`heatmap` (the others above).
      color: {
        field: 'delta',
        type: 'quantitative',
        scale: { domainMid: 0 },
        legend: { title: null },
      },
    },
  },
};

const donut: ThemePreviewSpec = {
  id: 'donut',
  caption: 'Pie & donut — palette, legend',
  spec: {
    $schema: SCHEMA,
    width: 200,
    height: 140,
    data: {
      values: [
        { browser: 'Firefox', share: 32 },
        { browser: 'Chrome', share: 41 },
        { browser: 'Safari', share: 18 },
        { browser: 'Other', share: 9 },
      ],
    },
    // Bare `mark: 'arc'` renders a pie; the Marks panel's Arc group (donut hole,
    // corner radius, pad angle) reshapes it — so those controls have a mirror.
    mark: 'arc',
    encoding: {
      theta: { field: 'share', type: 'quantitative' },
      color: { field: 'browser', type: 'nominal' },
    },
  },
};

const facet: ThemePreviewSpec = {
  id: 'facet',
  caption: 'Facets — headers, date format',
  spec: {
    $schema: SCHEMA,
    width: 80,
    height: 110,
    // Faceted by a raw temporal field (no time unit) so the header labels are
    // dates formatted by `config.timeFormat` — the mirror for that Formats
    // control (which does NOT affect axes, only text/legend/header labels) — on
    // top of the header colour/size/weight the Headers panel styles.
    data: {
      values: [
        { period: '2026-01-15', team: 'Alpha', v: 14 },
        { period: '2026-01-15', team: 'Beta', v: 9 },
        { period: '2026-01-15', team: 'Gamma', v: 11 },
        { period: '2026-06-15', team: 'Alpha', v: 21 },
        { period: '2026-06-15', team: 'Beta', v: 13 },
        { period: '2026-06-15', team: 'Gamma', v: 15 },
      ],
    },
    mark: 'bar',
    encoding: {
      x: { field: 'team', type: 'nominal', axis: { labelAngle: 0 } },
      y: { field: 'v', type: 'quantitative' },
      column: { field: 'period', type: 'temporal' },
    },
  },
};

/** The gallery, in display order — the three continuous-color examples
 *  (scatter → ramp, heatmap → heatmap, diverging → diverging) sit together. */
export const THEME_PREVIEW_SPECS: ReadonlyArray<ThemePreviewSpec> = [
  bar,
  line,
  area,
  scatter,
  heatmap,
  diverging,
  donut,
  facet,
];
