/**
 * Vega-Lite schema service for Monaco (docs/architecture/08 §1).
 *
 * Registers the **bundled** Vega-Lite JSON schema with Monaco's JSON language
 * service. This is what makes `$schema` resolve locally (no network fetch, no
 * "unable to load schema" warning) and powers schema-aware validation,
 * autocomplete, and hover docs.
 *
 * Two deliberate departures from vega/editor's setup:
 *   - `enableSchemaRequest: false` — offline-first; the schema is bundled, never
 *     fetched (vega/editor sets it true because it is an online tool).
 *   - `fileMatch: ['*']` — bind by model, not only by the doc's `$schema` value,
 *     so validation/autocomplete work even if the user removes the `$schema`
 *     line. (Every JSON model in this app is a Vega-Lite spec.)
 */

import * as monaco from 'monaco-editor/esm/vs/editor/edcore.main';
import 'monaco-editor/esm/vs/language/json/monaco.contribution';
import vegaLiteSchema from 'vega-lite/vega-lite-schema.json';

/** The canonical URI specs reference via `$schema`; we register the schema here. */
const VEGA_LITE_SCHEMA_URI = 'https://vega.github.io/schema/vega-lite/v6.json';

/**
 * Recursively copy each `description` to `markdownDescription`. Monaco renders
 * rich (markdown) hover docs only from `markdownDescription`; without this, the
 * schema's docs would hover as plain text. Done once, in place, at setup.
 */
function addMarkdownDescriptions(node: unknown): void {
  if (Array.isArray(node)) {
    node.forEach(addMarkdownDescriptions);
    return;
  }
  if (node !== null && typeof node === 'object') {
    const obj = node as Record<string, unknown>;
    if (typeof obj.description === 'string' && obj.markdownDescription === undefined) {
      obj.markdownDescription = obj.description;
    }
    for (const key of Object.keys(obj)) addMarkdownDescriptions(obj[key]);
  }
}

let configured = false;

/** Register the Vega-Lite schema with Monaco's JSON service. Idempotent. */
export function configureVegaLiteJson(): void {
  if (configured) return;
  configured = true;

  addMarkdownDescriptions(vegaLiteSchema);

  monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    enableSchemaRequest: false,
    schemas: [
      {
        uri: VEGA_LITE_SCHEMA_URI,
        fileMatch: ['*'],
        schema: vegaLiteSchema,
      },
    ],
  });
}
