import { Command, Option } from "commander";
import { readProjectConfig } from "./lib/config.js";
import chalk from "chalk";
import {
  convexPackageFromFunctions,
  functionsDir,
  ensureHasConvexDependency,
} from "./lib/utils.js";
import { doReadmeCodegen, doTsconfigCodegen, doCodegen } from "./lib/codegen";
import { oneoffContext } from "./lib/context.js";

export const codegen = new Command("codegen")
  .description(
    "Generate TypeScript code in `convex/_generated/` based on the current contents of `convex/`."
  )
  .option(
    "--dry-run",
    "Print out the generated configuration to stdout instead of writing to convex directory"
  )
  .addOption(new Option("--debug").hideHelp())
  .addOption(
    new Option(
      "--typecheck <mode>",
      `Whether to check TypeScript files with \`tsc --noEmit\`.`
    )
      .choices(["enable", "try", "disable"])
      .default("try")
  )
  .option(
    "--readme",
    "Also write the default convex/README.md, otherwise only written during convex init."
  )
  .option(
    "--tsconfig",
    "Also write the default convex/tsconfig.json, otherwise only written during convex init."
  )
  .action(async options => {
    const ctx = oneoffContext;
    const { projectConfig, configPath } = await readProjectConfig(ctx);
    // This also ensures the current directory is the project root.
    await ensureHasConvexDependency(ctx, "codegen");

    if (options.readme) {
      doReadmeCodegen(
        ctx,
        functionsDir(configPath, projectConfig),
        options.dryRun,
        options.debug
      );
    }

    if (options.tsconfig) {
      doTsconfigCodegen(
        ctx,
        functionsDir(configPath, projectConfig),
        convexPackageFromFunctions(configPath, projectConfig),
        options.dryRun,
        options.debug
      );
    }

    if (options.typecheck !== "disable") {
      console.error(
        chalk.gray(
          "Running TypeScript typecheck, add --typecheck=disable to disable."
        )
      );
    }

    await doCodegen({
      ctx,
      projectConfig,
      configPath,
      deploymentType: "dev",
      typeCheckMode: options.typecheck,
      dryRun: options.dryRun,
      debug: options.debug,
    });
    chalk.green("Codegen finished.");
  });
