import { describe, expect, it, vi } from "vitest";
import {
  PERMISSION_CHILD_CREATED_CHANNEL,
  PERMISSION_CHILD_DISPOSED_CHANNEL,
  registerPermissionChildSession,
  unregisterPermissionChildSession,
  withActiveAgentIdentity,
} from "../src/permission-system-bridge.js";

function session(id: string | undefined) {
  return { sessionManager: { getSessionId: () => id } } as any;
}

function publisher() {
  return { events: { emit: vi.fn() } } as any;
}

describe("permission-system child lifecycle bridge", () => {
  it("registers the child against the interactive root and disposes it once", () => {
    const pi = publisher();
    const child = session(" child-session ");

    expect(registerPermissionChildSession(pi, child, " root-session ")).toBe(true);
    expect(registerPermissionChildSession(pi, child, "root-session")).toBe(true);
    expect(pi.events.emit).toHaveBeenCalledTimes(1);
    expect(pi.events.emit).toHaveBeenNthCalledWith(1, PERMISSION_CHILD_CREATED_CHANNEL, {
      sessionId: "child-session",
      parentSessionId: "root-session",
    });

    unregisterPermissionChildSession(child);
    unregisterPermissionChildSession(child);
    expect(pi.events.emit).toHaveBeenCalledTimes(2);
    expect(pi.events.emit).toHaveBeenNthCalledWith(2, PERMISSION_CHILD_DISPOSED_CHANNEL, {
      sessionId: "child-session",
    });
  });

  it("does not claim integration without both session identities and an event bus", () => {
    expect(registerPermissionChildSession({} as any, session("child"), "root")).toBe(false);
    expect(registerPermissionChildSession(publisher(), session(undefined), "root")).toBe(false);
    expect(registerPermissionChildSession(publisher(), session("child"), "  ")).toBe(false);
  });

  it("fails child startup when a lifecycle subscriber rejects registration", () => {
    const pi = { events: { emit: vi.fn(() => { throw new Error("registry unavailable"); }) } } as any;
    expect(() => registerPermissionChildSession(pi, session("child"), "root"))
      .toThrow("registry unavailable");
  });

  it("replaces inherited identity with the stable child agent key", () => {
    expect(withActiveAgentIdentity(
      'parent\n<active_agent name="main-agent"/>\nchild instructions',
      "security-auditor",
    )).toBe('parent\nchild instructions\n\n<active_agent name="security-auditor"/>');
  });

  it("omits an unsafe agent key instead of emitting malformed identity markup", () => {
    expect(withActiveAgentIdentity("prompt", 'bad" name')).toBe("prompt");
  });
});
