/**
 * Switch skillset flow module
 *
 * Provides the complete interactive switch-skillset experience using @clack/prompts.
 * This flow handles:
 * - Broadcasting switch to all configured agents
 * - Local change detection and handling (proceed, capture, abort)
 * - Switch confirmation with current/new skillset info
 * - Spinner during switch and reinstall
 */
import { select, confirm, text, spinner, note, cancel } from "@clack/prompts";
import { AgentRegistry } from "../../../cli/features/agentRegistry.js";
import { bold, brightCyan, green } from "../../../cli/logger.js";
import { validateSkillsetName } from "../../../cli/prompts/validators.js";
import { formatDiffForNote } from "./diffFormat.js";
import { unwrapPrompt } from "./utils.js";
/**
 * Build a summary of changed files for display in a note
 *
 * @param args - Configuration arguments
 * @param args.diff - The manifest diff containing modified, added, and deleted files
 *
 * @returns Formatted string summarizing the changes
 */
const buildChangesSummary = (args) => {
    const { diff } = args;
    const lines = [];
    if (diff.modified.length > 0) {
        lines.push(`Modified (${diff.modified.length}):`);
        for (const file of diff.modified.slice(0, 5)) {
            lines.push(`  ${file}`);
        }
        if (diff.modified.length > 5) {
            lines.push(`  ... and ${diff.modified.length - 5} more`);
        }
    }
    if (diff.added.length > 0) {
        lines.push(`Added (${diff.added.length}):`);
        for (const file of diff.added.slice(0, 5)) {
            lines.push(`  ${file}`);
        }
        if (diff.added.length > 5) {
            lines.push(`  ... and ${diff.added.length - 5} more`);
        }
    }
    if (diff.deleted.length > 0) {
        lines.push(`Deleted (${diff.deleted.length}):`);
        for (const file of diff.deleted.slice(0, 5)) {
            lines.push(`  ${file}`);
        }
        if (diff.deleted.length > 5) {
            lines.push(`  ... and ${diff.deleted.length - 5} more`);
        }
    }
    return lines.join("\n");
};
/**
 * Execute the interactive switch skillset flow
 *
 * Broadcasts the switch to all resolved agents (no agent selection prompt).
 *
 * @param args - Flow configuration
 * @param args.skillsetName - The skillset name to switch to
 * @param args.installDir - Installation directory
 * @param args.callbacks - Callback functions for side-effectful operations
 *
 * @returns Result on success, null on cancel or abort
 */
export const switchSkillsetFlow = async (args) => {
    const { skillsetName, installDir, callbacks } = args;
    const cancelMsg = "Skillset switch cancelled.";
    // Step 1: Resolve all agents (broadcast to all, no selection prompt)
    const agents = await callbacks.onResolveAgents();
    const agentNames = agents.length > 0
        ? agents.map((a) => a.name)
        : [AgentRegistry.getInstance().getDefaultAgentName()];
    const agentName = agentNames[0];
    // Step 2: Prepare switch info for all agents (detect local changes + get current skillset)
    let currentProfile = null;
    let localChanges = null;
    for (const name of agentNames) {
        const info = await callbacks.onPrepareSwitchInfo({
            installDir,
            agentName: name,
        });
        if (currentProfile == null && info.currentProfile != null) {
            currentProfile = info.currentProfile;
        }
        if (info.localChanges != null) {
            if (localChanges == null) {
                localChanges = {
                    modified: [...info.localChanges.modified],
                    added: [...info.localChanges.added],
                    deleted: [...info.localChanges.deleted],
                };
            }
            else {
                localChanges.modified.push(...info.localChanges.modified);
                localChanges.added.push(...info.localChanges.added);
                localChanges.deleted.push(...info.localChanges.deleted);
            }
        }
    }
    if (localChanges != null) {
        const summary = buildChangesSummary({ diff: localChanges });
        note(summary, "Local Changes Detected");
        const hasModified = localChanges.modified.length > 0;
        const hasViewDiff = hasModified && callbacks.onReadFileDiff != null;
        let changeAction = null;
        while (changeAction == null || changeAction === "viewDiff") {
            const options = [
                {
                    value: "proceed",
                    label: "Proceed anyway",
                    hint: "changes will be lost",
                },
                {
                    value: "capture",
                    label: "Save current config as new skillset first",
                },
                ...(hasViewDiff
                    ? [
                        {
                            value: "viewDiff",
                            label: "View changes",
                            hint: "see what was modified",
                        },
                    ]
                    : []),
                { value: "abort", label: "Abort" },
            ];
            changeAction = unwrapPrompt({
                value: await select({
                    message: "How would you like to proceed?",
                    options,
                }),
                cancelMessage: cancelMsg,
            });
            if (changeAction == null)
                return null;
            if (changeAction === "viewDiff") {
                let selectedFile = null;
                if (localChanges.modified.length === 1) {
                    selectedFile = localChanges.modified[0];
                }
                else {
                    selectedFile = unwrapPrompt({
                        value: await select({
                            message: "Which file would you like to view?",
                            options: localChanges.modified.map((file) => ({
                                value: file,
                                label: file,
                            })),
                        }),
                        cancelMessage: cancelMsg,
                    });
                    if (selectedFile == null)
                        return null;
                }
                const diffResult = await callbacks.onReadFileDiff({
                    relativePath: selectedFile,
                    installDir,
                });
                if (diffResult == null) {
                    note("Diff not available for this file.", `Diff unavailable`);
                }
                else {
                    const diffContent = formatDiffForNote({
                        existingContent: diffResult.original,
                        localContent: diffResult.current,
                    });
                    note(diffContent, `Changes in "${selectedFile}"`);
                }
            }
        }
        if (changeAction === "abort") {
            cancel(cancelMsg);
            return null;
        }
        if (changeAction === "capture") {
            const skillsetName = unwrapPrompt({
                value: await text({
                    message: "Enter a name for this skillset",
                    placeholder: "my-skillset",
                    validate: (value) => validateSkillsetName({ value: value ?? "" }),
                }),
                cancelMessage: cancelMsg,
            });
            if (skillsetName == null)
                return null;
            const captureSpinner = spinner();
            captureSpinner.start("Saving current configuration...");
            await callbacks.onCaptureConfig({
                installDir,
                skillsetName: skillsetName,
            });
            captureSpinner.stop(`Saved as skillset: ${skillsetName}`);
        }
    }
    // Step 3: Show switch details and confirm
    const currentDisplay = currentProfile ?? "(none)";
    const agentDisplay = agentNames.length === 1 ? agentNames[0] : agentNames.join(", ");
    const detailLines = [
        `Install directory: ${installDir}`,
        `Agent: ${agentDisplay}`,
        `Current skillset: ${brightCyan({ text: bold({ text: currentDisplay }) })}`,
        `New skillset: ${green({ text: bold({ text: skillsetName }) })}`,
    ];
    note(detailLines.join("\n"), "Switching Skillset");
    const confirmed = unwrapPrompt({
        value: await confirm({
            message: `Switch to ${skillsetName}?`,
        }),
        cancelMessage: cancelMsg,
    });
    if (confirmed == null || !confirmed) {
        if (confirmed === false) {
            cancel(cancelMsg);
        }
        return null;
    }
    // Step 4: Re-download from registry (if callback provided)
    // The download flow handles its own "already-current" prompt, so no need to ask here.
    if (callbacks.onRedownload != null) {
        await callbacks.onRedownload({ skillsetName });
    }
    // Step 5: Perform the switch for all agents
    const s = spinner();
    s.start("Switching skillset...");
    for (const name of agentNames) {
        await callbacks.onExecuteSwitch({
            installDir,
            agentName: name,
            skillsetName,
        });
    }
    s.stop("Skillset switched");
    const successLines = [
        green({
            text: `Switched to ${bold({ text: skillsetName })} skillset for ${agentDisplay}.`,
        }),
        `Restart your agent instances to apply the new configuration.`,
    ];
    note(successLines.join("\n"), "Success");
    return {
        agentName,
        skillsetName,
        statusMessage: bold({ text: "Restart your agents to apply" }),
    };
};
//# sourceMappingURL=switchSkillset.js.map