import { describe, expect, it, vi } from "vitest";
import { buildTestCtx } from "../auto-reply/reply/test-ctx.js";
import { createHookRunnerWithRegistry } from "./hooks.test-helpers.js";

const replyDispatchEvent = {
  ctx: buildTestCtx({ SessionKey: "agent:test:session", BodyForAgent: "hello" }),
  sessionKey: "agent:test:session",
  inboundAudio: false,
  shouldRouteToOriginating: false,
  shouldSendToolSummaries: true,
  sendPolicy: "allow" as const,
};

const replyDispatchCtx = {
  cfg: {},
  dispatcher: {
    sendToolResult: () => false,
    sendBlockReply: () => false,
    sendFinalReply: () => false,
    waitForIdle: async () => {},
    getQueuedCounts: () => ({ tool: 0, block: 0, final: 0 }),
    getFailedCounts: () => ({ tool: 0, block: 0, final: 0 }),
    markComplete: () => {},
  },
  recordProcessed: () => {},
  markIdle: () => {},
};

describe("reply_dispatch hook runner", () => {
  it("stops at the first handler that claims reply dispatch", async () => {
    const first = vi.fn().mockResolvedValue({
      handled: true,
      queuedFinal: true,
      counts: { tool: 0, block: 1, final: 1 },
    });
    const second = vi.fn().mockResolvedValue({
      handled: true,
      queuedFinal: false,
      counts: { tool: 0, block: 0, final: 0 },
    });
    const { runner } = createHookRunnerWithRegistry([
      { hookName: "reply_dispatch", handler: first },
      { hookName: "reply_dispatch", handler: second },
    ]);

    const result = await runner.runReplyDispatch(replyDispatchEvent, replyDispatchCtx);

    expect(result).toEqual({
      handled: true,
      queuedFinal: true,
      counts: { tool: 0, block: 1, final: 1 },
    });
    expect(first).toHaveBeenCalledTimes(1);
    expect(second).not.toHaveBeenCalled();
  });

  it("continues to the next handler when a higher-priority handler throws", async () => {
    const logger = {
      warn: vi.fn(),
      error: vi.fn(),
    };
    const failing = vi.fn().mockRejectedValue(new Error("boom"));
    const succeeding = vi.fn().mockResolvedValue({
      handled: true,
      queuedFinal: false,
      counts: { tool: 1, block: 0, final: 0 },
    });
    const { runner } = createHookRunnerWithRegistry(
      [
        { hookName: "reply_dispatch", handler: failing },
        { hookName: "reply_dispatch", handler: succeeding },
      ],
      { logger },
    );

    const result = await runner.runReplyDispatch(replyDispatchEvent, replyDispatchCtx);

    expect(result).toEqual({
      handled: true,
      queuedFinal: false,
      counts: { tool: 1, block: 0, final: 0 },
    });
    expect(logger.error).toHaveBeenCalledWith(
      expect.stringContaining("reply_dispatch handler from test-plugin failed: Error: boom"),
    );
    expect(succeeding).toHaveBeenCalledTimes(1);
  });
});
