import path from "node:path";
import { defineCommand, arg } from "politty";
import { z } from "zod";
import { runGenerateCode } from "../../generator/generate-code";
import { runGenerateDoc, MODULE_DOC_TYPES, type DocType } from "../generate-doc";
import { executeCommand, success, silentFailure } from "../lib/command-result";

const cwd = process.cwd();

const pathArgs = z.object({
  path: arg(z.string(), {
    alias: "p",
    description: "Path to the module directory",
  }),
});

const docCommand = defineCommand({
  name: "doc",
  description: "Create a documentation file from a schema template",
  args: pathArgs.extend({
    type: arg(z.enum(MODULE_DOC_TYPES as unknown as [string, ...string[]]), {
      positional: true,
      description: `Doc type (${MODULE_DOC_TYPES.join(", ")})`,
    }),
    name: arg(z.string().optional(), {
      positional: true,
      description: "Item name (required for all types)",
    }),
  }),
  run: (args) => {
    return executeCommand(async () => {
      const exitCode = await runGenerateDoc(args.type as DocType, args.name, args.path, cwd);
      return exitCode === 0 ? success() : silentFailure(exitCode);
    });
  },
});

const codeCommand = defineCommand({
  name: "code",
  description: "Generate boilerplate, implementation stubs, and generated code from docs",
  args: pathArgs,
  run: (args) => {
    return executeCommand(() => {
      const modulePath = path.resolve(cwd, args.path);
      const moduleName = path.basename(modulePath);
      console.log(`Generating code for ${moduleName}...`);
      const exitCode = runGenerateCode(modulePath, moduleName);
      return exitCode === 0 ? success() : silentFailure(exitCode);
    });
  },
});

export const generateCommand = defineCommand({
  name: "generate",
  description: "Generate docs and code for a module",
  subCommands: {
    doc: docCommand,
    code: codeCommand,
  },
});
