import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../../config/config.js";

const buildGatewayInstallPlan = vi.hoisted(() => vi.fn());
const gatewayInstallErrorHint = vi.hoisted(() => vi.fn(() => "hint"));
const resolveGatewayInstallToken = vi.hoisted(() => vi.fn());
const serviceInstall = vi.hoisted(() => vi.fn(async () => {}));
const ensureSystemdUserLingerNonInteractive = vi.hoisted(() => vi.fn(async () => {}));

vi.mock("../../daemon-install-helpers.js", () => ({
  buildGatewayInstallPlan,
  gatewayInstallErrorHint,
}));

vi.mock("../../gateway-install-token.js", () => ({
  resolveGatewayInstallToken,
}));

vi.mock("../../../daemon/service.js", () => ({
  resolveGatewayService: vi.fn(() => ({
    install: serviceInstall,
  })),
}));

vi.mock("../../../daemon/systemd.js", () => ({
  isSystemdUserServiceAvailable: vi.fn(async () => true),
}));

vi.mock("../../daemon-runtime.js", () => ({
  DEFAULT_GATEWAY_DAEMON_RUNTIME: "node",
  isGatewayDaemonRuntime: vi.fn(() => true),
}));

vi.mock("../../systemd-linger.js", () => ({
  ensureSystemdUserLingerNonInteractive,
}));

const { installGatewayDaemonNonInteractive } = await import("./daemon-install.js");

describe("installGatewayDaemonNonInteractive", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    resolveGatewayInstallToken.mockResolvedValue({
      token: undefined,
      tokenRefConfigured: true,
      warnings: [],
    });
    buildGatewayInstallPlan.mockResolvedValue({
      programArguments: ["openclaw", "gateway", "run"],
      workingDirectory: "/tmp",
      environment: {},
    });
  });

  it("does not pass plaintext token for SecretRef-managed install", async () => {
    const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };

    await installGatewayDaemonNonInteractive({
      nextConfig: {
        gateway: {
          auth: {
            mode: "token",
            token: {
              source: "env",
              provider: "default",
              id: "OPENCLAW_GATEWAY_TOKEN",
            },
          },
        },
      } as OpenClawConfig,
      opts: { installDaemon: true },
      runtime,
      port: 18789,
    });

    expect(resolveGatewayInstallToken).toHaveBeenCalledTimes(1);
    expect(buildGatewayInstallPlan).toHaveBeenCalledTimes(1);
    expect("token" in buildGatewayInstallPlan.mock.calls[0][0]).toBe(false);
    expect(serviceInstall).toHaveBeenCalledTimes(1);
  });

  it("aborts with actionable error when SecretRef is unresolved", async () => {
    resolveGatewayInstallToken.mockResolvedValue({
      token: undefined,
      tokenRefConfigured: true,
      unavailableReason: "gateway.auth.token SecretRef is configured but unresolved (boom).",
      warnings: [],
    });
    const runtime = { log: vi.fn(), error: vi.fn(), exit: vi.fn() };

    await installGatewayDaemonNonInteractive({
      nextConfig: {} as OpenClawConfig,
      opts: { installDaemon: true },
      runtime,
      port: 18789,
    });

    expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Gateway install blocked"));
    expect(runtime.exit).toHaveBeenCalledWith(1);
    expect(buildGatewayInstallPlan).not.toHaveBeenCalled();
    expect(serviceInstall).not.toHaveBeenCalled();
  });
});
