import { DEFAULT_CHAT_CHANNEL } from "../channels/registry.js";
import { withProgress } from "../cli/progress.js";
import { loadConfig } from "../config/config.js";
import { resolveSessionKeyForRequest } from "./agent/session.js";
import { callGateway, randomIdempotencyKey } from "../gateway/call.js";
import { listAgentIds } from "../agents/agent-scope.js";
import { normalizeAgentId } from "../routing/session-key.js";
import { formatCliCommand } from "../cli/command-format.js";
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES, normalizeMessageChannel, } from "../utils/message-channel.js";
import { agentCommand } from "./agent.js";
function parseTimeoutSeconds(opts) {
    const raw = opts.timeout !== undefined
        ? Number.parseInt(String(opts.timeout), 10)
        : (opts.cfg.agents?.defaults?.timeoutSeconds ?? 600);
    if (Number.isNaN(raw) || raw <= 0) {
        throw new Error("--timeout must be a positive integer (seconds)");
    }
    return raw;
}
function formatPayloadForLog(payload) {
    const lines = [];
    if (payload.text)
        lines.push(payload.text.trimEnd());
    const mediaUrl = typeof payload.mediaUrl === "string" && payload.mediaUrl.trim()
        ? payload.mediaUrl.trim()
        : undefined;
    const media = payload.mediaUrls ?? (mediaUrl ? [mediaUrl] : []);
    for (const url of media)
        lines.push(`MEDIA:${url}`);
    return lines.join("\n").trimEnd();
}
export async function agentViaGatewayCommand(opts, runtime) {
    const body = (opts.message ?? "").trim();
    if (!body)
        throw new Error("Message (--message) is required");
    if (!opts.to && !opts.sessionId && !opts.agent) {
        throw new Error("Pass --to <E.164>, --session-id, or --agent to choose a session");
    }
    const cfg = loadConfig();
    const agentIdRaw = opts.agent?.trim();
    const agentId = agentIdRaw ? normalizeAgentId(agentIdRaw) : undefined;
    if (agentId) {
        const knownAgents = listAgentIds(cfg);
        if (!knownAgents.includes(agentId)) {
            throw new Error(`Unknown agent id "${agentIdRaw}". Use "${formatCliCommand("openclaw-cn agents list")}" to see configured agents.`);
        }
    }
    const timeoutSeconds = parseTimeoutSeconds({ cfg, timeout: opts.timeout });
    const gatewayTimeoutMs = Math.max(10_000, (timeoutSeconds + 30) * 1000);
    const sessionKey = resolveSessionKeyForRequest({
        cfg,
        agentId,
        to: opts.to,
        sessionId: opts.sessionId,
    }).sessionKey;
    const channel = normalizeMessageChannel(opts.channel) ?? DEFAULT_CHAT_CHANNEL;
    const idempotencyKey = opts.runId?.trim() || randomIdempotencyKey();
    const response = await withProgress({
        label: "Waiting for agent reply…",
        indeterminate: true,
        enabled: opts.json !== true,
    }, async () => await callGateway({
        method: "agent",
        params: {
            message: body,
            agentId,
            to: opts.to,
            replyTo: opts.replyTo,
            sessionId: opts.sessionId,
            sessionKey,
            thinking: opts.thinking,
            deliver: Boolean(opts.deliver),
            channel,
            replyChannel: opts.replyChannel,
            replyAccountId: opts.replyAccount,
            timeout: timeoutSeconds,
            lane: opts.lane,
            extraSystemPrompt: opts.extraSystemPrompt,
            idempotencyKey,
        },
        expectFinal: true,
        timeoutMs: gatewayTimeoutMs,
        clientName: GATEWAY_CLIENT_NAMES.CLI,
        mode: GATEWAY_CLIENT_MODES.CLI,
    }));
    if (opts.json) {
        runtime.log(JSON.stringify(response, null, 2));
        return response;
    }
    const result = response?.result;
    const payloads = result?.payloads ?? [];
    if (payloads.length === 0) {
        runtime.log(response?.summary ? String(response.summary) : "No reply from agent.");
        return response;
    }
    for (const payload of payloads) {
        const out = formatPayloadForLog(payload);
        if (out)
            runtime.log(out);
    }
    return response;
}
export async function agentCliCommand(opts, runtime, deps) {
    const localOpts = {
        ...opts,
        agentId: opts.agent,
        replyAccountId: opts.replyAccount,
    };
    if (opts.local === true) {
        return await agentCommand(localOpts, runtime, deps);
    }
    try {
        return await agentViaGatewayCommand(opts, runtime);
    }
    catch (err) {
        runtime.error?.(`Gateway agent failed; falling back to embedded: ${String(err)}`);
        return await agentCommand(localOpts, runtime, deps);
    }
}
