import fs from "node:fs/promises";
import path from "node:path";
import { DEFAULT_BOOTSTRAP_FILENAME } from "../agents/workspace.js";
import { DEFAULT_GATEWAY_DAEMON_RUNTIME, GATEWAY_DAEMON_RUNTIME_OPTIONS, } from "../commands/daemon-runtime.js";
import { healthCommand } from "../commands/health.js";
import { formatHealthCheckFailure } from "../commands/health-format.js";
import { detectBrowserOpenSupport, formatControlUiSshHint, openUrl, openUrlInBackground, probeGatewayReachable, waitForGatewayReachable, resolveControlUiLinks, } from "../commands/onboard-helpers.js";
import { formatCliCommand } from "../cli/command-format.js";
import { resolveGatewayService } from "../daemon/service.js";
import { isSystemdUserServiceAvailable } from "../daemon/systemd.js";
import { ensureControlUiAssetsBuilt } from "../infra/control-ui-assets.js";
import { runTui } from "../tui/tui.js";
import { resolveUserPath } from "../utils.js";
import { buildGatewayInstallPlan, gatewayInstallErrorHint, } from "../commands/daemon-install-helpers.js";
export async function finalizeOnboardingWizard(options) {
    const { flow, opts, baseConfig, nextConfig, settings, prompter, runtime } = options;
    const withWizardProgress = async (label, options, work) => {
        const progress = prompter.progress(label);
        try {
            return await work(progress);
        }
        finally {
            progress.stop(options.doneMessage);
        }
    };
    const systemdAvailable = process.platform === "linux" ? await isSystemdUserServiceAvailable() : true;
    if (process.platform === "linux" && !systemdAvailable) {
        await prompter.note("Systemd user services are unavailable. Skipping lingering checks and service install.", "Systemd");
    }
    if (process.platform === "linux" && systemdAvailable) {
        const { ensureSystemdUserLingerInteractive } = await import("../commands/systemd-linger.js");
        await ensureSystemdUserLingerInteractive({
            runtime,
            prompter: {
                confirm: prompter.confirm,
                note: prompter.note,
            },
            reason: "Linux installs use a systemd user service by default. Without lingering, systemd stops the user session on logout/idle and kills the Gateway.",
            requireConfirm: false,
        });
    }
    const explicitInstallDaemon = typeof opts.installDaemon === "boolean" ? opts.installDaemon : undefined;
    let installDaemon;
    if (explicitInstallDaemon !== undefined) {
        installDaemon = explicitInstallDaemon;
    }
    else if (process.platform === "linux" && !systemdAvailable) {
        installDaemon = false;
    }
    else if (flow === "quickstart") {
        installDaemon = true;
    }
    else {
        installDaemon = await prompter.confirm({
            message: "安装网关服务（推荐）",
            initialValue: true,
        });
    }
    if (process.platform === "linux" && !systemdAvailable && installDaemon) {
        await prompter.note("Systemd user services are unavailable; skipping service install. Use your container supervisor or `docker compose up -d`.", "Gateway service");
        installDaemon = false;
    }
    if (installDaemon) {
        const daemonRuntime = flow === "quickstart"
            ? DEFAULT_GATEWAY_DAEMON_RUNTIME
            : (await prompter.select({
                message: "网关服务运行时",
                options: GATEWAY_DAEMON_RUNTIME_OPTIONS,
                initialValue: opts.daemonRuntime ?? DEFAULT_GATEWAY_DAEMON_RUNTIME,
            }));
        if (flow === "quickstart") {
            await prompter.note("快速开始为网关服务使用Node（稳定+支持）。", "Gateway service runtime");
        }
        const service = resolveGatewayService();
        const loaded = await service.isLoaded({ env: process.env });
        if (loaded) {
            const action = (await prompter.select({
                message: "网关服务已安装",
                options: [
                    { value: "restart", label: "重启" },
                    { value: "reinstall", label: "重新安装" },
                    { value: "skip", label: "跳过" },
                ],
            }));
            if (action === "restart") {
                await withWizardProgress("Gateway service", { doneMessage: "Gateway service restarted." }, async (progress) => {
                    progress.update("Restarting Gateway service…");
                    await service.restart({
                        env: process.env,
                        stdout: process.stdout,
                    });
                });
            }
            else if (action === "reinstall") {
                await withWizardProgress("Gateway service", { doneMessage: "Gateway service uninstalled." }, async (progress) => {
                    progress.update("Uninstalling Gateway service…");
                    await service.uninstall({ env: process.env, stdout: process.stdout });
                });
            }
        }
        if (!loaded || (loaded && (await service.isLoaded({ env: process.env })) === false)) {
            const progress = prompter.progress("Gateway service");
            let installError = null;
            try {
                progress.update("Preparing Gateway service…");
                const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
                    env: process.env,
                    port: settings.port,
                    token: settings.gatewayToken,
                    runtime: daemonRuntime,
                    warn: (message, title) => prompter.note(message, title),
                    config: nextConfig,
                });
                progress.update("Installing Gateway service…");
                await service.install({
                    env: process.env,
                    stdout: process.stdout,
                    programArguments,
                    workingDirectory,
                    environment,
                });
            }
            catch (err) {
                installError = err instanceof Error ? err.message : String(err);
            }
            finally {
                progress.stop(installError ? "网关服务安装失败。" : "网关服务已安装。");
            }
            if (installError) {
                await prompter.note(`Gateway service install failed: ${installError}`, "Gateway");
                await prompter.note(gatewayInstallErrorHint(), "Gateway");
            }
        }
    }
    if (!opts.skipHealth) {
        const probeLinks = resolveControlUiLinks({
            bind: nextConfig.gateway?.bind ?? "loopback",
            port: settings.port,
            customBindHost: nextConfig.gateway?.customBindHost,
            basePath: undefined,
        });
        // Daemon install/restart can briefly flap the WS; wait a bit so health check doesn't false-fail.
        await waitForGatewayReachable({
            url: probeLinks.wsUrl,
            token: settings.gatewayToken,
            deadlineMs: 15_000,
        });
        try {
            await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
        }
        catch (err) {
            runtime.error(formatHealthCheckFailure(err));
            await prompter.note([
                "Docs:",
                "https://docs.clawd.bot/gateway/health",
                "https://docs.clawd.bot/gateway/troubleshooting",
            ].join("\n"), "Health check help");
        }
    }
    const controlUiEnabled = nextConfig.gateway?.controlUi?.enabled ?? baseConfig.gateway?.controlUi?.enabled ?? true;
    if (!opts.skipUi && controlUiEnabled) {
        const controlUiAssets = await ensureControlUiAssetsBuilt(runtime);
        if (!controlUiAssets.ok && controlUiAssets.message) {
            runtime.error(controlUiAssets.message);
        }
    }
    await prompter.note([
        "为额外功能添加节点：",
        "- macOS应用（系统+通知）",
        "- iOS应用（相机/画布）",
        "- Android应用（相机/画布）",
    ].join("\n"), "可选应用");
    const controlUiBasePath = nextConfig.gateway?.controlUi?.basePath ?? baseConfig.gateway?.controlUi?.basePath;
    const links = resolveControlUiLinks({
        bind: settings.bind,
        port: settings.port,
        customBindHost: settings.customBindHost,
        basePath: controlUiBasePath,
    });
    const tokenParam = settings.authMode === "token" && settings.gatewayToken
        ? `?token=${encodeURIComponent(settings.gatewayToken)}`
        : "";
    const authedUrl = `${links.httpUrl}${tokenParam}`;
    const gatewayProbe = await probeGatewayReachable({
        url: links.wsUrl,
        token: settings.authMode === "token" ? settings.gatewayToken : undefined,
        password: settings.authMode === "password" ? nextConfig.gateway?.auth?.password : "",
    });
    const gatewayStatusLine = gatewayProbe.ok
        ? "网关：可访问"
        : `网关：未检测到${gatewayProbe.detail ? ` (${gatewayProbe.detail})` : ""}`;
    const bootstrapPath = path.join(resolveUserPath(options.workspaceDir), DEFAULT_BOOTSTRAP_FILENAME);
    const hasBootstrap = await fs
        .access(bootstrapPath)
        .then(() => true)
        .catch(() => false);
    await prompter.note([
        `网页界面：${links.httpUrl}`,
        tokenParam ? `网页界面（带令牌）：${authedUrl}` : undefined,
        `网关WS：${links.wsUrl}`,
        gatewayStatusLine,
        "文档：https://docs.clawd.bot/web/control-ui",
    ]
        .filter(Boolean)
        .join("\n"), "控制界面");
    let controlUiOpened = false;
    let controlUiOpenHint;
    let seededInBackground = false;
    let hatchChoice = null;
    if (!opts.skipUi && gatewayProbe.ok) {
        if (hasBootstrap) {
            await prompter.note([
                "这是定义性的操作，使您的智能体成为您的。",
                "请慢慢来。",
                "您告诉它的越多，体验就会越好。",
                '我们将发送："醒来吧，我的朋友！"',
            ].join("\n"), "启动TUI（最佳选项！）");
        }
        await prompter.note([
            "网关令牌：网关+控制界面的共享认证。",
            "存储在：~/.openclaw/openclaw.json（gateway.auth.token）或OPENCLAW_GATEWAY_TOKEN。",
            "网页界面在此浏览器的localStorage中存储副本（clawdbot.control.settings.v1）。",
            `随时获取带令牌的链接：${formatCliCommand("openclaw-cn dashboard --no-open")}`,
        ].join("\n"), "令牌");
        hatchChoice = (await prompter.select({
            message: "您想如何孵化您的机器人？",
            options: [
                { value: "tui", label: "在TUI中孵化（推荐）" },
                { value: "web", label: "打开网页界面" },
                { value: "later", label: "稍后执行" },
            ],
            initialValue: "tui",
        }));
        if (hatchChoice === "tui") {
            await runTui({
                url: links.wsUrl,
                token: settings.authMode === "token" ? settings.gatewayToken : undefined,
                password: settings.authMode === "password" ? nextConfig.gateway?.auth?.password : "",
                // Safety: onboarding TUI should not auto-deliver to lastProvider/lastTo.
                deliver: false,
                message: hasBootstrap ? "Wake up, my friend!" : undefined,
            });
            if (settings.authMode === "token" && settings.gatewayToken) {
                seededInBackground = await openUrlInBackground(authedUrl);
            }
            if (seededInBackground) {
                await prompter.note(`网页界面已在后台播种。稍后使用以下命令打开：${formatCliCommand("openclaw-cn dashboard --no-open")}`, "网页界面");
            }
        }
        else if (hatchChoice === "web") {
            const browserSupport = await detectBrowserOpenSupport();
            if (browserSupport.ok) {
                controlUiOpened = await openUrl(authedUrl);
                if (!controlUiOpened) {
                    controlUiOpenHint = formatControlUiSshHint({
                        port: settings.port,
                        basePath: controlUiBasePath,
                        token: settings.gatewayToken,
                    });
                }
            }
            else {
                controlUiOpenHint = formatControlUiSshHint({
                    port: settings.port,
                    basePath: controlUiBasePath,
                    token: settings.gatewayToken,
                });
            }
            await prompter.note([
                `Dashboard link (with token): ${authedUrl}`,
                controlUiOpened
                    ? "Opened in your browser. Keep that tab to control Clawdbot."
                    : "Copy/paste this URL in a browser on this machine to control Clawdbot.",
                controlUiOpenHint,
            ]
                .filter(Boolean)
                .join("\n"), "Dashboard ready");
        }
        else {
            await prompter.note(`当您准备就绪时：${formatCliCommand("openclaw-cn dashboard --no-open")}`, "稍后");
        }
    }
    else if (opts.skipUi) {
        await prompter.note("跳过控制界面/TUI提示。", "控制界面");
    }
    await prompter.note(["备份您的智能体工作区。", "文档：https://docs.clawd.bot/concepts/agent-workspace"].join("\n"), "工作区备份");
    await prompter.note("在您的计算机上运行智能体是有风险的——加强您的设置：https://docs.clawd.bot/security", "安全");
    const shouldOpenControlUi = !opts.skipUi &&
        settings.authMode === "token" &&
        Boolean(settings.gatewayToken) &&
        hatchChoice === null;
    if (shouldOpenControlUi) {
        const browserSupport = await detectBrowserOpenSupport();
        if (browserSupport.ok) {
            controlUiOpened = await openUrl(authedUrl);
            if (!controlUiOpened) {
                controlUiOpenHint = formatControlUiSshHint({
                    port: settings.port,
                    basePath: controlUiBasePath,
                    token: settings.gatewayToken,
                });
            }
        }
        else {
            controlUiOpenHint = formatControlUiSshHint({
                port: settings.port,
                basePath: controlUiBasePath,
                token: settings.gatewayToken,
            });
        }
        await prompter.note([
            `仪表盘链接（带令牌）：${authedUrl}`,
            controlUiOpened
                ? "已在浏览器中打开。保留该标签页以控制Clawdbot。"
                : "在此机器上的浏览器中复制/粘贴此URL以控制Clawdbot。",
            controlUiOpenHint,
        ]
            .filter(Boolean)
            .join("\n"), "仪表盘就绪");
    }
    const webSearchKey = (nextConfig.tools?.web?.search?.apiKey ?? "").trim();
    const webSearchEnv = (process.env.BRAVE_API_KEY ?? "").trim();
    const hasWebSearchKey = Boolean(webSearchKey || webSearchEnv);
    await prompter.note(hasWebSearchKey
        ? [
            "网络搜索已启用，因此您的智能体可以在需要时在线查找内容。",
            "",
            webSearchKey
                ? "API密钥：存储在配置中（tools.web.search.apiKey）。"
                : "API密钥：通过BRAVE_API_KEY环境变量提供（网关环境）。",
            "文档：https://docs.clawd.bot/tools/web",
        ].join("\n")
        : [
            "如果希望您的智能体能够搜索网络，则需要API密钥。",
            "",
            "Clawdbot使用Brave Search作为`web_search`工具。没有Brave Search API密钥，网络搜索将无法工作。",
            "",
            "交互式设置：",
            `- 运行：${formatCliCommand("openclaw-cn configure --section web")}`,
            "- 启用web_search并粘贴您的Brave Search API密钥",
            "",
            "替代方案：在网关环境中设置BRAVE_API_KEY（无需更改配置）。",
            "文档：https://docs.clawd.bot/tools/web",
        ].join("\n"), "网络搜索（可选）");
    await prompter.note('接下来：https://clawd.bot/showcase（"人们正在构建什么"）。', "接下来");
    await prompter.outro(controlUiOpened
        ? "安装引导完成。仪表盘已使用您的令牌打开；保留该标签页以控制Clawdbot。"
        : seededInBackground
            ? "安装引导完成。网页界面已在后台播种；随时使用上面的带令牌链接打开它。"
            : "安装引导完成。使用上面的带令牌仪表盘链接控制Clawdbot。");
}
