import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync, copyFileSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const __generatorDir = dirname(fileURLToPath(import.meta.url));
function generateVSCodeExtension(context) {
  const { spec, outputDir } = context;
  const extensionDir = join(outputDir || ".", "tools", "vscode-extension");
  if (!existsSync(extensionDir)) mkdirSync(extensionDir, { recursive: true });
  const distribution = extractDistribution(spec);
  let cliCommands = [];
  if (distribution?.commands) {
    cliCommands = distribution.commands.map((cmd) => {
      const parts = (cmd.from || cmd.command || "").split(".");
      const name = parts[parts.length - 1] || "unknown";
      return {
        command: `specverse.${name}`,
        title: cmd.title || `${capitalize(name)}: ${cmd.description || ""}`,
        category: "SpecVerse"
      };
    });
  }
  if (cliCommands.length === 0) {
    cliCommands = extractCLICommands(spec);
  }
  if (cliCommands.length === 0) {
    cliCommands = getStandardCommands();
  }
  const entityTypes = extractEntityTypes(spec);
  const specVersion = distribution?.version || spec?.metadata?.version || spec?.version || "4.0.0";
  const packageJson = generatePackageJson(cliCommands, entityTypes, specVersion);
  if (distribution) {
    if (distribution.displayName) packageJson.displayName = distribution.displayName;
    if (distribution.publisher) packageJson.publisher = distribution.publisher;
    if (distribution.description) packageJson.description = distribution.description;
    if (distribution.languages && distribution.languages.length > 0) {
      packageJson.contributes.languages = distribution.languages.map((lang) => ({
        id: lang.id,
        aliases: lang.aliases || [lang.id],
        extensions: lang.extensions || [],
        configuration: `./language-configuration.json`
      }));
      packageJson.contributes.grammars = distribution.languages.filter((lang) => lang.grammar).map((lang) => ({
        language: lang.id,
        scopeName: lang.grammar,
        path: `./syntaxes/${lang.id}.tmLanguage.json`
      }));
    }
    if (distribution.themes && distribution.themes.length > 0) {
      packageJson.contributes.themes = distribution.themes.map((theme) => ({
        label: theme.name,
        uiTheme: theme.type === "dark" ? "vs-dark" : theme.type === "light" ? "vs" : "hc-black",
        path: `./themes/${theme.name.toLowerCase().replace(/\s+/g, "-")}-theme.json`
      }));
    }
  }
  writeFileSync(join(extensionDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
  let staticDir = join(__generatorDir, "static");
  if (!existsSync(staticDir)) {
    staticDir = join(__generatorDir.replace("/dist/libs/", "/libs/"), "static");
  }
  if (existsSync(staticDir)) {
    copyRecursive(staticDir, extensionDir);
  }
  const srcDir = join(extensionDir, "src");
  if (!existsSync(srcDir)) mkdirSync(srcDir, { recursive: true });
  const extTs = join(staticDir, "extension.ts");
  if (existsSync(extTs)) {
    copyFileSync(extTs, join(srcDir, "extension.ts"));
  }
  const buildScript = `const esbuild = require('esbuild');
esbuild.build({
  entryPoints: ['src/extension.ts'],
  bundle: true,
  outfile: 'dist/extension.js',
  external: ['vscode'],
  format: 'cjs',
  platform: 'node',
}).catch(() => process.exit(1));
`;
  const scriptsDir = join(extensionDir, "scripts");
  if (!existsSync(scriptsDir)) mkdirSync(scriptsDir, { recursive: true });
  writeFileSync(join(scriptsDir, "build.js"), buildScript);
  return `VSCode extension generated in: ${extensionDir}
  ${cliCommands.length} commands, ${entityTypes.length} entity keywords`;
}
function extractDistribution(spec) {
  const allDistributions = [];
  if (spec?.distributions) {
    const entries = Array.isArray(spec.distributions) ? spec.distributions : Object.entries(spec.distributions).map(([name, data]) => ({ name, ...data }));
    allDistributions.push(...entries);
  }
  const components = spec?.components || {};
  const componentList = Array.isArray(components) ? components : Object.values(components);
  for (const comp of componentList) {
    const distributions = comp?.distributions;
    if (!distributions) continue;
    const distEntries = Array.isArray(distributions) ? distributions : Object.entries(distributions).map(([name, data]) => ({ name, ...data }));
    allDistributions.push(...distEntries);
  }
  for (const dist of allDistributions) {
    if (dist.type === "ide") return dist;
  }
  return allDistributions.length > 0 ? allDistributions[0] : null;
}
function extractCLICommands(spec) {
  const commands = [];
  const components = spec?.components || {};
  const componentList = Array.isArray(components) ? components : Object.entries(components).map(([name, data]) => ({ name, ...data }));
  for (const comp of componentList) {
    const cliCommands = comp?.commands;
    if (!cliCommands) continue;
    for (const [rootName, rootDef] of Object.entries(cliCommands)) {
      const subcommands = rootDef?.subcommands || {};
      for (const [subName, subDef] of Object.entries(subcommands)) {
        const sub = subDef;
        const nestedSubs = sub?.subcommands;
        if (nestedSubs) {
          for (const [nestedName, nestedDef] of Object.entries(nestedSubs)) {
            commands.push({
              command: `specverse.${subName}.${nestedName}`,
              title: `${capitalize(subName)} ${capitalize(nestedName)}: ${nestedDef.description || ""}`,
              category: "SpecVerse"
            });
          }
        } else {
          commands.push({
            command: `specverse.${subName}`,
            title: `${capitalize(subName)}: ${sub.description || ""}`,
            category: "SpecVerse"
          });
        }
      }
    }
  }
  return commands;
}
function extractEntityTypes(spec) {
  const types = /* @__PURE__ */ new Set();
  const components = spec?.components || [];
  for (const component of Array.isArray(components) ? components : Object.values(components)) {
    const comp = component;
    const models = comp?.models;
    if (models) {
      if (Array.isArray(models)) {
        models.forEach((m) => types.add(m.name));
      } else {
        Object.keys(models).forEach((name) => types.add(name));
      }
    }
  }
  return [...types];
}
function generatePackageJson(commands, _entityTypes, specVersion = "1.0.0") {
  return {
    name: "specverse",
    displayName: "SpecVerse",
    description: "SpecVerse specification language support \u2014 syntax highlighting, validation, IntelliSense",
    version: specVersion,
    publisher: "specverse",
    engines: { vscode: "^1.80.0" },
    categories: ["Programming Languages", "Linters", "Snippets"],
    activationEvents: ["onLanguage:specverse"],
    main: "./dist/extension.js",
    contributes: {
      languages: [{
        id: "specverse",
        aliases: ["SpecVerse", "specly"],
        extensions: [".specly", ".specverse"],
        configuration: "./language-configuration.json"
      }],
      grammars: [{
        language: "specverse",
        scopeName: "source.specverse",
        path: "./syntaxes/specverse.tmLanguage.json"
      }],
      jsonValidation: [{
        fileMatch: ["*.specly", "*.specverse"],
        url: "./schemas/specverse-v3-schema.json"
      }],
      themes: [
        { label: "SpecVerse Dark", uiTheme: "vs-dark", path: "./themes/specverse-complete-theme.json" },
        { label: "SpecVerse Basic", uiTheme: "vs-dark", path: "./themes/specverse-basic-theme.json" }
      ],
      commands: commands.map((c) => ({
        command: c.command,
        title: c.title,
        category: c.category
      }))
    },
    scripts: {
      "vscode:prepublish": "npm run build",
      build: "node scripts/build.js",
      package: "npx @vscode/vsce package"
    },
    devDependencies: {
      "@types/vscode": "^1.80.0",
      "@vscode/vsce": "^3.0.0",
      esbuild: "^0.25.0"
    },
    overrides: {
      // Force the patched version of lodash through @vscode/vsce →
      // @secretlint → @textlint transitive chain (4.17.23 has a
      // code-injection advisory in `_.template`).
      lodash: "^4.18.1"
    }
  };
}
function copyRecursive(src, dest) {
  for (const entry of readdirSync(src)) {
    if (entry === "extension.ts") continue;
    const srcPath = join(src, entry);
    const destPath = join(dest, entry);
    if (statSync(srcPath).isDirectory()) {
      if (!existsSync(destPath)) mkdirSync(destPath, { recursive: true });
      copyRecursive(srcPath, destPath);
    } else {
      copyFileSync(srcPath, destPath);
    }
  }
}
function getStandardCommands() {
  return [
    { command: "specverse.validate", title: "Validate specification", category: "SpecVerse" },
    { command: "specverse.infer", title: "Infer full architecture", category: "SpecVerse" },
    { command: "specverse.realize", title: "Generate code from specification", category: "SpecVerse" },
    { command: "specverse.init", title: "Initialize new project", category: "SpecVerse" },
    { command: "specverse.gen.diagrams", title: "Generate Mermaid diagrams", category: "SpecVerse" },
    { command: "specverse.gen.docs", title: "Generate documentation", category: "SpecVerse" },
    { command: "specverse.gen.uml", title: "Generate UML diagrams", category: "SpecVerse" },
    { command: "specverse.dev.format", title: "Format .specly file", category: "SpecVerse" },
    { command: "specverse.dev.watch", title: "Watch and validate on change", category: "SpecVerse" },
    { command: "specverse.dev.quick", title: "Quick validation", category: "SpecVerse" },
    { command: "specverse.cache", title: "Manage import cache", category: "SpecVerse" },
    { command: "specverse.ai.docs", title: "Generate AI implementation prompt", category: "SpecVerse" },
    { command: "specverse.ai.suggest", title: "Get spec improvement suggestions", category: "SpecVerse" },
    { command: "specverse.ai.template", title: "Load AI prompt template", category: "SpecVerse" }
  ];
}
function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}
export {
  generateVSCodeExtension as default
};
