import test from "node:test";
import assert from "node:assert/strict";
import fixture from "../examples/esp32-audio.json" with { type: "json" };
import { compile, analyze } from "../src/compile.js";
import {
  API_VERSION as REST_API_VERSION,
  SCHEMA_VERSION as REST_SCHEMA_VERSION,
  withEnvelopeMeta as withRestEnvelopeMeta,
  parsePayloadOptions,
  errorEnvelope
} from "../src/server.js";
import {
  handleToolCall,
  uiBundleDescriptor,
  toolListResult
} from "../src/mcp-server.js";

test("REST compile contract shape is stable with version metadata", () => {
  const parsed = parsePayloadOptions({ payload: fixture, options: { render_mode: "schematic_stub" } });
  const body = withRestEnvelopeMeta({ request_id: "req-test-1", ...compile(parsed.payload, parsed.options) });

  assert.equal(body.ok, true);
  assert.equal(body.api_version, REST_API_VERSION);
  assert.equal(body.schema_version, REST_SCHEMA_VERSION);
  assert.equal(body.request_id, "req-test-1");
  assert.ok(Array.isArray(body.errors));
  assert.ok(Array.isArray(body.warnings));
  assert.ok(Array.isArray(body.bus_groups));
  assert.equal(typeof body.render_mode_used, "string");
  assert.equal(typeof body.layout_engine_requested, "string");
  assert.equal(typeof body.layout_engine_used, "string");
  assert.ok(Array.isArray(body.layout_warnings));
  assert.equal(typeof body.svg, "string");
});

test("REST analyze contract shape is stable with version metadata", () => {
  const parsed = parsePayloadOptions({ payload: fixture });
  const body = withRestEnvelopeMeta(analyze(parsed.payload, parsed.options));

  assert.equal(body.ok, true);
  assert.equal(body.api_version, REST_API_VERSION);
  assert.equal(body.schema_version, REST_SCHEMA_VERSION);
  assert.ok(body.topology);
  assert.ok(Array.isArray(body.topology.power_domains));
  assert.ok(Array.isArray(body.topology.signal_paths));
});

test("REST error envelope exposes stable code/message fields", () => {
  const body = errorEnvelope("rate_limited", "Rate limit exceeded. Try again shortly.", { request_id: "req-test-2" });
  assert.equal(body.ok, false);
  assert.equal(body.error.code, "rate_limited");
  assert.equal(typeof body.error.message, "string");
  assert.equal(body.request_id, "req-test-2");
});

test("MCP schemeta_compile returns structured content with version metadata", () => {
  const result = handleToolCall("schemeta_compile", { payload: fixture });
  const body = result.structuredContent;

  assert.equal(result.isError, false);
  assert.equal(body.ok, true);
  assert.equal(typeof body.api_version, "string");
  assert.equal(typeof body.schema_version, "string");
  assert.equal(typeof body.svg, "string");
});

test("MCP schemeta_analyze returns structured topology fields", () => {
  const result = handleToolCall("schemeta_analyze", { payload: fixture });
  const body = result.structuredContent;

  assert.equal(result.isError, false);
  assert.equal(body.ok, true);
  assert.equal(typeof body.api_version, "string");
  assert.equal(typeof body.schema_version, "string");
  assert.ok(body.topology);
  assert.ok(Array.isArray(body.topology.power_domains));
});

test("MCP UI bundle and tool list contracts remain stable", () => {
  const ui = uiBundleDescriptor();
  assert.equal(ui.transport, "iframe");
  assert.equal(typeof ui.api_version, "string");
  assert.equal(typeof ui.schema_version, "string");

  const tools = toolListResult();
  assert.ok(Array.isArray(tools.tools));
  assert.ok(tools.tools.some((t) => t.name === "schemeta_compile"));
  assert.ok(tools.tools.some((t) => t.name === "schemeta_analyze"));
  assert.ok(tools.tools.some((t) => t.name === "schemeta_ui_bundle"));
});
