import { defineCommand, useLoader } from '@kb-labs/sdk';
import fs from 'fs';
import path from 'path';

// src/cli/commands/fix-deps.ts
var fix_deps_default = defineCommand({
  id: "quality:fix-deps",
  description: "Auto-fix dependency issues",
  handler: {
    async execute(ctx, input) {
      const { ui, platform } = ctx;
      const flags = input.flags ?? input;
      const dryRun = flags["dry-run"] ?? false;
      const removeUnused = flags["remove-unused"] || flags.all;
      const addMissing = flags["add-missing"] || flags.all;
      const alignVersions = flags["align-versions"] || flags.all;
      const showStats = flags.stats;
      if (showStats) {
        const stats = await getDependencyStats(ctx.cwd);
        outputStats(stats, flags, ui);
        return { exitCode: 0 };
      }
      if (!removeUnused && !addMissing && !alignVersions) {
        ui?.error?.("No fix options specified. Use --remove-unused, --add-missing, --align-versions, or --all");
        return { exitCode: 1 };
      }
      const loader = useLoader("Scanning packages...");
      loader.start();
      const result = {
        packagesScanned: 0,
        removedDeps: [],
        addedDeps: [],
        alignedDeps: [],
        dryRun
      };
      const packages = findPackages(ctx.cwd);
      result.packagesScanned = packages.length;
      loader.update({ text: `Scanned ${packages.length} packages` });
      if (alignVersions) {
        loader.update({ text: "Analyzing duplicate dependencies..." });
        const aligned = await alignDuplicateVersions(packages, dryRun);
        result.alignedDeps = aligned;
      }
      if (addMissing) {
        loader.update({ text: "Checking for missing workspace dependencies..." });
        const added = await addMissingWorkspaceDeps(packages, dryRun);
        result.addedDeps = added;
      }
      if (removeUnused) {
        loader.update({ text: "Checking for unused dependencies..." });
        const removed = await removeUnusedDeps(packages, dryRun);
        result.removedDeps = removed;
      }
      loader.succeed("Dependency analysis completed");
      await platform.analytics.track("quality:fix-deps", {
        dryRun,
        packagesScanned: result.packagesScanned,
        removedCount: result.removedDeps.length,
        addedCount: result.addedDeps.length,
        alignedCount: result.alignedDeps.length
      });
      outputResults(result, flags, ui);
      return {
        exitCode: 0,
        result
      };
    }
  }
});
function findPackages(rootDir) {
  const packages = [];
  if (!fs.existsSync(rootDir)) {
    return packages;
  }
  const entries = fs.readdirSync(rootDir, { withFileTypes: true });
  for (const entry of entries) {
    if (!entry.isDirectory() || !entry.name.startsWith("kb-labs-")) {
      continue;
    }
    const repoPath = path.join(rootDir, entry.name);
    const packagesDir = path.join(repoPath, "packages");
    if (!fs.existsSync(packagesDir)) {
      continue;
    }
    const packageDirs = fs.readdirSync(packagesDir, { withFileTypes: true });
    for (const pkgDir of packageDirs) {
      if (!pkgDir.isDirectory()) {
        continue;
      }
      const packageJsonPath = path.join(packagesDir, pkgDir.name, "package.json");
      if (fs.existsSync(packageJsonPath)) {
        const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
        packages.push({
          name: packageJson.name || pkgDir.name,
          path: packageJsonPath,
          json: packageJson
        });
      }
    }
  }
  return packages;
}
async function getDependencyStats(rootDir) {
  const packages = findPackages(rootDir);
  const allDeps = /* @__PURE__ */ new Map();
  for (const pkg of packages) {
    const deps = {
      ...pkg.json.dependencies,
      ...pkg.json.devDependencies
    };
    for (const [dep, version] of Object.entries(deps)) {
      if (!allDeps.has(dep)) {
        allDeps.set(dep, /* @__PURE__ */ new Set());
      }
      allDeps.get(dep).add(version);
    }
  }
  const duplicates = Array.from(allDeps.entries()).filter(([_, versions]) => versions.size > 1).filter(([dep]) => !dep.startsWith("@kb-labs/"));
  const topUsed = Array.from(allDeps.entries()).map(([name, versions]) => ({ name, count: versions.size > 1 ? versions.size : 1 })).sort((a, b) => b.count - a.count).slice(0, 10);
  return {
    totalPackages: packages.length,
    totalDeps: allDeps.size,
    duplicates: duplicates.length,
    topUsed
  };
}
async function alignDuplicateVersions(packages, dryRun) {
  const aligned = [];
  const depVersions = /* @__PURE__ */ new Map();
  for (const pkg of packages) {
    const deps = {
      ...pkg.json.dependencies,
      ...pkg.json.devDependencies
    };
    for (const [dep, version] of Object.entries(deps)) {
      if (dep.startsWith("@kb-labs/")) {
        continue;
      }
      if (!depVersions.has(dep)) {
        depVersions.set(dep, /* @__PURE__ */ new Map());
      }
      const versions = depVersions.get(dep);
      if (!versions.has(version)) {
        versions.set(version, /* @__PURE__ */ new Set());
      }
      versions.get(version).add(pkg.name);
    }
  }
  for (const [dep, versions] of depVersions.entries()) {
    if (versions.size <= 1) {
      continue;
    }
    const versionCounts = Array.from(versions.entries()).map(([ver, pkgs]) => ({
      version: ver,
      count: pkgs.size,
      packages: Array.from(pkgs)
    }));
    versionCounts.sort((a, b) => b.count - a.count);
    const targetVersion = versionCounts[0]?.version;
    if (!targetVersion) {
      continue;
    }
    for (const { version, packages: pkgNames } of versionCounts.slice(1)) {
      aligned.push({
        dep,
        from: version,
        to: targetVersion,
        packages: pkgNames
      });
      if (!dryRun) {
        for (const pkgName of pkgNames) {
          const pkg = packages.find((p) => p.name === pkgName);
          if (!pkg) {
            continue;
          }
          if (pkg.json.dependencies?.[dep]) {
            pkg.json.dependencies[dep] = targetVersion;
          }
          if (pkg.json.devDependencies?.[dep]) {
            pkg.json.devDependencies[dep] = targetVersion;
          }
          fs.writeFileSync(pkg.path, JSON.stringify(pkg.json, null, 2) + "\n");
        }
      }
    }
  }
  return aligned;
}
async function addMissingWorkspaceDeps(packages, dryRun) {
  const added = [];
  const workspacePackages = /* @__PURE__ */ new Map();
  for (const pkg of packages) {
    if (pkg.name.startsWith("@kb-labs/")) {
      workspacePackages.set(pkg.name, "workspace:*");
    }
  }
  for (const pkg of packages) {
    const packageDir = path.dirname(pkg.path);
    const srcDir = path.join(packageDir, "src");
    if (!fs.existsSync(srcDir)) {
      continue;
    }
    const imports = scanImports(srcDir);
    const currentDeps = {
      ...pkg.json.dependencies,
      ...pkg.json.devDependencies
    };
    for (const imp of imports) {
      if (imp.startsWith("@kb-labs/") && workspacePackages.has(imp) && !currentDeps[imp]) {
        added.push({
          package: pkg.name,
          dep: imp,
          version: "workspace:*"
        });
        if (!dryRun) {
          if (!pkg.json.dependencies) {
            pkg.json.dependencies = {};
          }
          pkg.json.dependencies[imp] = "workspace:*";
          fs.writeFileSync(pkg.path, JSON.stringify(pkg.json, null, 2) + "\n");
        }
      }
    }
  }
  return added;
}
async function removeUnusedDeps(packages, dryRun) {
  const removed = [];
  for (const pkg of packages) {
    const packageDir = path.dirname(pkg.path);
    const srcDir = path.join(packageDir, "src");
    if (!fs.existsSync(srcDir)) {
      continue;
    }
    const imports = new Set(scanImports(srcDir));
    const deps = {
      ...pkg.json.dependencies,
      ...pkg.json.devDependencies
    };
    for (const dep of Object.keys(deps)) {
      if (isProtectedDep(dep)) {
        continue;
      }
      if (!imports.has(dep)) {
        removed.push({
          package: pkg.name,
          dep
        });
        if (!dryRun) {
          delete pkg.json.dependencies?.[dep];
          delete pkg.json.devDependencies?.[dep];
          fs.writeFileSync(pkg.path, JSON.stringify(pkg.json, null, 2) + "\n");
        }
      }
    }
  }
  return removed;
}
function scanImports(dir) {
  const imports = [];
  function walk(currentDir) {
    const entries = fs.readdirSync(currentDir, { withFileTypes: true });
    for (const entry of entries) {
      const fullPath = path.join(currentDir, entry.name);
      if (entry.isDirectory()) {
        walk(fullPath);
      } else if (entry.isFile() && /\.(ts|tsx|js|jsx)$/.test(entry.name)) {
        const content = fs.readFileSync(fullPath, "utf-8");
        const importRegex = /(?:import|require)\s*\(?['"]([^'"]+)['"]\)?/g;
        let match;
        while ((match = importRegex.exec(content)) !== null) {
          const imp = match[1];
          if (!imp) {
            continue;
          }
          const pkgName = imp.startsWith("@") ? imp.split("/").slice(0, 2).join("/") : imp.split("/")[0];
          if (pkgName) {
            imports.push(pkgName);
          }
        }
      }
    }
  }
  walk(dir);
  return Array.from(new Set(imports));
}
function isProtectedDep(dep) {
  const protectedDeps = [
    "typescript",
    "tsup",
    "esbuild",
    "vite",
    "rollup",
    "rimraf",
    "vitest",
    "jest",
    "playwright",
    "eslint",
    "prettier"
  ];
  return protectedDeps.some((p) => dep === p || dep.startsWith(`${p}-`) || dep.startsWith(`@${p}/`));
}
function outputStats(stats, flags, ui) {
  if (flags.json) {
    ui?.json?.(stats);
    return;
  }
  const sections = [];
  sections.push({
    header: "Overview",
    items: [
      `Total Packages: ${stats.totalPackages}`,
      `Total Dependencies: ${stats.totalDeps}`,
      `Duplicate Versions: ${stats.duplicates}`
    ]
  });
  if (stats.topUsed.length > 0) {
    sections.push({
      header: "Top 10 Most Used",
      items: stats.topUsed.map((d) => `${d.name} (${d.count} packages)`)
    });
  }
  ui?.success?.("Dependency statistics", {
    title: "\u{1F4CA} Dependency Statistics",
    sections
  });
}
function outputResults(result, flags, ui) {
  if (flags.json) {
    ui?.json?.(result);
    return;
  }
  const sections = [];
  const summaryItems = [
    `Packages Scanned: ${result.packagesScanned}`,
    `Mode: ${result.dryRun ? "\u{1F50D} Dry Run (no changes applied)" : "\u2705 Changes Applied"}`
  ];
  sections.push({ header: "Summary", items: summaryItems });
  if (result.alignedDeps.length > 0) {
    const alignedItems = result.alignedDeps.map(
      (a) => `${a.dep}: ${a.from} \u2192 ${a.to} (${a.packages.length} packages)`
    );
    sections.push({ header: "Aligned Versions", items: alignedItems.slice(0, 10) });
    if (result.alignedDeps.length > 10) {
      const lastSection = sections[sections.length - 1];
      if (lastSection) {
        lastSection.items.push(`... and ${result.alignedDeps.length - 10} more`);
      }
    }
  }
  if (result.addedDeps.length > 0) {
    const addedItems = result.addedDeps.map((a) => `${a.package}: +${a.dep}`);
    sections.push({ header: "Added Dependencies", items: addedItems.slice(0, 10) });
    if (result.addedDeps.length > 10) {
      const lastSection = sections[sections.length - 1];
      if (lastSection) {
        lastSection.items.push(`... and ${result.addedDeps.length - 10} more`);
      }
    }
  }
  if (result.removedDeps.length > 0) {
    const removedItems = result.removedDeps.map((r) => `${r.package}: -${r.dep}`);
    sections.push({ header: "Removed Dependencies", items: removedItems.slice(0, 10) });
    if (result.removedDeps.length > 10) {
      const lastSection = sections[sections.length - 1];
      if (lastSection) {
        lastSection.items.push(`... and ${result.removedDeps.length - 10} more`);
      }
    }
  }
  if (result.alignedDeps.length === 0 && result.addedDeps.length === 0 && result.removedDeps.length === 0) {
    sections.push({ header: "Result", items: ["\u2705 No issues found!"] });
  }
  if (result.dryRun && (result.alignedDeps.length > 0 || result.addedDeps.length > 0 || result.removedDeps.length > 0)) {
    sections.push({
      header: "Next Steps",
      items: ["Remove --dry-run flag to apply changes", "Run `pnpm install` after applying changes"]
    });
  }
  const title = result.dryRun ? "\u{1F50D} Dependency Fix Preview" : "\u2705 Dependency Fix Complete";
  ui?.success?.("Dependency fix completed", {
    title,
    sections
  });
}

export { fix_deps_default as default };
//# sourceMappingURL=fix-deps.js.map
//# sourceMappingURL=fix-deps.js.map