// @generated by usage-cli from cli/usage.usage.kdl
const envVarGenerator = {
  script: ["sh", "-c", "env"],
  postProcess: (output: string) => {
    return output.split("\n").map((l) => ({ name: l.split("=")[0] }));
  },
};

const usageGenerateSpec = (cmds: string[]) => {
  return async (
    context: string[],
    executeCommand: Fig.ExecuteCommandFunction
  ): Promise<Fig.Spec> => {
    const promises = cmds.map(async (cmd): Promise<Fig.Subcommand[]> => {
      try {
        const args = cmd.split(" ");
        const {
          stdout,
          stderr: cmdStderr,
          status: cmdStatus,
        } = await executeCommand({
          command: args[0],
          args: args.splice(1),
        });
        if (cmdStatus !== 0) {
          return [{ name: "error", description: cmdStderr }];
        }
        const {
          stdout: figSpecOut,
          stderr: figSpecStderr,
          status: usageFigStatus,
        } = await executeCommand({
          command: "usage",
          args: ["g", "fig", "--spec", stdout],
        });
        if (usageFigStatus !== 0) {
          return [{ name: "error", description: figSpecStderr }];
        }

        const start_of_json = figSpecOut.indexOf("{");
        const j = figSpecOut.slice(start_of_json);
        return JSON.parse(j).subcommands as Fig.Subcommand[];
      } catch (e) {
        return [{ name: "error", description: e }] as Fig.Subcommand[];
      }
    });

    // eslint-disable-next-line compat/compat
    const results = await Promise.allSettled(promises);
    const subcommands = results
      .filter((p) => p.status === "fulfilled")
      .map((p) => p.value);
    const failed = results
      .filter((p) => p.status === "rejected")
      .map((p) => ({ name: "error", description: p.reason }));

    return { subcommands: [...subcommands.flat(), ...failed] } as Fig.Spec;
  };
};

const completionGeneratorTemplate = (
  argSuggestionBash: string
): Fig.Generator => {
  return {
    custom: async (tokens: string[], executeCommand) => {
      let arg = argSuggestionBash;
      if (tokens.length >= 1) {
        arg = argSuggestionBash.replace(
          "{{words[CURRENT]}}",
          tokens[tokens.length - 1]
        );
      }

      if (tokens.length >= 2) {
        arg = arg.replace(`{{words[PREV]}}`, tokens[tokens.length - 2]);
      }
      const { stdout: text } = await executeCommand({
        command: "sh",
        args: ["-c", arg],
      });
      if (text.trim().length == 0) return [];
      return text.split("\n").map((elm) => ({ name: elm }));
    },
  };
};

const completionSpec: Fig.Spec = {
  name: "usage",
  subcommands: [
    {
      name: "bash",
      description: "Execute a shell script using bash",
      options: [
        {
          name: "-h",
          description: "Show help",
          isRepeatable: false,
        },
        {
          name: "--help",
          description: "Show help",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "script",
        },
        {
          name: "args",
          description: "Arguments to pass to script",
          isOptional: true,
          isVariadic: true,
        },
      ],
    },
    {
      name: ["complete-word", "cw"],
      description:
        "Generate shell completion candidates for a partial command line",
      options: [
        {
          name: ["-f", "--file"],
          description:
            'Usage spec file or script with usage shebang, use "-" to read from stdin',
          isRepeatable: false,
          args: {
            name: "file",
            template: "filepaths",
          },
        },
        {
          name: ["-s", "--spec"],
          description: "Raw string spec input",
          isRepeatable: false,
          args: {
            name: "spec",
          },
        },
        {
          name: "--cword",
          description: "Current word index",
          isRepeatable: false,
          args: {
            name: "cword",
          },
        },
        {
          name: "--shell",
          isRepeatable: false,
          args: {
            name: "shell",
            suggestions: ["bash", "fish", "nu", "powershell", "zsh"],
          },
        },
      ],
      args: {
        name: "words",
        description: "User's input from the command line",
        isOptional: true,
        isVariadic: true,
      },
    },
    {
      name: "diff",
      description:
        "Compare two usage specs and report what changed about the interface",
      options: [
        {
          name: ["-f", "--format"],
          description: "Output format",
          isRepeatable: false,
          args: {
            name: "format",
            suggestions: ["text", "json"],
          },
        },
        {
          name: ["-b", "--breaking"],
          description: "Report only breaking changes",
          isRepeatable: false,
        },
        {
          name: "--exit-zero",
          description: "Exit 0 even when there are breaking changes",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "old",
          description:
            'The spec as it was, typically the released one, use "-" to read from stdin',
          template: "filepaths",
        },
        {
          name: "new",
          description: 'The spec as it is now, use "-" to read from stdin',
          template: "filepaths",
        },
      ],
    },
    {
      name: ["exec", "x"],
      description:
        "Execute a script, parsing args and exposing them as environment variables",
      options: [
        {
          name: "-h",
          description: "Show help",
          isRepeatable: false,
        },
        {
          name: "--help",
          description: "Show help",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "command",
          description: "Command to execute after parsing usage spec",
        },
        {
          name: "bin",
          description: "Path to script to execute",
        },
        {
          name: "args",
          description: "Arguments to pass to script",
          isOptional: true,
          isVariadic: true,
        },
      ],
    },
    {
      name: "explain",
      description: "Explain what a command line binds to",
      options: [
        {
          name: ["-f", "--file"],
          description:
            'A usage spec file or script with a usage shebang, use "-" to read from stdin',
          isRepeatable: false,
          args: {
            name: "file",
            template: "filepaths",
          },
        },
        {
          name: ["-s", "--spec"],
          description: "Raw string spec input",
          isRepeatable: false,
          args: {
            name: "spec",
          },
        },
        {
          name: "--format",
          description: "Output format",
          isRepeatable: false,
          args: {
            name: "format",
            suggestions: ["text", "json"],
          },
        },
        {
          name: "--view",
          description: "A spec-declared executable view to explain",
          isRepeatable: false,
          args: {
            name: "view",
          },
        },
        {
          name: ["-e", "--env"],
          description:
            "Environment to explain against, as KEY=VALUE, repeatable",
          isRepeatable: true,
          args: {
            name: "env",
          },
        },
      ],
      args: {
        name: "argv",
        description:
          "The command line to explain, starting with the program name",
        isOptional: true,
        isVariadic: true,
      },
    },
    {
      name: "fish",
      description: "Execute a shell script using fish",
      options: [
        {
          name: "-h",
          description: "Show help",
          isRepeatable: false,
        },
        {
          name: "--help",
          description: "Show help",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "script",
        },
        {
          name: "args",
          description: "Arguments to pass to script",
          isOptional: true,
          isVariadic: true,
        },
      ],
    },
    {
      name: ["generate", "g"],
      description:
        "Generate completions, documentation, and other artifacts from usage specs",
      subcommands: [
        {
          name: ["completion", "c"],
          description:
            "Generate shell completion scripts for bash, fish, nu, powershell, or zsh",
          options: [
            {
              name: "--install",
              description:
                "Install the script where this shell looks for it, instead of printing it",
              isRepeatable: false,
            },
            {
              name: "--force",
              description:
                "Replace a file at the target path that usage did not write",
              isRepeatable: false,
            },
            {
              name: ["-f", "--file"],
              description:
                'A .usage.kdl spec file to use for generating completions, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--cache-key",
              description:
                "A cache key to use for storing the results of calling the CLI with --usage-cmd",
              isRepeatable: false,
              args: {
                name: "cache_key",
              },
            },
            {
              name: "--usage-bin",
              description:
                "Override the bin used for calling back to usage-cli",
              isRepeatable: false,
              args: {
                name: "usage_bin",
              },
            },
            {
              name: "--usage-cmd",
              description:
                'A command which generates a usage spec e.g.: `mycli --usage` or `mycli completion usage` Defaults to "$bin --usage"',
              isRepeatable: false,
              args: {
                name: "usage_cmd",
              },
            },
          ],
          args: [
            {
              name: "shell",
              description: "Shell to generate completions for",
              suggestions: ["bash", "fish", "nu", "powershell", "zsh"],
            },
            {
              name: "bin",
              description: "The CLI which we're generating completions for",
            },
          ],
        },
        {
          name: ["completion-init", "ci"],
          description:
            "Generate a shell init script that auto-completes any usage shebang script on $PATH",
          options: [
            {
              name: "--usage-bin",
              description:
                "Override the bin used for calling back to usage-cli",
              isRepeatable: false,
              args: {
                name: "usage_bin",
              },
            },
          ],
          args: {
            name: "shell",
            description: "Shell to generate the init script for",
            suggestions: ["bash", "fish", "zsh"],
          },
        },
        {
          name: "fig",
          description: "Generate Fig completion spec for Amazon Q / Fig",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--out-file",
              description:
                'File path where the generated Fig spec will be saved, or "-" for stdout',
              isRepeatable: false,
              args: {
                name: "out_file",
                template: "filepaths",
              },
            },
            {
              name: "--spec",
              description: "Raw string spec input",
              isRepeatable: false,
              args: {
                name: "spec",
              },
            },
          ],
        },
        {
          name: "go",
          description: "Generate Go parse tables from a usage spec",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: ["-o", "--out-file"],
              description:
                'File path where the generated Go source will be saved, or "-" for stdout',
              isRepeatable: false,
              args: {
                name: "out_file",
                template: "filepaths",
              },
            },
            {
              name: ["-p", "--package"],
              description:
                "Go package clause for the generated file (defaults to the spec's bin name)",
              isRepeatable: false,
              args: {
                name: "package",
              },
            },
            {
              name: "--spec",
              description: "Raw string spec input",
              isRepeatable: false,
              args: {
                name: "spec",
              },
            },
          ],
        },
        {
          name: "json",
          description: "Outputs a usage spec in json format",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--spec",
              description: "Raw string spec input",
              isRepeatable: false,
              args: {
                name: "spec",
              },
            },
            {
              name: "--view",
              description: "Render one spec-declared executable view",
              isRepeatable: false,
              args: {
                name: "view",
              },
            },
          ],
        },
        {
          name: "json-schema",
          description:
            "Generate a JSON Schema for a CLI's config file from its usage spec",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--out-file",
              description: "Write the schema here instead of to stdout",
              isRepeatable: false,
              args: {
                name: "out_file",
                template: "filepaths",
              },
            },
            {
              name: "--spec",
              description: "Raw string spec input",
              isRepeatable: false,
              args: {
                name: "spec",
              },
            },
            {
              name: "--title",
              description: "The schema's title, shown by editors",
              isRepeatable: false,
              args: {
                name: "title",
              },
            },
            {
              name: "--url",
              description: "Where the schema is published, for its `$id`",
              isRepeatable: false,
              args: {
                name: "url",
              },
            },
          ],
        },
        {
          name: ["manpage", "man"],
          description: "Generate a manpage from a usage spec",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--view",
              description: "Render one spec-declared executable view",
              isRepeatable: false,
              args: {
                name: "view",
              },
            },
            {
              name: ["-o", "--out-file"],
              description: 'Output file path, or "-" for stdout (default)',
              isRepeatable: false,
              args: {
                name: "out_file",
                template: "filepaths",
              },
            },
            {
              name: ["-s", "--section"],
              description: "Manual section number (default: 1)",
              isRepeatable: false,
              args: {
                name: "section",
              },
            },
          ],
        },
        {
          name: ["markdown", "md"],
          description: "Generate markdown documentation from usage specs",
          options: [
            {
              name: ["-f", "--file"],
              description:
                'A usage spec taken in as a file, use "-" to read from stdin',
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: "--view",
              description: "Render one spec-declared executable view",
              isRepeatable: false,
              args: {
                name: "view",
              },
            },
            {
              name: ["-m", "--multi"],
              description: "Render each subcommand as a separate markdown file",
              isRepeatable: false,
            },
            {
              name: "--html-encode",
              description: "Escape HTML in markdown",
              isRepeatable: false,
            },
            {
              name: "--out-dir",
              description:
                "Output markdown files to this directory (required when using --multi)",
              isRepeatable: false,
              args: {
                name: "out_dir",
                template: "folders",
              },
            },
            {
              name: "--out-file",
              description:
                'Output file path for single-file markdown generation, or "-" for stdout (default)',
              isRepeatable: false,
              args: {
                name: "out_file",
                template: "filepaths",
              },
            },
            {
              name: "--replace-pre-with-code-fences",
              description: "Replace `<pre>` tags with markdown code fences",
              isRepeatable: false,
            },
            {
              name: "--url-prefix",
              description: "Prefix to add to all URLs",
              isRepeatable: false,
              args: {
                name: "url_prefix",
              },
            },
          ],
        },
        {
          name: "sdk",
          description: "Generate a type-safe SDK from a usage spec",
          options: [
            {
              name: ["-f", "--file"],
              description: "A usage spec taken in as a file",
              isRepeatable: false,
              args: {
                name: "file",
                template: "filepaths",
              },
            },
            {
              name: ["-l", "--language"],
              description: "Target language for the SDK",
              isRepeatable: false,
              args: {
                name: "language",
                suggestions: ["typescript", "python"],
              },
            },
            {
              name: ["-o", "--output"],
              description: "Output directory for generated SDK files",
              isRepeatable: false,
              args: {
                name: "output",
              },
            },
            {
              name: ["-p", "--package-name"],
              description:
                "Override the package/module name (defaults to spec bin name)",
              isRepeatable: false,
              args: {
                name: "package_name",
              },
            },
            {
              name: "--spec",
              description: "Raw string spec input",
              isRepeatable: false,
              args: {
                name: "spec",
              },
            },
          ],
        },
      ],
    },
    {
      name: "lint",
      description: "Lint a usage spec file for common issues",
      options: [
        {
          name: ["-f", "--format"],
          description: "Output format",
          isRepeatable: false,
          args: {
            name: "format",
            suggestions: ["text", "json"],
          },
        },
        {
          name: ["-W", "--warnings-as-errors"],
          description: "Treat warnings as errors",
          isRepeatable: false,
        },
        {
          name: "--sorted",
          description:
            "Also check that subcommands and flags are declared in sorted order",
          isRepeatable: false,
        },
      ],
      args: {
        name: "file",
        description: 'A usage spec file to lint, use "-" to read from stdin',
        template: "filepaths",
      },
    },
    {
      name: ["mcp", "mcp-server"],
      description: "Serve a usage spec over the Model Context Protocol",
      options: [
        {
          name: ["-f", "--file"],
          description: 'Usage spec file (not "-": stdin is the MCP transport)',
          isRepeatable: false,
          args: {
            name: "file",
            template: "filepaths",
          },
        },
        {
          name: ["-s", "--spec"],
          description: "Raw string spec input",
          isRepeatable: false,
          args: {
            name: "spec",
          },
        },
      ],
    },
    {
      name: "powershell",
      description: "Execute a shell script using PowerShell",
      options: [
        {
          name: "-h",
          description: "Show help",
          isRepeatable: false,
        },
        {
          name: "--help",
          description: "Show help",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "script",
        },
        {
          name: "args",
          description: "Arguments to pass to script",
          isOptional: true,
          isVariadic: true,
        },
      ],
    },
    {
      name: "sponsors",
      description:
        "Show the companies sponsoring usage and the jdx.dev open source tools",
    },
    {
      name: "zsh",
      description: "Execute a shell script using zsh",
      options: [
        {
          name: "-h",
          description: "Show help",
          isRepeatable: false,
        },
        {
          name: "--help",
          description: "Show help",
          isRepeatable: false,
        },
      ],
      args: [
        {
          name: "script",
        },
        {
          name: "args",
          description: "Arguments to pass to script",
          isOptional: true,
          isVariadic: true,
        },
      ],
    },
  ],
  options: [
    {
      name: "--completions",
      description:
        "Outputs completions for the specified shell for completing the `usage` CLI itself",
      isRepeatable: false,
      args: {
        name: "completions",
      },
    },
    {
      name: "--usage-spec",
      description: "Outputs a `usage.kdl` spec for this CLI itself",
      isRepeatable: false,
    },
  ],
};

export default completionSpec;
