import { sanitizeErrorMessage } from "../../fs/sanitize-error.js";
import { showHelp } from "../help.js";
const agExplainHelp = {
    name: "ag-explain",
    summary: "parse and explain a shell command",
    usage: "ag-explain [--json] <command_string>",
    options: [
        "    --json        output raw AST in JSON format",
        "    --help        display this help and exit",
    ],
};
export const agExplainCommand = {
    name: "ag-explain",
    async execute(args, _ctx) {
        if (args.includes("--help") || args.includes("-h"))
            return showHelp(agExplainHelp);
        let useJson = false;
        const commandArgs = [];
        for (const arg of args) {
            if (arg === "--json") {
                useJson = true;
            }
            else {
                commandArgs.push(arg);
            }
        }
        const commandToExplain = commandArgs.join(" ");
        if (!commandToExplain) {
            return {
                stdout: "",
                stderr: "ag-explain: missing command string\n",
                exitCode: 2,
            };
        }
        try {
            const { parse } = await import("../../parser/parser.js");
            const ast = parse(commandToExplain);
            if (useJson) {
                return {
                    stdout: JSON.stringify(ast, (k, v) => (k === "parent" ? undefined : v), 2) +
                        "\n",
                    stderr: "",
                    exitCode: 0,
                };
            }
            let explanation = `--- Explanation for: ${commandToExplain} ---\n`;
            const explainNode = (node, indent = "") => {
                let text = "";
                if (!node)
                    return "";
                try {
                    switch (node.type) {
                        case "Script":
                            if (node.statements)
                                node.statements.forEach((s) => (text += explainNode(s, indent)));
                            break;
                        case "Statement":
                            if (node.pipelines)
                                node.pipelines.forEach((p) => (text += explainNode(p, indent)));
                            break;
                        case "Pipeline":
                            if (node.commands && node.commands.length > 1) {
                                text += `${indent}Pipeline with ${node.commands.length} stages:\n`;
                                node.commands.forEach((c, i) => {
                                    text += `${indent}  [Stage ${i + 1}]:\n`;
                                    text += explainNode(c, `${indent}    `);
                                });
                            }
                            else if (node.commands && node.commands.length === 1) {
                                text += explainNode(node.commands[0], indent);
                            }
                            break;
                        case "SimpleCommand":
                            text += `${indent}Execute command: '${node.name?.text || ""}'\n`;
                            if (node.args && node.args.length > 0) {
                                text += `${indent}  Arguments: ${node.args.map((a) => `'${a.text}'`).join(", ")}\n`;
                            }
                            if (node.assignments && node.assignments.length > 0) {
                                text += `${indent}  Environment variables: ${node.assignments.map((a) => `${a.name}=${a.value?.text || ""}`).join(", ")}\n`;
                            }
                            if (node.redirects && node.redirects.length > 0) {
                                text += `${indent}  Redirections:\n`;
                                node.redirects.forEach((r) => {
                                    text += `${indent}    - fd ${r.fd || (r.type.startsWith(">") ? 1 : 0)} ${r.type} ${r.file?.text || "unknown"}\n`;
                                });
                            }
                            break;
                        default:
                            text += `${indent}Node type: ${node.type}\n`;
                    }
                }
                catch (e) {
                    text += `${indent}[Error explaining ${node.type}: ${e.message}]\n`;
                }
                return text;
            };
            explanation += explainNode(ast);
            explanation += `--------------------------------------\n`;
            return { stdout: explanation, stderr: "", exitCode: 0 };
        }
        catch (e) {
            return {
                stdout: "",
                stderr: `ag-explain: parse error: ${sanitizeErrorMessage(e.message)}\n`,
                exitCode: 1,
            };
        }
    },
};
