// Pure-protocol tests for OpenClaw-specific surface.
//
// Deliberately does not import from `./accounts.js` so it runs without the
// `openclaw` peer dependency installed. The account resolution tests live
// in `accounts.test.ts` — those require a real OpenClaw install.
//
// Wire-shared protocol pieces (subject builders, envelope decoder, chunk
// encoder, heartbeat payload, base64 / filename safety, service-name
// constants, max_payload formatting) now live in `@synadia-ai/agents` and
// are exercised by that package's test suite. This file only covers what's
// genuinely OpenClaw-flavoured.

import { describe, it, expect } from "vitest";
import { AgentSubject } from "@synadia-ai/agents";
import {
  AGENT_ID,
  DEFAULT_SESSION,
  SUBJECT_AGENT_TOKEN,
  fromNatsHeaders,
  outboundSubject,
  toNatsHeaders,
} from "./nats/protocol.js";

describe("OpenClaw agent identity (Appendix C)", () => {
  it("declares the canonical metadata.agent value", () => {
    expect(AGENT_ID).toBe("openclaw");
  });

  it("declares the conventional subject abbreviation `oc`", () => {
    expect(SUBJECT_AGENT_TOKEN).toBe("oc");
  });

  it("ships a `default` session for session-less harnesses (Appendix C)", () => {
    expect(DEFAULT_SESSION).toBe("default");
  });
});

describe("AgentSubject with OpenClaw's token split", () => {
  it("places the abbreviation in the subject and keeps the canonical name in metadata", () => {
    const s = AgentSubject.new(AGENT_ID, "acme", "echo", { subjectToken: SUBJECT_AGENT_TOKEN });
    expect(s.agent).toBe("openclaw");
    expect(s.subjectToken).toBe("oc");
    expect(s.prompt).toBe("agents.prompt.oc.acme.echo");
    expect(s.heartbeat).toBe("agents.hb.oc.acme.echo");
    expect(s.status).toBe("agents.status.oc.acme.echo");
  });
});

describe("outboundSubject — OpenClaw extension (not protocol-defined)", () => {
  it("nests under the abbreviation token, off the verb-first protocol slots", () => {
    expect(outboundSubject("acme", "echo")).toBe("agents.oc.acme.echo.outbound");
  });
});

describe("NATS header sugar", () => {
  it("round-trips a flat header map (NATS preserves the original case)", () => {
    const hdrs = toNatsHeaders({ "X-OC-Foo": "bar", "X-OC-Baz": "qux" });
    expect(fromNatsHeaders(hdrs)).toEqual({ "X-OC-Foo": "bar", "X-OC-Baz": "qux" });
  });

  it("returns an empty object for undefined headers", () => {
    expect(fromNatsHeaders(undefined)).toEqual({});
  });
});
