import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { createSystemdUnitContent, handleCliCommand, readPackageVersion, } from "./cli-commands.js";
const tempRoots = [];
function createPackageRoot(version = "9.8.7") {
    const root = mkdtempSync(path.join(os.tmpdir(), "aws-bridge-cli-"));
    tempRoots.push(root);
    mkdirSync(root, { recursive: true });
    writeFileSync(path.join(root, "package.json"), JSON.stringify({ name: "aws-runtime-bridge", version }), "utf-8");
    return root;
}
function createServiceUnitPath() {
    const root = mkdtempSync(path.join(os.tmpdir(), "aws-bridge-service-"));
    tempRoots.push(root);
    return path.join(root, "systemd", "awsb.service");
}
function quotedSystemdArg(value) {
    return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
}
afterEach(() => {
    for (const root of tempRoots.splice(0)) {
        rmSync(root, { recursive: true, force: true });
    }
});
describe("cli commands", () => {
    it("reads package version from package root", () => {
        const packageRoot = createPackageRoot("1.2.3");
        expect(readPackageVersion(packageRoot)).toBe("1.2.3");
    });
    it("prints version for -v", async () => {
        const packageRoot = createPackageRoot("1.2.3");
        const output = [];
        const result = await handleCliCommand({
            argv: ["-v"],
            packageRoot,
            stdout: (message) => output.push(message),
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(output).toEqual(["aws-runtime-bridge 1.2.3"]);
    });
    it("prints version for version command", async () => {
        const packageRoot = createPackageRoot("2.0.0");
        const output = [];
        const result = await handleCliCommand({
            argv: ["version"],
            packageRoot,
            stdout: (message) => output.push(message),
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(output).toEqual(["aws-runtime-bridge 2.0.0"]);
    });
    it("runs npm global update for update command", async () => {
        const output = [];
        const commands = [];
        const result = await handleCliCommand({
            argv: ["update"],
            stdout: (message) => output.push(message),
            runCommand: (command, args) => {
                commands.push({ command, args });
                return { status: 0 };
            },
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(commands).toEqual([
            { command: "npm", args: ["install", "-g", "aws-runtime-bridge@latest"] },
        ]);
        expect(output.at(-1)).toBe("[runtime-bridge] 更新完成。请重新运行 awsb -v 查看当前版本。");
    });
    it("returns npm exit code when update fails", async () => {
        const errors = [];
        const result = await handleCliCommand({
            argv: ["update"],
            stdout: () => undefined,
            stderr: (message) => errors.push(message),
            runCommand: () => ({ status: 7 }),
        });
        expect(result).toEqual({ handled: true, exitCode: 7 });
        expect(errors).toEqual(["[runtime-bridge] 更新失败，npm 退出码: 7"]);
    });
    it("runs interactive config command", async () => {
        const result = await handleCliCommand({
            argv: ["config"],
            configure: async () => "configured",
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
    });
    it("returns non-zero when config command fails", async () => {
        const result = await handleCliCommand({
            argv: ["config"],
            configure: async () => "failed",
        });
        expect(result).toEqual({ handled: true, exitCode: 1 });
    });
    it("creates a systemd unit that starts the current executable with setup skipped", () => {
        const executablePath = "/opt/aws-runtime-bridge/dist/index.js";
        const unit = createSystemdUnitContent(executablePath);
        expect(unit).toContain("Description=AgentsWorkStudio Runtime Bridge");
        expect(unit).toContain("Environment=AWS_BRIDGE_SKIP_SETUP=true");
        expect(unit).toContain(`ExecStart=${quotedSystemdArg(process.execPath)} ${quotedSystemdArg(executablePath)}`);
        expect(unit).toContain("Restart=on-failure");
        expect(unit).toContain("WantedBy=multi-user.target");
    });
    it("installs service, enables autostart, and starts when inactive", async () => {
        const output = [];
        const commands = [];
        const serviceUnitPath = createServiceUnitPath();
        const executablePath = "/usr/local/bin/awsb";
        const result = await handleCliCommand({
            argv: ["service", "install"],
            platform: "linux",
            serviceUnitPath,
            executablePath,
            stdout: (message) => output.push(message),
            runCommand: (command, args) => {
                commands.push({ command, args });
                if (args[0] === "is-active") {
                    return { status: 3 };
                }
                return { status: 0 };
            },
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(readFileSync(serviceUnitPath, "utf-8")).toContain(`ExecStart=${quotedSystemdArg(process.execPath)} ${quotedSystemdArg(executablePath)}`);
        expect(commands).toEqual([
            { command: "systemctl", args: ["daemon-reload"] },
            { command: "systemctl", args: ["enable", "awsb.service"] },
            { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
            { command: "systemctl", args: ["start", "awsb.service"] },
        ]);
        expect(output.at(-1)).toBe("[runtime-bridge] awsb systemd 服务已安装、已启用开机自启并已启动。");
    });
    it("does not start service during install when it is already active", async () => {
        const commands = [];
        const serviceUnitPath = createServiceUnitPath();
        const result = await handleCliCommand({
            argv: ["service", "install"],
            platform: "linux",
            serviceUnitPath,
            executablePath: "/usr/local/bin/awsb",
            runCommand: (command, args) => {
                commands.push({ command, args });
                return { status: 0 };
            },
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(commands).toEqual([
            { command: "systemctl", args: ["daemon-reload"] },
            { command: "systemctl", args: ["enable", "awsb.service"] },
            { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
        ]);
    });
    it("uninstalls service by stopping, disabling, removing unit, and reloading systemd", async () => {
        const output = [];
        const commands = [];
        const serviceUnitPath = createServiceUnitPath();
        mkdirSync(path.dirname(serviceUnitPath), { recursive: true });
        writeFileSync(serviceUnitPath, "unit", "utf-8");
        const result = await handleCliCommand({
            argv: ["service", "uninstall"],
            platform: "linux",
            serviceUnitPath,
            stdout: (message) => output.push(message),
            runCommand: (command, args) => {
                commands.push({ command, args });
                return { status: 0 };
            },
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(existsSync(serviceUnitPath)).toBe(false);
        expect(commands).toEqual([
            { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
            { command: "systemctl", args: ["stop", "awsb.service"] },
            { command: "systemctl", args: ["disable", "awsb.service"] },
            { command: "systemctl", args: ["daemon-reload"] },
        ]);
        expect(output.at(-1)).toBe("[runtime-bridge] awsb systemd 服务已卸载。");
    });
    it("tolerates uninstall when service is inactive and unit is absent", async () => {
        const output = [];
        const commands = [];
        const serviceUnitPath = createServiceUnitPath();
        const result = await handleCliCommand({
            argv: ["service", "uninstall"],
            platform: "linux",
            serviceUnitPath,
            stdout: (message) => output.push(message),
            runCommand: (command, args) => {
                commands.push({ command, args });
                if (args[0] === "is-active" || args[0] === "disable") {
                    return { status: 1 };
                }
                return { status: 0 };
            },
        });
        expect(result).toEqual({ handled: true, exitCode: 0 });
        expect(commands).toEqual([
            { command: "systemctl", args: ["is-active", "--quiet", "awsb.service"] },
            { command: "systemctl", args: ["disable", "awsb.service"] },
            { command: "systemctl", args: ["daemon-reload"] },
        ]);
        expect(output).toContain("[runtime-bridge] awsb systemd unit 不存在，跳过删除。");
    });
    it("fails service commands clearly on non-linux platforms", async () => {
        const errors = [];
        const result = await handleCliCommand({
            argv: ["service", "install"],
            platform: "win32",
            stderr: (message) => errors.push(message),
        });
        expect(result).toEqual({ handled: true, exitCode: 1 });
        expect(errors).toEqual([
            "[runtime-bridge] service 命令仅支持 Linux systemd 环境。",
        ]);
    });
    it("prints service help for missing subcommand", async () => {
        const output = [];
        const result = await handleCliCommand({
            argv: ["service"],
            stdout: (message) => output.push(message),
        });
        expect(result).toEqual({ handled: true, exitCode: 1 });
        expect(output).toEqual(["Usage: awsb service <install|uninstall>"]);
    });
    it("does not handle normal startup arguments", async () => {
        const result = await handleCliCommand({ argv: [] });
        expect(result).toEqual({ handled: false, exitCode: 0 });
    });
});
