import { defineCommand } from '@kb-labs/sdk';
import { CACHE_KEYS } from '@kb-labs/quality-contracts';
import fs from 'fs';
import path from 'path';

// src/cli/commands/health.ts
var health_default = defineCommand({
  id: "quality:health",
  description: "Check monorepo health score",
  handler: {
    async execute(ctx, input) {
      const { ui, platform } = ctx;
      const flags = input.flags ?? input;
      const health = await calculateHealth(ctx.cwd, flags.package);
      await platform.cache.set(CACHE_KEYS.HEALTH, health, 5 * 60 * 1e3);
      await platform.analytics.track("quality:health", {
        score: health.score,
        grade: health.grade,
        issueCount: health.issues.length,
        packageSpecific: !!flags.package
      });
      outputHealth(health, flags, ui);
      return {
        exitCode: health.score < 60 ? 1 : 0,
        result: health
      };
    }
  }
});
function findPackages(rootDir, specificPackage) {
  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)) {
        if (specificPackage) {
          const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
          if (pkgJson.name === specificPackage || pkgDir.name === specificPackage) {
            packages.push(packageJsonPath);
          }
        } else {
          packages.push(packageJsonPath);
        }
      }
    }
  }
  return packages;
}
async function calculateHealth(rootDir, specificPackage) {
  const packages = findPackages(rootDir, specificPackage);
  let score = 100;
  const issues = [];
  const allDeps = /* @__PURE__ */ new Map();
  for (const packagePath of packages) {
    const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
    const deps = {
      ...packageJson.dependencies,
      ...packageJson.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/"));
  if (duplicates.length > 0) {
    const penalty = Math.min(20, duplicates.length * 2);
    score -= penalty;
    issues.push({
      type: "duplicates",
      severity: "warning",
      message: `${duplicates.length} duplicate dependencies (-${penalty})`
    });
  }
  let missingReadmes = 0;
  for (const packagePath of packages) {
    const packageDir = path.dirname(packagePath);
    const readmePath = path.join(packageDir, "README.md");
    if (!fs.existsSync(readmePath)) {
      missingReadmes++;
    }
  }
  if (missingReadmes > 0) {
    const penalty = Math.min(15, missingReadmes);
    score -= penalty;
    issues.push({
      type: "missing-docs",
      severity: "warning",
      message: `${missingReadmes} packages missing README (-${penalty})`
    });
  }
  let namingIssues = 0;
  for (const packagePath of packages) {
    const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
    const packageName = packageJson.name;
    if (!packageName || !packageName.startsWith("@kb-labs/")) {
      namingIssues++;
    }
  }
  if (namingIssues > 0) {
    const penalty = Math.min(10, namingIssues * 2);
    score -= penalty;
    issues.push({
      type: "naming",
      severity: "critical",
      message: `${namingIssues} packages with naming issues (-${penalty})`
    });
  }
  let missingTypes = 0;
  for (const packagePath of packages) {
    const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf-8"));
    if (!packageJson.types && !packageJson.typings) {
      missingTypes++;
    }
  }
  if (missingTypes > 0) {
    const penalty = Math.min(15, missingTypes);
    score -= penalty;
    issues.push({
      type: "missing-types",
      severity: "warning",
      message: `${missingTypes} packages missing types field (-${penalty})`
    });
  }
  let grade;
  if (score >= 90) {
    grade = "A";
  } else if (score >= 80) {
    grade = "B";
  } else if (score >= 70) {
    grade = "C";
  } else if (score >= 60) {
    grade = "D";
  } else {
    grade = "F";
  }
  return {
    score: Math.max(0, score),
    grade,
    issues
  };
}
function outputHealth(health, flags, ui) {
  if (flags.json) {
    ui?.json?.(health);
    return;
  }
  const sections = [];
  const scoreItems = [
    `Score: ${health.score}/100`,
    `Grade: ${health.grade}`,
    `Status: ${health.score >= 80 ? "\u2705 Healthy" : health.score >= 60 ? "\u26A0\uFE0F Needs Attention" : "\u274C Critical"}`
  ];
  sections.push({ header: "Health Score", items: scoreItems });
  if (health.issues.length > 0) {
    const issueItems = health.issues.map((issue) => {
      const icon = issue.severity === "critical" ? "\u274C" : issue.severity === "warning" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
      return `${icon} ${issue.message}`;
    });
    if (flags.detailed) {
      sections.push({ header: "Issues (Detailed)", items: issueItems });
    } else {
      sections.push({ header: "Issues", items: issueItems });
    }
  } else {
    sections.push({ header: "Issues", items: ["\u2705 No issues found!"] });
  }
  if (health.score < 90) {
    const recommendations = [];
    if (health.issues.some((i) => i.type === "duplicates")) {
      recommendations.push("Run `kb quality:fix-deps --align-versions` to fix duplicates");
    }
    if (health.issues.some((i) => i.type === "missing-docs")) {
      recommendations.push("Add README.md files to packages");
    }
    if (health.issues.some((i) => i.type === "missing-types")) {
      recommendations.push('Add "types" field to package.json or enable dts generation');
    }
    if (recommendations.length > 0) {
      sections.push({ header: "Recommendations", items: recommendations });
    }
  }
  const title = health.score >= 80 ? "\u{1F49A} Monorepo Health Check - Healthy" : health.score >= 60 ? "\u{1F49B} Monorepo Health Check - Needs Attention" : "\u2764\uFE0F Monorepo Health Check - Critical";
  ui?.success?.("Health check completed", {
    title,
    sections
  });
}

export { health_default as default };
//# sourceMappingURL=health.js.map
//# sourceMappingURL=health.js.map