import {
  asRecord
} from "./chunk-HMEVZKPQ.js";
import {
  createWUParser,
  runCLI
} from "./chunk-2GXVIN57.js";
import {
  GIT_DIRECTORY_NAME,
  WORKSPACE_CONFIG_FILE_NAME,
  findProjectRoot,
  getConfig
} from "./chunk-V6OJGLBA.js";

// src/lane-health.ts
import fg from "fast-glob";
import { minimatch } from "minimatch";
import chalk from "chalk";
var LOG_PREFIX = "[lane:health]";
var CONFIG_FILE_NAME = WORKSPACE_CONFIG_FILE_NAME;
var MAX_DISPLAY_FILES = 5;
var MAX_DISPLAY_GAPS = 10;
var GIT_DIR_GLOB = `${GIT_DIRECTORY_NAME}/**`;
var RECURSIVE_GIT_DIR_GLOB = `**/${GIT_DIRECTORY_NAME}/**`;
var DEFAULT_EXCLUDE_PATTERNS = [
  "node_modules/**",
  GIT_DIR_GLOB,
  "dist/**",
  "build/**",
  "coverage/**",
  ".turbo/**",
  "*.lock",
  "pnpm-lock.yaml",
  "package-lock.json",
  "yarn.lock",
  ".lumenflow/**",
  "worktrees/**"
];
var CODE_FILE_EXTENSIONS = [
  ".ts",
  ".tsx",
  ".js",
  ".jsx",
  ".mjs",
  ".cjs",
  ".vue",
  ".svelte",
  ".py",
  ".go",
  ".rs",
  ".java",
  ".kt",
  ".swift",
  ".c",
  ".cpp",
  ".h",
  ".hpp",
  ".cs",
  ".rb",
  ".php"
];
function parseLaneDefinition(lane) {
  const laneObj = asRecord(lane);
  if (!laneObj) {
    return null;
  }
  if (typeof laneObj.name !== "string" || !Array.isArray(laneObj.code_paths)) {
    return null;
  }
  return {
    name: laneObj.name,
    code_paths: laneObj.code_paths.filter((p) => typeof p === "string"),
    wip_limit: typeof laneObj.wip_limit === "number" ? laneObj.wip_limit : void 0
  };
}
function loadLaneDefinitions(projectRoot) {
  try {
    const config = getConfig({
      projectRoot,
      reload: true,
      strictWorkspace: true
    });
    return (config.lanes?.definitions ?? []).map(parseLaneDefinition).filter((lane) => lane !== null);
  } catch {
    return [];
  }
}
function patternsCanOverlap(patternA, patternB) {
  const testPathA = patternA.replace(/\*\*/g, "test/nested").replace(/\*/g, "testfile");
  const testPathB = patternB.replace(/\*\*/g, "test/nested").replace(/\*/g, "testfile");
  return minimatch(testPathB, patternA) || minimatch(testPathA, patternB);
}
function findOverlappingFiles(patternA, patternB) {
  const globOptions = {
    dot: true,
    ignore: ["**/node_modules/**", RECURSIVE_GIT_DIR_GLOB, "**/worktrees/**"],
    followSymbolicLinks: false,
    suppressErrors: true
  };
  const filesA = new Set(fg.sync(patternA, globOptions));
  const filesB = new Set(fg.sync(patternB, globOptions));
  return [...filesA].filter((file) => filesB.has(file));
}
function checkLanePairOverlap(laneA, laneB) {
  const overlaps = [];
  for (const pathA of laneA.code_paths) {
    for (const pathB of laneB.code_paths) {
      if (patternsCanOverlap(pathA, pathB)) {
        let files = [];
        try {
          files = findOverlappingFiles(pathA, pathB);
        } catch {
        }
        overlaps.push({
          lanes: [laneA.name, laneB.name],
          pattern: `${pathA} <-> ${pathB}`,
          files
        });
      }
    }
  }
  return overlaps;
}
function detectLaneOverlaps(lanes) {
  const overlaps = [];
  for (let i = 0; i < lanes.length; i++) {
    for (let j = i + 1; j < lanes.length; j++) {
      const pairOverlaps = checkLanePairOverlap(lanes[i], lanes[j]);
      overlaps.push(...pairOverlaps);
    }
  }
  return {
    hasOverlaps: overlaps.length > 0,
    overlaps
  };
}
function buildCodeFilesPattern() {
  const extensions = CODE_FILE_EXTENSIONS.map((ext) => ext.replace(".", "")).join(",");
  return `**/*.{${extensions}}`;
}
function detectCoverageGaps(lanes, options) {
  const { projectRoot, excludePatterns = DEFAULT_EXCLUDE_PATTERNS, codeOnly = true } = options;
  const allFilesPattern = codeOnly ? buildCodeFilesPattern() : "**/*";
  const globOptions = {
    cwd: projectRoot,
    dot: true,
    ignore: excludePatterns,
    onlyFiles: true,
    followSymbolicLinks: false,
    suppressErrors: true
  };
  const allFiles = fg.sync(allFilesPattern, globOptions);
  const coveredFiles = /* @__PURE__ */ new Set();
  for (const lane of lanes) {
    for (const pattern of lane.code_paths) {
      const matchedFiles = fg.sync(pattern, {
        ...globOptions,
        ignore: ["**/node_modules/**", RECURSIVE_GIT_DIR_GLOB, "**/worktrees/**"]
      });
      matchedFiles.forEach((file) => coveredFiles.add(file));
    }
  }
  const uncoveredFiles = allFiles.filter((file) => !coveredFiles.has(file));
  return {
    hasGaps: uncoveredFiles.length > 0,
    uncoveredFiles
  };
}
function getExitCode(report) {
  return report.healthy ? 0 : 1;
}
function formatOverlapSection(overlap) {
  const lines = [];
  lines.push(`    ${chalk.cyan(overlap.lanes[0])} <-> ${chalk.cyan(overlap.lanes[1])}`);
  lines.push(`    Pattern: ${overlap.pattern}`);
  lines.push(`    Files (${overlap.files.length}):`);
  const displayFiles = overlap.files.slice(0, MAX_DISPLAY_FILES);
  displayFiles.forEach((file) => lines.push(`      - ${file}`));
  if (overlap.files.length > MAX_DISPLAY_FILES) {
    lines.push(`      ... and ${overlap.files.length - MAX_DISPLAY_FILES} more`);
  }
  lines.push("");
  return lines;
}
function formatLaneHealthReport(report) {
  const lines = [];
  lines.push("");
  lines.push(chalk.bold("=".repeat(60)));
  lines.push(chalk.bold.cyan("  Lane Health Report"));
  lines.push(chalk.bold("=".repeat(60)));
  lines.push("");
  if (report.healthy) {
    lines.push(chalk.green.bold("  Status: healthy"));
    lines.push("");
    lines.push("  All lane configurations are valid:");
    lines.push("    - No overlapping code_paths detected");
    lines.push("    - All code files covered by lanes");
  } else {
    lines.push(chalk.red.bold("  Status: Issues detected"));
  }
  lines.push("");
  if (report.overlaps.hasOverlaps) {
    lines.push(chalk.yellow.bold("  Overlapping Code Paths"));
    lines.push("  " + "-".repeat(40));
    lines.push("");
    report.overlaps.overlaps.forEach((overlap) => {
      lines.push(...formatOverlapSection(overlap));
    });
  }
  if (report.gaps.hasGaps) {
    lines.push(chalk.yellow.bold("  Coverage Gaps"));
    lines.push("  " + "-".repeat(40));
    lines.push("");
    lines.push(`    ${report.gaps.uncoveredFiles.length} files not covered by UnsafeAny lane:`);
    lines.push("");
    const displayFiles = report.gaps.uncoveredFiles.slice(0, MAX_DISPLAY_GAPS);
    displayFiles.forEach((file) => lines.push(`      - ${file}`));
    if (report.gaps.uncoveredFiles.length > MAX_DISPLAY_GAPS) {
      lines.push(`      ... and ${report.gaps.uncoveredFiles.length - MAX_DISPLAY_GAPS} more`);
    }
    lines.push("");
  }
  lines.push(chalk.bold("=".repeat(60)));
  lines.push("");
  return lines.join("\n");
}
var log = console.log.bind(console);
var warn = console.warn.bind(console);
function runLaneHealthCheck(options) {
  const { projectRoot = findProjectRoot(), checkCoverage = true, excludePatterns } = options;
  const lanes = loadLaneDefinitions(projectRoot);
  if (lanes.length === 0) {
    warn(`${LOG_PREFIX} No lane definitions found in ${CONFIG_FILE_NAME}`);
    return {
      overlaps: { hasOverlaps: false, overlaps: [] },
      gaps: { hasGaps: false, uncoveredFiles: [] },
      healthy: true
    };
  }
  const overlaps = detectLaneOverlaps(lanes);
  let gaps = { hasGaps: false, uncoveredFiles: [] };
  if (checkCoverage) {
    gaps = detectCoverageGaps(lanes, { projectRoot, excludePatterns });
  }
  return {
    overlaps,
    gaps,
    healthy: !overlaps.hasOverlaps && !gaps.hasGaps
  };
}
async function main() {
  const args = createWUParser({
    name: "lane-health",
    description: "Check lane configuration health (WU-1188)",
    options: [
      { name: "json", flags: "-j, --json", type: "boolean", description: "Output as JSON" },
      {
        name: "verbose",
        flags: "-v, --verbose",
        type: "boolean",
        description: "Show verbose output"
      },
      {
        name: "no-coverage",
        flags: "--no-coverage",
        type: "boolean",
        description: "Skip coverage gap detection"
      }
    ],
    required: []
  });
  const {
    json,
    verbose,
    "no-coverage": noCoverage
  } = args;
  const projectRoot = findProjectRoot();
  if (verbose) {
    log(`${LOG_PREFIX} Checking lane health in: ${projectRoot}`);
  }
  const report = runLaneHealthCheck({
    projectRoot,
    checkCoverage: !noCoverage
  });
  if (json) {
    log(JSON.stringify(report, null, 2));
  } else {
    log(formatLaneHealthReport(report));
  }
  process.exit(getExitCode(report));
}
if (import.meta.main) {
  void runCLI(main);
}

export {
  loadLaneDefinitions,
  detectLaneOverlaps,
  detectCoverageGaps,
  getExitCode,
  formatLaneHealthReport,
  runLaneHealthCheck,
  main
};
