// Build the Fabric slash-command catalog from OpenClaw's native-command
// specs (the same source Discord uses to register slash commands) and push
// it to each connected guild. Fabric is a TEXT-command surface: a /<cmd>
// message is delivered normally and OpenClaw's command system executes it —
// this catalog only drives the frontend `/` autocomplete, so we resolve any
// dynamic arg `choices` to a static snapshot here (like Discord does at
// registration time).
import { listNativeCommandSpecsForConfig, findCommandByNativeName, resolveCommandArgChoices, } from 'openclaw/plugin-sdk/native-command-registry';
function normChoice(c) {
    if (typeof c === 'string')
        return { value: c, label: c };
    const o = c;
    return { value: String(o.value ?? ''), label: String(o.label ?? o.value ?? '') };
}
export function buildFabricCommandSpecs(cfg) {
    const specs = listNativeCommandSpecsForConfig(cfg, {
        provider: 'fabric',
    });
    return specs.map((s) => {
        // ChatCommandDefinition (for argsParsing + dynamic choices provider)
        const def = findCommandByNativeName(s.name, 'fabric');
        const args = (s.args ?? []).map((a) => {
            const raw = a.choices;
            let choices = null;
            if (Array.isArray(raw)) {
                choices = raw.map(normChoice);
            }
            else if (typeof raw === 'function' && def) {
                try {
                    const r = resolveCommandArgChoices({
                        command: def,
                        arg: a,
                        cfg: cfg,
                        provider: 'fabric',
                    });
                    choices = r.map((x) => ({ value: x.value, label: x.label }));
                }
                catch {
                    choices = null;
                }
            }
            return {
                name: String(a.name ?? ''),
                description: String(a.description ?? ''),
                type: String(a.type ?? 'string'),
                required: !!a.required,
                captureRemaining: !!a.captureRemaining,
                preferAutocomplete: !!a.preferAutocomplete,
                choices,
            };
        });
        return {
            name: s.name,
            nativeName: s.name,
            description: s.description,
            acceptsArgs: !!s.acceptsArgs,
            args,
            argsParsing: def?.argsParsing ?? 'positional',
        };
    });
}
// Push the catalog to every guild the known agents belong to (idempotent;
// the catalog is OpenClaw-global, so one PUT per guild is enough).
export async function syncFabricCommands(client, cfg, accounts, log) {
    let specs;
    try {
        specs = buildFabricCommandSpecs(cfg);
    }
    catch (err) {
        log.warn(`fabric: build command specs failed: ${String(err)}`);
        return;
    }
    if (!specs.length)
        return;
    const done = new Set();
    for (const a of accounts) {
        let session;
        try {
            session = await client.agentLogin(a.fabricApiKey);
        }
        catch {
            continue;
        }
        for (const g of session.guilds) {
            if (done.has(g.nodeId))
                continue;
            const tok = session.guildAccessTokens.find((t) => t.guildNodeId === g.nodeId)?.token;
            if (!tok)
                continue;
            try {
                await client.syncCommands(g.endpoint, tok, specs);
                done.add(g.nodeId);
                log.info(`fabric: synced ${specs.length} slash command(s) -> ${g.nodeId}`);
            }
            catch (err) {
                log.warn(`fabric: command sync failed ${g.nodeId}: ${String(err)}`);
            }
        }
    }
}
