"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.runSkillCommand = runSkillCommand;
const store_1 = require("../auth-profiles/store");
const control_plane_config_1 = require("../config/control-plane-config");
const fs_errors_1 = require("../core/fs-errors");
const catalog_1 = require("../i18n/catalog");
const catalog_2 = require("../skills/catalog");
const install_1 = require("../skills/install");
const resolution_issue_1 = require("../skills/resolution-issue");
const search_1 = require("../skills/search");
const runtime_1 = require("../worker/runtime");
const skill_inventory_1 = require("../workflows/skill-inventory");
const template_registry_1 = require("../workflows/template-registry");
const prompts_1 = require("./prompts");
const resolution_create_draft_1 = require("./resolution-create-draft");
const catalog_search_worker_1 = require("./catalog-search-worker");
const json_output_1 = require("./json-output");
async function runSkillCommand(cwd, args, deps = {}) {
    switch (args.action) {
        case "list":
            return runSkillListCommand(cwd, args, deps);
        case "search":
            return runSkillSearchCommand(cwd, args, deps);
        case "install":
            return runSkillInstallCommand(cwd, args, deps);
        case "create":
            return runSkillCreateCommand(cwd, args, deps);
        case "catalog":
            return runSkillCatalogCommand(cwd, args);
    }
}
async function runSkillListCommand(cwd, args, deps = {}) {
    const context = await loadSkillCommandContext(cwd, deps.homeDirectory);
    const workers = resolveSkillTargets(args.target, context.configuredWorkers);
    const result = await (0, skill_inventory_1.listAvailableSkills)({
        repoRoot: cwd,
        workers,
        configuredWorkers: context.configuredWorkers,
        authProfiles: context.authProfiles,
        ...(deps.homeDirectory === undefined
            ? {}
            : { homeDirectory: deps.homeDirectory }),
        includeExcluded: args.includeExcluded === true,
    });
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillSearchCommand(cwd, args, deps = {}) {
    const context = await loadSkillCommandContext(cwd, deps.homeDirectory);
    const targets = resolveSearchTargets(args.target, context.configuredWorkers);
    const baselineResult = await (0, search_1.searchSkills)({
        repoRoot: cwd,
        query: args.query,
        targets,
        mode: args.mode,
        configuredWorkers: context.configuredWorkers,
        authProfiles: context.authProfiles,
        includeExcluded: args.includeExcluded === true,
        ...(deps.homeDirectory === undefined
            ? {}
            : { homeDirectory: deps.homeDirectory }),
    });
    let result = baselineResult;
    if (args.withWorker === true) {
        const runtime = deps.workerRuntime ??
            (await (0, runtime_1.createConfiguredWorkerRuntime)(context.config, {
                ...(deps.homeDirectory === undefined
                    ? {}
                    : { homeDirectory: deps.homeDirectory }),
            }));
        const workerSelection = await (0, catalog_search_worker_1.runCatalogSearchWorkerSelection)({
            runtime,
            repositoryRoot: cwd,
            query: args.query,
            kind: "skill",
            mode: args.mode,
            target: (0, catalog_search_worker_1.renderCatalogSearchTarget)({ target: args.target, targets }),
            outputLanguage: context.configLocale,
        });
        if (workerSelection.kind === "selected") {
            const forcedResult = await (0, search_1.searchSkills)({
                repoRoot: cwd,
                query: args.query,
                targets,
                mode: args.mode,
                configuredWorkers: context.configuredWorkers,
                authProfiles: context.authProfiles,
                forcedIds: workerSelection.selected.map((item) => item.id),
                includeExcluded: args.includeExcluded === true,
                ...(deps.homeDirectory === undefined
                    ? {}
                    : { homeDirectory: deps.homeDirectory }),
            });
            const applied = (0, catalog_search_worker_1.applyCatalogSearchWorkerSelection)({
                items: forcedResult.items,
                selected: workerSelection.selected,
            });
            result =
                applied.rejected.length > 0
                    ? {
                        ...baselineResult,
                        worker: {
                            requested: true,
                            used: false,
                            selected: [],
                            fallbackReason: "invalid_worker_selection",
                        },
                    }
                    : {
                        ...forcedResult,
                        items: applied.items,
                        worker: {
                            requested: true,
                            used: true,
                            selected: applied.selected,
                            fallbackReason: null,
                        },
                    };
        }
        else {
            result = {
                ...baselineResult,
                worker: {
                    requested: true,
                    used: false,
                    selected: [],
                    fallbackReason: workerSelection.reason,
                },
            };
        }
    }
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillCatalogCommand(cwd, args) {
    switch (args.catalogAction) {
        case "list":
            return runSkillCatalogListCommand(cwd, args);
        case "add":
            return runSkillCatalogAddCommand(cwd, args);
        case "import-github":
            return runSkillCatalogImportGithubCommand(cwd, args);
        case "remove":
            return runSkillCatalogRemoveCommand(cwd, args);
    }
}
async function runSkillCatalogListCommand(cwd, args) {
    const result = await (0, catalog_2.listSkillCatalog)({
        repoRoot: cwd,
        includeSystem: args.includeSystem,
    });
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillCatalogAddCommand(cwd, args) {
    const result = await (0, catalog_2.addSkillCatalogEntry)({
        repoRoot: cwd,
        id: args.id,
        description: args.description,
        ...(args.defaultSource === undefined
            ? {}
            : { defaultSource: args.defaultSource }),
        ...(args.codexSource === undefined
            ? {}
            : { codexSource: args.codexSource }),
        ...(args.claudeSource === undefined
            ? {}
            : { claudeSource: args.claudeSource }),
    });
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillCatalogImportGithubCommand(cwd, args) {
    const result = await (0, catalog_2.importGithubSkillCatalogEntries)({
        repoRoot: cwd,
        repo: args.repo,
        path: args.path,
        ref: args.ref,
        target: args.target,
        overwrite: args.overwrite,
    });
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillCatalogRemoveCommand(cwd, args) {
    const result = await (0, catalog_2.removeSkillCatalogEntry)({
        repoRoot: cwd,
        id: args.id,
    });
    (0, json_output_1.printCommandJson)(result);
    return 0;
}
async function runSkillInstallCommand(cwd, args, deps) {
    const context = await loadSkillCommandContext(cwd, deps.homeDirectory);
    try {
        const result = await (0, install_1.installSkill)(buildSkillInstallInput(cwd, args, context, deps));
        (0, json_output_1.printCommandJson)(result);
        return 0;
    }
    catch (error) {
        if (error instanceof install_1.SkillInstallSelectionError) {
            const prompter = deps.prompter ?? (0, prompts_1.createCliPrompter)({ locale: context.configLocale });
            if (prompter.interactive) {
                const selectedItem = await selectSkillInstallItem(error.result, prompter, context.configLocale);
                const result = await (0, install_1.installSkill)({
                    ...buildSkillInstallInput(cwd, {
                        action: "install",
                        source: selectedItem.source,
                        target: args.target,
                        overwrite: args.overwrite,
                        pluginScope: args.pluginScope,
                    }, context, deps),
                    installId: selectedItem.id,
                });
                (0, json_output_1.printCommandJson)(result);
                return 0;
            }
            (0, json_output_1.printCommandJson)(error.result);
            return 0;
        }
        throw error;
    }
}
function buildSkillInstallInput(cwd, args, context, deps = {}) {
    assertConfiguredSkillTarget(args.target, context.configuredWorkers);
    return {
        repoRoot: cwd,
        target: args.target,
        ...(args.source === undefined ? {} : { source: args.source }),
        ...(args.query === undefined ? {} : { query: args.query }),
        overwrite: args.overwrite,
        pluginScope: args.pluginScope,
        includeExcluded: args.includeExcluded === true,
        configuredWorkers: context.configuredWorkers,
        authProfiles: context.authProfiles,
        ...(deps.homeDirectory === undefined
            ? {}
            : { homeDirectory: deps.homeDirectory }),
    };
}
async function selectSkillInstallItem(result, prompter, locale) {
    const [defaultItem] = result.items;
    if (!defaultItem) {
        throw new Error(`No installable skill found for query: ${result.query}`);
    }
    const selectedIndex = await prompter.select({
        label: (0, catalog_1.translate)(locale, "skill.command.install.prompt.selectSkill"),
        options: formatSkillInstallSelectionOptions(result.items),
        defaultValue: 0,
    });
    const selectedItem = result.items[selectedIndex];
    if (selectedItem === undefined) {
        throw new Error(`Invalid skill selection index: ${selectedIndex}`);
    }
    return selectedItem;
}
function formatSkillInstallSelectionOptions(items) {
    const baseLabels = items.map(formatSkillInstallSelectionBaseLabel);
    return items.map((item, index) => {
        const baseLabel = baseLabels[index] ?? formatSkillInstallSelectionBaseLabel(item);
        const duplicate = baseLabels.filter((label) => label === baseLabel).length > 1;
        return {
            value: index,
            label: duplicate ? `${baseLabel} [${item.source}]` : baseLabel,
        };
    });
}
function formatSkillInstallSelectionBaseLabel(item) {
    const suffix = item.description ? ` - ${item.description}` : "";
    return `${item.title} (${item.sourceKind})${suffix}`;
}
async function runSkillCreateCommand(cwd, args, deps = {}) {
    if (args.mode === "apply-draft") {
        const { runIssueCreateCommand } = await Promise.resolve().then(() => __importStar(require("./issue")));
        return runIssueCreateCommand(cwd, {
            action: "create",
            mode: "apply-draft",
            applyDraftPath: args.applyDraftPath,
            validateDraft: assertSkillResolutionDraft,
        }, deps);
    }
    const config = await (0, resolution_create_draft_1.loadResolutionCreateConfig)(cwd);
    const configuredWorkers = (0, control_plane_config_1.getConfiguredWorkerProviders)(config);
    assertConfiguredSkillCreateTarget(args.target, configuredWorkers);
    const configLocale = config.i18n.defaultLanguage;
    const workflowOptions = await resolveSkillResolutionWorkflowOptions(cwd, configLocale);
    const draft = await (0, resolution_create_draft_1.draftResolutionIssueFields)({
        config,
        cwd,
        kind: "skill",
        prompt: args.prompt,
        target: args.target,
        locale: configLocale,
        ...(deps.homeDirectory === undefined
            ? {}
            : { homeDirectory: deps.homeDirectory }),
    });
    const issueArgs = {
        action: "create",
        mode: "manual",
        title: draft.title,
        body: {
            kind: "text",
            text: (0, resolution_issue_1.buildSkillResolutionIssueBody)({
                capability: draft.capability,
                originalRequest: args.prompt,
                target: args.target,
                configuredWorkers,
                locale: configLocale,
                origin: (0, catalog_1.translate)(configLocale, "skill.resolution.origin.createdByCommand"),
            }),
        },
        assignees: [],
        labels: [],
        disabled: false,
        ...(args.saveDraft === true ? { saveDraft: true } : {}),
        ...(workflowOptions === undefined ? {} : { workflowOptions }),
    };
    const { runIssueCreateCommand } = await Promise.resolve().then(() => __importStar(require("./issue")));
    return runIssueCreateCommand(cwd, issueArgs, deps);
}
function assertSkillResolutionDraft(draftFile) {
    if (!(0, resolution_issue_1.isSkillResolutionIssueDraft)(draftFile)) {
        throw new Error("Skill create --apply-draft must be an alpaca skill-resolution issue draft bound to __system/skill-resolution.md.");
    }
}
async function loadSkillCommandContext(cwd, homeDirectory) {
    const config = await loadSkillCommandConfig(cwd);
    const configuredWorkers = [...(0, control_plane_config_1.getConfiguredWorkerProviders)(config)];
    const { profiles } = await (0, store_1.loadAuthProfiles)(homeDirectory);
    return {
        config,
        configuredWorkers,
        authProfiles: profiles,
        configLocale: config.i18n.defaultLanguage,
    };
}
async function loadSkillCommandConfig(cwd) {
    try {
        return await (0, control_plane_config_1.loadConfig)(cwd);
    }
    catch (error) {
        if ((0, fs_errors_1.isMissingFileError)(error)) {
            return control_plane_config_1.DEFAULT_CONFIG;
        }
        throw error;
    }
}
async function resolveSkillResolutionWorkflowOptions(cwd, configLocale) {
    const catalog = await (0, template_registry_1.loadWorkflowTemplates)((0, template_registry_1.getWorkflowTemplatesDirectoryPath)(cwd), configLocale);
    if (catalog?.templateByPath.has(resolution_issue_1.SKILL_RESOLUTION_SYSTEM_WORKFLOW_TEMPLATE) !==
        true) {
        return undefined;
    }
    return {
        workflowSelection: {
            mode: "template",
            templatePath: resolution_issue_1.SKILL_RESOLUTION_SYSTEM_WORKFLOW_TEMPLATE,
        },
    };
}
function resolveSearchTargets(target, configuredWorkers) {
    return resolveSkillTargets(target, configuredWorkers);
}
function resolveSkillTargets(target, configuredWorkers) {
    if (target === "all") {
        return [...configuredWorkers];
    }
    if (target !== undefined) {
        assertConfiguredSkillTarget(target, configuredWorkers);
        return [target];
    }
    return [...configuredWorkers];
}
function assertConfiguredSkillCreateTarget(target, configuredWorkers) {
    if (target !== "all") {
        assertConfiguredSkillTarget(target, configuredWorkers);
    }
}
function assertConfiguredSkillTarget(target, configuredWorkers) {
    if (!configuredWorkers.includes(target)) {
        throw new Error(`Worker is not configured: ${target}`);
    }
}
