import { existsSync, mkdirSync, writeFileSync, readdirSync, statSync, copyFileSync } from "fs";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
const __generatorDir = dirname(fileURLToPath(import.meta.url));
function generateMCPServer(context) {
  const { spec, outputDir } = context;
  const mcpDir = join(outputDir || ".", "tools", "specverse-mcp");
  if (!existsSync(mcpDir)) mkdirSync(mcpDir, { recursive: true });
  let staticDir = join(__generatorDir, "static");
  if (!existsSync(staticDir)) {
    staticDir = __generatorDir.replace("/dist/libs/", "/libs/");
    staticDir = join(staticDir, "static");
  }
  if (existsSync(staticDir)) {
    copyRecursive(staticDir, mcpDir);
  } else {
    console.warn(`[MCP Generator] Static assets not found at ${staticDir}`);
  }
  const tools = extractMCPTools(spec);
  const resources = extractMCPResources(spec);
  const cliCommands = extractCLICommands(spec);
  const registryCode = generateToolRegistry(tools, resources, cliCommands);
  const registryDir = join(mcpDir, "src", "generated");
  if (!existsSync(registryDir)) mkdirSync(registryDir, { recursive: true });
  writeFileSync(join(registryDir, "spec-registry.ts"), registryCode);
  return `MCP server generated in: ${mcpDir}
  ${tools.length} tools, ${resources.length} resources, ${cliCommands.length} CLI commands`;
}
function extractMCPTools(spec) {
  const tools = [];
  const components = spec?.components || {};
  const componentList = Array.isArray(components) ? components : Object.values(components);
  if (spec?.services && !Array.isArray(components)) {
    componentList.push({ services: spec.services, models: spec.models });
  }
  for (const component of componentList) {
    const comp = component;
    const services = comp?.services;
    if (services) {
      const serviceList = Array.isArray(services) ? services : Object.entries(services).map(([n, d]) => ({ name: n, ...d }));
      for (const service of serviceList) {
        const operations = service.operations;
        if (operations) {
          const opEntries = Array.isArray(operations) ? operations : Object.entries(operations).map(([n, d]) => ({ name: n, ...d }));
          for (const op of opEntries) {
            tools.push({
              name: `${service.name.replace(/Service$/, "").toLowerCase()}-${op.name}`,
              description: op.description || `${op.name} via ${service.name}`,
              isEntityTool: false
            });
          }
        }
      }
    }
    const models = comp?.models;
    if (models) {
      const modelList = Array.isArray(models) ? models : Object.entries(models).map(([n, d]) => ({ name: n, ...d }));
      for (const model of modelList) {
        const behaviors = model.behaviors;
        if (behaviors) {
          const behaviorEntries = typeof behaviors === "object" && !Array.isArray(behaviors) ? Object.entries(behaviors).map(([n, d]) => ({ name: n, ...d })) : [];
          for (const behavior of behaviorEntries) {
            tools.push({
              name: `${model.name.toLowerCase()}-${behavior.name}`,
              description: behavior.description || `${behavior.name} on ${model.name}`,
              isEntityTool: true
            });
          }
        }
      }
    }
  }
  const cliCmds = extractCLICommands(spec);
  for (const cmd of cliCmds) {
    tools.push({
      name: `specverse-${cmd}`,
      description: `Execute specverse ${cmd} command`,
      isEntityTool: false
    });
  }
  if (tools.length === 0) {
    tools.push(
      { name: "specverse-validate", description: "Validate a specification", isEntityTool: false },
      { name: "specverse-create", description: "Create a specification", isEntityTool: false }
    );
  }
  return tools;
}
function extractMCPResources(spec) {
  return [
    { uri: "specverse://schema", name: "SpecVerse Schema", description: "JSON Schema for .specly validation" },
    { uri: "specverse://conventions", name: "Convention Reference", description: "Convention syntax patterns" },
    { uri: "specverse://library-catalog", name: "Library Catalog", description: "Available SpecVerse libraries" },
    { uri: "specverse://prompts", name: "Prompt Templates", description: "AI prompt template versions" }
  ];
}
function extractCLICommands(spec) {
  const commands = [];
  const components = spec?.components || [];
  for (const component of Array.isArray(components) ? components : Object.values(components)) {
    const cliCommands = component?.commands;
    if (!cliCommands) continue;
    for (const [, rootDef] of Object.entries(cliCommands)) {
      const subs = rootDef?.subcommands || {};
      for (const subName of Object.keys(subs)) {
        commands.push(subName);
      }
    }
  }
  return commands;
}
function generateToolRegistry(tools, resources, cliCommands) {
  return `/**
 * Spec-Driven MCP Registry
 * Generated from SpecVerse self-specification.
 *
 * Tools, resources, and CLI command mappings derived from the spec.
 */

export const SPEC_TOOLS = ${JSON.stringify(tools, null, 2)};

export const SPEC_RESOURCES = ${JSON.stringify(resources, null, 2)};

export const CLI_COMMANDS = ${JSON.stringify(cliCommands, null, 2)};

export function getToolByName(name: string) {
  return SPEC_TOOLS.find(t => t.name === name);
}

export function getResourceByUri(uri: string) {
  return SPEC_RESOURCES.find(r => r.uri === uri);
}
`;
}
function copyRecursive(src, dest) {
  for (const entry of readdirSync(src)) {
    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);
    }
  }
}
export {
  generateMCPServer as default
};
