import { describe, expect, it } from "vitest";
import { isUiEnvelopeAllowed, parseUiEnvelope, parseUiRegistry } from "./validator";
import type { UIRegistry } from "./types";

const registry: UIRegistry = {
  schema_version: "agent-ui-registry@1",
  chart_grammars: ["echarts-safe-subset"],
  components: [{ id: "HistoryPanel", supportedSurfaces: ["side_panel", "canvas"] }],
  actions: [{ id: "zoom_to_map", supportedSurfaces: ["map_overlay"] }]
};

describe("UIEnvelope validation", () => {
  it("fails closed when the backend registry is unavailable", () => {
    const envelope = parseUiEnvelope({
      kind: "chart",
      schemaVersion: "agent-ui@1",
      grammar: "echarts-safe-subset",
      surface: "chat_inline",
      spec: { chart_type: "line" },
      data: { x_data: ["a"], series: [{ name: "s", data: [1] }] }
    });
    expect(envelope).not.toBeNull();
    expect(envelope ? isUiEnvelopeAllowed(envelope, null) : true).toBe(false);
  });

  it("rejects registered components outside the frontend allowlist", () => {
    const envelope = parseUiEnvelope({
      kind: "registered_component",
      schemaVersion: "agent-ui@1",
      component: "UnsafePanel",
      surface: "side_panel",
      props: {}
    });

    expect(envelope).toBeNull();
  });

  it("rejects registered components on unsupported surfaces", () => {
    const envelope = parseUiEnvelope({
      kind: "registered_component",
      schemaVersion: "agent-ui@1",
      component: "HistoryPanel",
      surface: "chat_inline",
      props: { feature_infos: [["J1", "junction"]], data_type: "realtime" }
    });

    expect(envelope).not.toBeNull();
    expect(envelope ? isUiEnvelopeAllowed(envelope, registry) : false).toBe(false);
  });

  it("accepts only the echarts-safe-subset chart grammar", () => {
    expect(
      parseUiEnvelope({
        kind: "chart",
        schemaVersion: "agent-ui@1",
        grammar: "vega-lite",
        surface: "chat_inline",
        spec: { chart_type: "line" },
        data: { x_data: ["a"], series: [{ name: "s", data: [1] }] }
      })
    ).toBeNull();

    const envelope = parseUiEnvelope({
      kind: "chart",
      schemaVersion: "agent-ui@1",
      grammar: "echarts-safe-subset",
      surface: "chat_inline",
      spec: { chart_type: "line" },
      data: { x_data: ["a"], series: [{ name: "s", data: [1] }] }
    });

    expect(envelope).not.toBeNull();
    expect(envelope ? isUiEnvelopeAllowed(envelope, registry) : false).toBe(true);
  });

  it("rejects unsupported chart types and mismatched data", () => {
    expect(parseUiEnvelope({
      kind: "chart",
      schemaVersion: "agent-ui@1",
      grammar: "echarts-safe-subset",
      surface: "chat_inline",
      spec: { chart_type: "pie" },
      data: { x_data: ["a"], series: [{ name: "s", data: [1] }] }
    })).toBeNull();
    expect(parseUiEnvelope({
      kind: "chart",
      schemaVersion: "agent-ui@1",
      grammar: "echarts-safe-subset",
      surface: "chat_inline",
      spec: { chart_type: "line" },
      data: { x_data: ["a", "b"], series: [{ name: "s", data: [1] }] }
    })).toBeNull();
  });

  it("filters invalid registry surfaces before allowlist checks", () => {
    const parsed = parseUiRegistry({
      schema_version: "agent-ui-registry@1",
      chart_grammars: ["echarts-safe-subset"],
      components: [{ id: "HistoryPanel", supportedSurfaces: ["side_panel", "unsafe_surface"] }],
      actions: []
    });

    expect(parsed?.components[0]?.supportedSurfaces).toEqual(["side_panel"]);
  });
});
