import type { ExecApprovalReplyDecision } from "openclaw/plugin-sdk/infra-runtime";
import { beforeEach, describe, expect, it, vi } from "vitest";

const approvalGatewayRuntimeHoisted = vi.hoisted(() => ({
  resolveApprovalOverGatewaySpy: vi.fn(),
}));

vi.mock("openclaw/plugin-sdk/approval-gateway-runtime", () => ({
  resolveApprovalOverGateway: (...args: unknown[]) =>
    approvalGatewayRuntimeHoisted.resolveApprovalOverGatewaySpy(...args),
}));

describe("resolveTelegramExecApproval", () => {
  async function invokeResolver(params: {
    approvalId: string;
    decision: ExecApprovalReplyDecision;
    senderId: string;
    allowPluginFallback?: boolean;
  }) {
    const { resolveTelegramExecApproval } = await import("./exec-approval-resolver.js");

    await resolveTelegramExecApproval({
      cfg: {} as never,
      gatewayUrl: undefined,
      ...params,
    });
  }

  function expectApprovalGatewayCall(params: {
    approvalId: string;
    decision: ExecApprovalReplyDecision;
    senderId: string;
    allowPluginFallback?: boolean;
  }) {
    expect(approvalGatewayRuntimeHoisted.resolveApprovalOverGatewaySpy).toHaveBeenCalledWith({
      cfg: {} as never,
      approvalId: params.approvalId,
      decision: params.decision,
      senderId: params.senderId,
      gatewayUrl: undefined,
      allowPluginFallback: params.allowPluginFallback,
      clientDisplayName: `Telegram approval (${params.senderId})`,
    });
  }

  beforeEach(() => {
    approvalGatewayRuntimeHoisted.resolveApprovalOverGatewaySpy
      .mockReset()
      .mockResolvedValue(undefined);
  });

  it("routes plugin approval ids through plugin.approval.resolve", async () => {
    await invokeResolver({
      approvalId: "plugin:abc123",
      decision: "allow-once",
      senderId: "9",
    });

    expectApprovalGatewayCall({
      approvalId: "plugin:abc123",
      decision: "allow-once",
      senderId: "9",
    });
  });

  it.each([
    "falls back to plugin.approval.resolve when exec approval ids are unknown",
    "falls back to plugin.approval.resolve for structured approval-not-found errors",
  ])("%s", async () => {
    await invokeResolver({
      approvalId: "legacy-plugin-123",
      decision: "allow-always",
      senderId: "9",
      allowPluginFallback: true,
    });

    expectApprovalGatewayCall({
      approvalId: "legacy-plugin-123",
      decision: "allow-always",
      senderId: "9",
      allowPluginFallback: true,
    });
  });

  it("passes fallback disablement through unchanged", async () => {
    await invokeResolver({
      approvalId: "legacy-plugin-123",
      decision: "allow-always",
      senderId: "9",
    });

    expectApprovalGatewayCall({
      approvalId: "legacy-plugin-123",
      decision: "allow-always",
      senderId: "9",
    });
  });
});
