import a from './index5.mjs';
import ora from './index8.mjs';
import fs from 'node:fs/promises';
import os__default from 'node:os';
import path__default from 'node:path';
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
import '../shared/ccjk.BAGoDD49.mjs';
import 'node:process';
import '../shared/ccjk.Cjgrln_h.mjs';
import '../shared/ccjk.DeWpAShp.mjs';

function getCcjkConfigDir() {
  if (process.env.CCJK_CONFIG_DIR) {
    return process.env.CCJK_CONFIG_DIR;
  }
  return path__default.join(os__default.homedir(), ".ccjk");
}
function getInstallPath(pluginType, name) {
  const configDir = getCcjkConfigDir();
  const typeDir = {
    skill: "skills",
    mcp: "mcp-servers",
    agent: "agents",
    hook: "hooks"
  }[pluginType];
  return path__default.join(configDir, typeDir, name);
}
async function copyDirectory(src, dest) {
  await fs.mkdir(dest, { recursive: true });
  const entries = await fs.readdir(src, { withFileTypes: true });
  for (const entry of entries) {
    const srcPath = path__default.join(src, entry.name);
    const destPath = path__default.join(dest, entry.name);
    if (entry.isDirectory()) {
      await copyDirectory(srcPath, destPath);
    } else {
      await fs.copyFile(srcPath, destPath);
    }
  }
}
async function downloadFile(url, destPath) {
  const response = await fetch(url, {
    headers: {
      "User-Agent": "ccjk-cli"
    },
    redirect: "follow"
  });
  if (!response.ok) {
    throw new Error(`Failed to download: ${response.statusText}`);
  }
  const buffer = Buffer.from(await response.arrayBuffer());
  await fs.writeFile(destPath, buffer);
}

async function installFromGitHub(sourceInfo, pluginType, options = {}) {
  const { force = false, dryRun = false } = options;
  const { owner, repo, ref = "main", subpath } = sourceInfo;
  try {
    const repoInfo = await fetchRepoInfo(owner, repo);
    const defaultBranch = repoInfo.default_branch || "main";
    const actualRef = ref || defaultBranch;
    const installPath = getInstallPath(pluginType, repo);
    if (!force) {
      try {
        await fs.access(installPath);
        return {
          success: false,
          source: sourceInfo.originalUrl,
          sourceType: "github",
          pluginType,
          error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
        };
      } catch {
      }
    }
    if (dryRun) {
      const files = await listRepoFiles(owner, repo, actualRef, subpath);
      return {
        success: true,
        source: sourceInfo.originalUrl,
        sourceType: "github",
        pluginType,
        installedPath: installPath,
        details: {
          name: repo,
          version: actualRef,
          description: repoInfo.description || void 0,
          files: files.slice(0, 20)
        }
      };
    }
    const tempDir = await downloadRepo(owner, repo, actualRef);
    const sourcePath = subpath ? path__default.join(tempDir, subpath) : tempDir;
    await fs.mkdir(path__default.dirname(installPath), { recursive: true });
    await copyDirectory(sourcePath, installPath);
    await fs.rm(tempDir, { recursive: true, force: true });
    const installedFiles = await listInstalledFiles$1(installPath);
    return {
      success: true,
      source: sourceInfo.originalUrl,
      sourceType: "github",
      pluginType,
      installedPath: installPath,
      details: {
        name: repo,
        version: actualRef,
        description: repoInfo.description || void 0,
        files: installedFiles
      }
    };
  } catch (error) {
    return {
      success: false,
      source: sourceInfo.originalUrl,
      sourceType: "github",
      pluginType,
      error: error instanceof Error ? error.message : String(error)
    };
  }
}
async function fetchRepoInfo(owner, repo) {
  const url = `https://api.github.com/repos/${owner}/${repo}`;
  const response = await fetch(url, {
    headers: {
      "Accept": "application/vnd.github.v3+json",
      "User-Agent": "ccjk-cli"
    }
  });
  if (!response.ok) {
    if (response.status === 404) {
      throw new Error(`Repository not found: ${owner}/${repo}`);
    }
    throw new Error(`Failed to fetch repository info: ${response.statusText}`);
  }
  return response.json();
}
async function listRepoFiles(owner, repo, ref, subpath) {
  const treePath = subpath || "";
  const url = `https://api.github.com/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`;
  const response = await fetch(url, {
    headers: {
      "Accept": "application/vnd.github.v3+json",
      "User-Agent": "ccjk-cli"
    }
  });
  if (!response.ok) {
    return [];
  }
  const data = await response.json();
  const files = (data.tree || []).filter((item) => item.type === "blob").map((item) => item.path).filter((filePath) => !treePath || filePath.startsWith(treePath));
  return files;
}
async function downloadRepo(owner, repo, ref) {
  const zipUrl = `https://github.com/${owner}/${repo}/archive/${ref}.zip`;
  const tempDir = path__default.join(os__default.tmpdir(), `ccjk-${repo}-${Date.now()}`);
  const zipPath = path__default.join(tempDir, "repo.zip");
  await fs.mkdir(tempDir, { recursive: true });
  await downloadFile(zipUrl, zipPath);
  const extractedDir = await extractZip(zipPath, tempDir);
  await fs.unlink(zipPath);
  return extractedDir;
}
async function extractZip(zipPath, destDir) {
  const { exec } = await import('node:child_process');
  const { promisify } = await import('node:util');
  const execAsync = promisify(exec);
  try {
    await execAsync(`unzip -q "${zipPath}" -d "${destDir}"`);
  } catch {
    try {
      await execAsync(`tar -xf "${zipPath}" -C "${destDir}"`);
    } catch {
      throw new Error("Failed to extract archive. Please ensure unzip or tar is installed.");
    }
  }
  const entries = await fs.readdir(destDir);
  const extractedDir = entries.find((entry) => !entry.endsWith(".zip"));
  if (!extractedDir) {
    throw new Error("Failed to find extracted directory");
  }
  return path__default.join(destDir, extractedDir);
}
async function listInstalledFiles$1(dir) {
  const files = [];
  async function walk(currentDir, prefix = "") {
    const entries = await fs.readdir(currentDir, { withFileTypes: true });
    for (const entry of entries) {
      const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
      if (entry.isDirectory()) {
        await walk(path__default.join(currentDir, entry.name), relativePath);
      } else {
        files.push(relativePath);
      }
    }
  }
  await walk(dir);
  return files;
}

async function installFromLocal(sourceInfo, pluginType, options = {}) {
  const { force = false, dryRun = false } = options;
  const { absolutePath, originalPath } = sourceInfo;
  try {
    const stat = await fs.stat(absolutePath);
    const isFile = stat.isFile();
    const isDirectory = stat.isDirectory();
    if (!isFile && !isDirectory) {
      return {
        success: false,
        source: originalPath,
        sourceType: "local",
        pluginType,
        error: `Source path is neither a file nor a directory: ${absolutePath}`
      };
    }
    const pluginName = path__default.basename(absolutePath, path__default.extname(absolutePath));
    const installPath = getInstallPath(pluginType, pluginName);
    if (!force) {
      try {
        await fs.access(installPath);
        return {
          success: false,
          source: originalPath,
          sourceType: "local",
          pluginType,
          error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
        };
      } catch {
      }
    }
    const files = isFile ? [path__default.basename(absolutePath)] : await listFiles(absolutePath);
    const pluginInfo = await readPluginInfo(absolutePath, isFile);
    if (dryRun) {
      return {
        success: true,
        source: originalPath,
        sourceType: "local",
        pluginType,
        installedPath: installPath,
        details: {
          name: pluginInfo.name || pluginName,
          version: pluginInfo.version,
          description: pluginInfo.description,
          files
        }
      };
    }
    if (isFile) {
      await fs.mkdir(path__default.dirname(installPath), { recursive: true });
      if (absolutePath.endsWith(".md")) {
        await fs.copyFile(absolutePath, installPath);
      } else {
        await fs.mkdir(installPath, { recursive: true });
        await fs.copyFile(
          absolutePath,
          path__default.join(installPath, path__default.basename(absolutePath))
        );
      }
    } else {
      await fs.mkdir(path__default.dirname(installPath), { recursive: true });
      await copyDirectory(absolutePath, installPath);
    }
    const installedFiles = isFile ? [path__default.basename(absolutePath)] : await listFiles(installPath);
    return {
      success: true,
      source: originalPath,
      sourceType: "local",
      pluginType,
      installedPath: installPath,
      details: {
        name: pluginInfo.name || pluginName,
        version: pluginInfo.version,
        description: pluginInfo.description,
        files: installedFiles
      }
    };
  } catch (error) {
    return {
      success: false,
      source: originalPath,
      sourceType: "local",
      pluginType,
      error: error instanceof Error ? error.message : String(error)
    };
  }
}
async function listFiles(dir) {
  const files = [];
  async function walk(currentDir, prefix = "") {
    const entries = await fs.readdir(currentDir, { withFileTypes: true });
    for (const entry of entries) {
      if (entry.name.startsWith(".") || entry.name === "node_modules") {
        continue;
      }
      const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
      if (entry.isDirectory()) {
        await walk(path__default.join(currentDir, entry.name), relativePath);
      } else {
        files.push(relativePath);
      }
    }
  }
  await walk(dir);
  return files;
}
async function readPluginInfo(sourcePath, isFile) {
  if (isFile) {
    const name = path__default.basename(sourcePath, path__default.extname(sourcePath));
    return { name };
  }
  try {
    const packageJsonPath = path__default.join(sourcePath, "package.json");
    const content = await fs.readFile(packageJsonPath, "utf-8");
    const packageJson = JSON.parse(content);
    return {
      name: packageJson.name,
      version: packageJson.version,
      description: packageJson.description
    };
  } catch {
  }
  const metaFiles = ["SKILL.md", "skill.md", "README.md", "readme.md"];
  for (const metaFile of metaFiles) {
    try {
      const metaPath = path__default.join(sourcePath, metaFile);
      const content = await fs.readFile(metaPath, "utf-8");
      const titleMatch = content.match(/^#\s+(.+)$/m);
      if (titleMatch) {
        return { name: titleMatch[1].trim() };
      }
    } catch {
    }
  }
  return {};
}

const execAsync = promisify(exec);
async function installFromNpm(sourceInfo, pluginType, options = {}) {
  const { force = false, dryRun = false } = options;
  const { packageName, version } = sourceInfo;
  try {
    const packageInfo = await fetchPackageInfo(packageName, version);
    const packageVersion = version || packageInfo.version;
    const shortName = getShortName(packageName);
    const installPath = getInstallPath(pluginType, shortName);
    if (!force) {
      try {
        await fs.access(installPath);
        return {
          success: false,
          source: packageName,
          sourceType: "npm",
          pluginType,
          error: `Plugin already exists at ${installPath}. Use --force to overwrite.`
        };
      } catch {
      }
    }
    if (dryRun) {
      const files = packageInfo.files || ["(package files)"];
      return {
        success: true,
        source: packageName,
        sourceType: "npm",
        pluginType,
        installedPath: installPath,
        details: {
          name: packageName,
          version: packageVersion,
          description: packageInfo.description,
          files
        }
      };
    }
    if (pluginType === "mcp") {
      await installMcpPackage(packageName, packageVersion, installPath);
    } else {
      await installGenericPackage(packageName, packageVersion, installPath);
    }
    const installedFiles = await listInstalledFiles(installPath);
    return {
      success: true,
      source: packageName,
      sourceType: "npm",
      pluginType,
      installedPath: installPath,
      details: {
        name: packageName,
        version: packageVersion,
        description: packageInfo.description,
        files: installedFiles
      }
    };
  } catch (error) {
    return {
      success: false,
      source: packageName,
      sourceType: "npm",
      pluginType,
      error: error instanceof Error ? error.message : String(error)
    };
  }
}
async function fetchPackageInfo(packageName, version) {
  const url = version ? `https://registry.npmjs.org/${packageName}/${version}` : `https://registry.npmjs.org/${packageName}/latest`;
  const response = await fetch(url);
  if (!response.ok) {
    if (response.status === 404) {
      throw new Error(`Package not found: ${packageName}`);
    }
    throw new Error(`Failed to fetch package info: ${response.statusText}`);
  }
  const data = await response.json();
  return {
    version: data.version,
    description: data.description,
    files: data.files
  };
}
function getShortName(packageName) {
  if (packageName.startsWith("@")) {
    const parts = packageName.split("/");
    return parts[1] || packageName;
  }
  return packageName;
}
async function installMcpPackage(packageName, version, installPath) {
  await fs.mkdir(installPath, { recursive: true });
  const packageJson = {
    name: `ccjk-mcp-${getShortName(packageName)}`,
    version: "1.0.0",
    private: true,
    dependencies: {
      [packageName]: version
    }
  };
  await fs.writeFile(
    path__default.join(installPath, "package.json"),
    JSON.stringify(packageJson, null, 2)
  );
  try {
    await execAsync("npm install", { cwd: installPath });
  } catch (error) {
    try {
      await execAsync("pnpm install", { cwd: installPath });
    } catch {
      throw new Error(
        `Failed to install package. Original error: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  }
}
async function installGenericPackage(packageName, version, installPath) {
  const registryUrl = `https://registry.npmjs.org/${packageName}/${version}`;
  const response = await fetch(registryUrl);
  if (!response.ok) {
    throw new Error(`Failed to fetch package info: ${response.statusText}`);
  }
  const data = await response.json();
  const tarballUrl = data.dist?.tarball;
  if (!tarballUrl) {
    throw new Error("Failed to get tarball URL");
  }
  const tarballResponse = await fetch(tarballUrl);
  if (!tarballResponse.ok) {
    throw new Error(`Failed to download tarball: ${tarballResponse.statusText}`);
  }
  await fs.mkdir(installPath, { recursive: true });
  const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
  const tarballPath = path__default.join(installPath, "package.tgz");
  await fs.writeFile(tarballPath, tarballBuffer);
  try {
    await execAsync(`tar -xzf package.tgz --strip-components=1`, { cwd: installPath });
  } finally {
    await fs.unlink(tarballPath).catch(() => {
    });
  }
}
async function listInstalledFiles(dir) {
  const files = [];
  async function walk(currentDir, prefix = "") {
    try {
      const entries = await fs.readdir(currentDir, { withFileTypes: true });
      for (const entry of entries) {
        if (entry.name === "node_modules")
          continue;
        const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
        if (entry.isDirectory()) {
          await walk(path__default.join(currentDir, entry.name), relativePath);
        } else {
          files.push(relativePath);
        }
      }
    } catch {
    }
  }
  await walk(dir);
  return files;
}

function parseSource(source) {
  const trimmed = source.trim();
  const githubInfo = parseGitHubSource(trimmed);
  if (githubInfo) {
    return githubInfo;
  }
  const localInfo = parseLocalSource(trimmed);
  if (localInfo) {
    return localInfo;
  }
  return parseNpmSource(trimmed);
}
function parseGitHubSource(source) {
  const prefixMatch = source.match(/^(?:github|gh):([^/]+)\/([^#@/]+)(?:#(.+))?$/);
  if (prefixMatch) {
    return {
      type: "github",
      owner: prefixMatch[1],
      repo: prefixMatch[2],
      ref: prefixMatch[3],
      originalUrl: source
    };
  }
  const urlMatch = source.match(
    /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^/]+))?(?:\/(.+))?$/
  );
  if (urlMatch) {
    return {
      type: "github",
      owner: urlMatch[1],
      repo: urlMatch[2],
      ref: urlMatch[3],
      subpath: urlMatch[4],
      originalUrl: source
    };
  }
  const shortMatch = source.match(/^([\w-]+)\/([\w.-]+)(?:#(.+))?$/);
  if (shortMatch && !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("~")) {
    return {
      type: "github",
      owner: shortMatch[1],
      repo: shortMatch[2],
      ref: shortMatch[3],
      originalUrl: source
    };
  }
  return null;
}
function parseLocalSource(source) {
  if (source.startsWith("./") || source.startsWith("../") || source.startsWith("/") || source.startsWith("~/")) {
    let absolutePath;
    if (source.startsWith("~/")) {
      absolutePath = path__default.join(os__default.homedir(), source.slice(2));
    } else if (path__default.isAbsolute(source)) {
      absolutePath = source;
    } else {
      absolutePath = path__default.resolve(process.cwd(), source);
    }
    return {
      type: "local",
      absolutePath,
      originalPath: source
    };
  }
  if (/^[a-z]:[\\/]/i.test(source)) {
    return {
      type: "local",
      absolutePath: path__default.resolve(source),
      originalPath: source
    };
  }
  return null;
}
function parseNpmSource(source) {
  const npmPrefixMatch = source.match(/^npm:(.+)$/);
  const packageStr = npmPrefixMatch ? npmPrefixMatch[1] : source;
  const scopedMatch = packageStr.match(/^(@[^/]+)\/([^@]+)(?:@(.+))?$/);
  if (scopedMatch) {
    return {
      type: "npm",
      scope: scopedMatch[1],
      packageName: `${scopedMatch[1]}/${scopedMatch[2]}`,
      version: scopedMatch[3]
    };
  }
  const versionMatch = packageStr.match(/^([^@]+)@(.+)$/);
  if (versionMatch) {
    return {
      type: "npm",
      packageName: versionMatch[1],
      version: versionMatch[2]
    };
  }
  return {
    type: "npm",
    packageName: packageStr
  };
}
function buildGitHubRawUrl(info, filePath) {
  const ref = info.ref || "main";
  return `https://raw.githubusercontent.com/${info.owner}/${info.repo}/${ref}/${filePath}`;
}

async function detectPluginType(sourceInfo) {
  const result = await detectPluginTypeWithConfidence(sourceInfo);
  return result.type;
}
async function detectPluginTypeWithConfidence(sourceInfo) {
  switch (sourceInfo.type) {
    case "github":
      return detectFromGitHub(sourceInfo);
    case "npm":
      return detectFromNpm(sourceInfo);
    case "local":
      return detectFromLocal(sourceInfo);
    default:
      return { type: "skill", confidence: "low", reason: "Unknown source type" };
  }
}
async function detectFromGitHub(info) {
  const repoNameResult = detectFromRepoName(info.repo);
  if (repoNameResult.confidence === "high") {
    return repoNameResult;
  }
  try {
    const packageJsonUrl = buildGitHubRawUrl(info, "package.json");
    const response = await fetch(packageJsonUrl);
    if (response.ok) {
      const packageJson = await response.json();
      const pkgResult = detectFromPackageJson(packageJson);
      if (pkgResult.confidence !== "low") {
        return pkgResult;
      }
    }
  } catch {
  }
  const filePatterns = [
    { file: "SKILL.md", type: "skill" },
    { file: "skill.md", type: "skill" },
    { file: "AGENT.md", type: "agent" },
    { file: "agent.md", type: "agent" },
    { file: "mcp.json", type: "mcp" },
    { file: "hook.json", type: "hook" }
  ];
  for (const pattern of filePatterns) {
    try {
      const fileUrl = buildGitHubRawUrl(info, pattern.file);
      const response = await fetch(fileUrl, { method: "HEAD" });
      if (response.ok) {
        return {
          type: pattern.type,
          confidence: "high",
          reason: `Found ${pattern.file}`
        };
      }
    } catch {
    }
  }
  return repoNameResult.confidence !== "low" ? repoNameResult : { type: "skill", confidence: "low", reason: "Default type" };
}
async function detectFromNpm(info) {
  const nameResult = detectFromPackageName(info.packageName);
  if (nameResult.confidence === "high") {
    return nameResult;
  }
  try {
    const registryUrl = `https://registry.npmjs.org/${info.packageName}`;
    const response = await fetch(registryUrl);
    if (response.ok) {
      const data = await response.json();
      const latestVersion = data["dist-tags"]?.latest;
      if (latestVersion && data.versions?.[latestVersion]) {
        const packageJson = data.versions[latestVersion];
        const pkgResult = detectFromPackageJson(packageJson);
        if (pkgResult.confidence !== "low") {
          return pkgResult;
        }
      }
    }
  } catch {
  }
  return nameResult.confidence !== "low" ? nameResult : { type: "skill", confidence: "low", reason: "Default type" };
}
async function detectFromLocal(info) {
  const { absolutePath } = info;
  const dirName = path__default.basename(absolutePath);
  const dirResult = detectFromRepoName(dirName);
  if (dirResult.confidence === "high") {
    return dirResult;
  }
  try {
    const packageJsonPath = path__default.join(absolutePath, "package.json");
    const content = await fs.readFile(packageJsonPath, "utf-8");
    const packageJson = JSON.parse(content);
    const pkgResult = detectFromPackageJson(packageJson);
    if (pkgResult.confidence !== "low") {
      return pkgResult;
    }
  } catch {
  }
  const filePatterns = [
    { file: "SKILL.md", type: "skill" },
    { file: "skill.md", type: "skill" },
    { file: "AGENT.md", type: "agent" },
    { file: "agent.md", type: "agent" },
    { file: "mcp.json", type: "mcp" },
    { file: "hook.json", type: "hook" }
  ];
  for (const pattern of filePatterns) {
    try {
      const filePath = path__default.join(absolutePath, pattern.file);
      await fs.access(filePath);
      return {
        type: pattern.type,
        confidence: "high",
        reason: `Found ${pattern.file}`
      };
    } catch {
    }
  }
  try {
    const stat = await fs.stat(absolutePath);
    if (stat.isFile() && absolutePath.endsWith(".md")) {
      return {
        type: "skill",
        confidence: "high",
        reason: "Single markdown file"
      };
    }
  } catch {
  }
  return dirResult.confidence !== "low" ? dirResult : { type: "skill", confidence: "low", reason: "Default type" };
}
function detectFromRepoName(name) {
  const lowerName = name.toLowerCase();
  if (lowerName.includes("mcp-server") || lowerName.includes("mcp_server") || lowerName.startsWith("mcp-") || lowerName.endsWith("-mcp")) {
    return { type: "mcp", confidence: "high", reason: `Name contains MCP pattern: ${name}` };
  }
  if (lowerName.includes("agent") || lowerName.includes("-agent") || lowerName.endsWith("-agent")) {
    return { type: "agent", confidence: "medium", reason: `Name contains agent pattern: ${name}` };
  }
  if (lowerName.includes("hook") || lowerName.includes("-hook") || lowerName.endsWith("-hook")) {
    return { type: "hook", confidence: "medium", reason: `Name contains hook pattern: ${name}` };
  }
  if (lowerName.includes("skill") || lowerName.includes("-skill") || lowerName.endsWith("-skill")) {
    return { type: "skill", confidence: "medium", reason: `Name contains skill pattern: ${name}` };
  }
  return { type: "skill", confidence: "low", reason: "No pattern matched" };
}
function detectFromPackageName(packageName) {
  const lowerName = packageName.toLowerCase();
  if (lowerName.startsWith("@modelcontextprotocol/")) {
    return { type: "mcp", confidence: "high", reason: "MCP official scope" };
  }
  if (lowerName.includes("mcp-server") || lowerName.includes("mcp_server")) {
    return { type: "mcp", confidence: "high", reason: "MCP server pattern in name" };
  }
  return detectFromRepoName(packageName);
}
function detectFromPackageJson(packageJson) {
  if (packageJson.ccjk && typeof packageJson.ccjk === "object") {
    const ccjk = packageJson.ccjk;
    if (ccjk.type && typeof ccjk.type === "string") {
      const type = ccjk.type;
      if (["skill", "mcp", "agent", "hook"].includes(type)) {
        return { type, confidence: "high", reason: "Explicit ccjk.type field" };
      }
    }
  }
  if (Array.isArray(packageJson.keywords)) {
    const keywords = packageJson.keywords;
    const keywordMap = {
      "mcp-server": "mcp",
      "mcp": "mcp",
      "model-context-protocol": "mcp",
      "ccjk-skill": "skill",
      "claude-skill": "skill",
      "ccjk-agent": "agent",
      "ccjk-hook": "hook"
    };
    for (const keyword of keywords) {
      const type = keywordMap[keyword.toLowerCase()];
      if (type) {
        return { type, confidence: "high", reason: `Keyword: ${keyword}` };
      }
    }
  }
  if (packageJson.bin) {
    const binKeys = Object.keys(packageJson.bin);
    for (const key of binKeys) {
      if (key.includes("mcp") || key.includes("server")) {
        return { type: "mcp", confidence: "medium", reason: `Binary name: ${key}` };
      }
    }
  }
  if (typeof packageJson.main === "string") {
    const main = packageJson.main.toLowerCase();
    if (main.includes("server") || main.includes("mcp")) {
      return { type: "mcp", confidence: "low", reason: `Main file: ${packageJson.main}` };
    }
  }
  return { type: "skill", confidence: "low", reason: "No specific indicators" };
}

async function addCommand(source, options = {}) {
  const { force = false, dryRun = false, json = false, lang = "en" } = options;
  const i18n = getI18n(lang);
  const spinner = json ? null : ora(i18n.parsing).start();
  let sourceInfo;
  try {
    sourceInfo = parseSource(source);
    spinner?.succeed(i18n.parsed(sourceInfo.type));
  } catch (error) {
    spinner?.fail(i18n.parseFailed);
    const result = {
      success: false,
      source,
      sourceType: "local",
      pluginType: "skill",
      error: error instanceof Error ? error.message : String(error)
    };
    if (json) {
      console.log(JSON.stringify(result, null, 2));
    } else {
      console.error(a.red(`
${i18n.error}: ${result.error}
`));
    }
    return result;
  }
  let pluginType = options.type;
  if (!pluginType) {
    spinner?.start(i18n.detectingType);
    try {
      pluginType = await detectPluginType(sourceInfo);
      spinner?.succeed(i18n.detectedType(pluginType));
    } catch {
      spinner?.info(i18n.defaultType);
      pluginType = "skill";
    }
  }
  spinner?.start(dryRun ? i18n.previewInstall : i18n.installing);
  try {
    let result;
    switch (sourceInfo.type) {
      case "github":
        result = await installFromGitHub(sourceInfo, pluginType, { force, dryRun });
        break;
      case "npm":
        result = await installFromNpm(sourceInfo, pluginType, { force, dryRun });
        break;
      case "local":
        result = await installFromLocal(sourceInfo, pluginType, { force, dryRun });
        break;
      default:
        throw new Error(`Unsupported source type: ${sourceInfo.type}`);
    }
    if (result.success) {
      spinner?.succeed(dryRun ? i18n.previewSuccess : i18n.installSuccess);
    } else {
      spinner?.fail(i18n.installFailed);
    }
    if (json) {
      console.log(JSON.stringify(result, null, 2));
    } else if (result.success && !dryRun) {
      printSuccessMessage(result, i18n);
    } else if (result.success && dryRun) {
      printPreviewMessage(result, i18n);
    } else {
      console.error(a.red(`
${i18n.error}: ${result.error}
`));
    }
    return result;
  } catch (error) {
    spinner?.fail(i18n.installFailed);
    const result = {
      success: false,
      source,
      sourceType: sourceInfo.type,
      pluginType,
      error: error instanceof Error ? error.message : String(error)
    };
    if (json) {
      console.log(JSON.stringify(result, null, 2));
    } else {
      console.error(a.red(`
${i18n.error}: ${result.error}
`));
    }
    return result;
  }
}
function printSuccessMessage(result, i18n) {
  console.log();
  console.log(a.green.bold(`\u2713 ${i18n.installed}`));
  console.log();
  console.log(`  ${a.gray(i18n.name)}:     ${result.details?.name || result.source}`);
  if (result.details?.version) {
    console.log(`  ${a.gray(i18n.version)}:  ${result.details.version}`);
  }
  console.log(`  ${a.gray(i18n.type)}:     ${result.pluginType}`);
  console.log(`  ${a.gray(i18n.path)}:     ${result.installedPath}`);
  console.log();
  console.log(a.cyan(i18n.nextSteps));
  switch (result.pluginType) {
    case "skill":
      console.log(`  ${a.gray("\u2022")} ${i18n.skillHint}`);
      break;
    case "mcp":
      console.log(`  ${a.gray("\u2022")} ${i18n.mcpHint}`);
      break;
    case "agent":
      console.log(`  ${a.gray("\u2022")} ${i18n.agentHint}`);
      break;
    case "hook":
      console.log(`  ${a.gray("\u2022")} ${i18n.hookHint}`);
      break;
  }
  console.log();
}
function printPreviewMessage(result, i18n) {
  console.log();
  console.log(a.yellow.bold(`\u26A1 ${i18n.preview}`));
  console.log();
  console.log(`  ${a.gray(i18n.source)}:   ${result.source}`);
  console.log(`  ${a.gray(i18n.type)}:     ${result.pluginType}`);
  console.log(`  ${a.gray(i18n.target)}:   ${result.installedPath}`);
  if (result.details?.files?.length) {
    console.log(`  ${a.gray(i18n.files)}:`);
    for (const file of result.details.files.slice(0, 5)) {
      console.log(`    ${a.gray("\u2022")} ${file}`);
    }
    if (result.details.files.length > 5) {
      console.log(`    ${a.gray("...")} ${i18n.andMore(result.details.files.length - 5)}`);
    }
  }
  console.log();
  console.log(a.gray(i18n.dryRunNote));
  console.log();
}
function getI18n(lang) {
  const texts = {
    "zh-CN": {
      parsing: "\u89E3\u6790\u6765\u6E90...",
      parsed: (type) => `\u6765\u6E90\u7C7B\u578B: ${type}`,
      parseFailed: "\u89E3\u6790\u6765\u6E90\u5931\u8D25",
      detectingType: "\u68C0\u6D4B\u63D2\u4EF6\u7C7B\u578B...",
      detectedType: (type) => `\u68C0\u6D4B\u5230\u7C7B\u578B: ${type}`,
      defaultType: "\u4F7F\u7528\u9ED8\u8BA4\u7C7B\u578B: skill",
      installing: "\u5B89\u88C5\u4E2D...",
      previewInstall: "\u9884\u89C8\u5B89\u88C5...",
      installSuccess: "\u5B89\u88C5\u6210\u529F",
      previewSuccess: "\u9884\u89C8\u5B8C\u6210",
      installFailed: "\u5B89\u88C5\u5931\u8D25",
      error: "\u9519\u8BEF",
      installed: "\u63D2\u4EF6\u5DF2\u5B89\u88C5",
      preview: "\u5B89\u88C5\u9884\u89C8 (dry-run)",
      name: "\u540D\u79F0",
      version: "\u7248\u672C",
      type: "\u7C7B\u578B",
      path: "\u8DEF\u5F84",
      source: "\u6765\u6E90",
      target: "\u76EE\u6807",
      files: "\u6587\u4EF6",
      nextSteps: "\u4E0B\u4E00\u6B65:",
      skillHint: "\u4F7F\u7528 /skill-name \u5728 Claude Code \u4E2D\u8C03\u7528",
      mcpHint: "\u8FD0\u884C ccjk mcp status \u67E5\u770B\u72B6\u6001",
      agentHint: "\u4F7F\u7528 ccjk agent list \u67E5\u770B\u5DF2\u5B89\u88C5\u7684 agent",
      hookHint: "\u8FD0\u884C ccjk hooks list \u67E5\u770B\u5DF2\u5B89\u88C5\u7684 hook",
      dryRunNote: "\u8FD9\u662F\u9884\u89C8\u6A21\u5F0F\uFF0C\u672A\u5B9E\u9645\u5B89\u88C5\u3002\u79FB\u9664 --dry-run \u6267\u884C\u5B89\u88C5\u3002",
      andMore: (n) => `\u8FD8\u6709 ${n} \u4E2A\u6587\u4EF6`
    },
    "en": {
      parsing: "Parsing source...",
      parsed: (type) => `Source type: ${type}`,
      parseFailed: "Failed to parse source",
      detectingType: "Detecting plugin type...",
      detectedType: (type) => `Detected type: ${type}`,
      defaultType: "Using default type: skill",
      installing: "Installing...",
      previewInstall: "Previewing installation...",
      installSuccess: "Installation successful",
      previewSuccess: "Preview complete",
      installFailed: "Installation failed",
      error: "Error",
      installed: "Plugin installed",
      preview: "Installation preview (dry-run)",
      name: "Name",
      version: "Version",
      type: "Type",
      path: "Path",
      source: "Source",
      target: "Target",
      files: "Files",
      nextSteps: "Next steps:",
      skillHint: "Use /skill-name in Claude Code to invoke",
      mcpHint: "Run ccjk mcp status to check status",
      agentHint: "Use ccjk agent list to see installed agents",
      hookHint: "Run ccjk hooks list to see installed hooks",
      dryRunNote: "This is preview mode, nothing was installed. Remove --dry-run to install.",
      andMore: (n) => `and ${n} more files`
    }
  };
  return texts[lang];
}

export { addCommand, parseSource };
