import {
  normalizeValidationIssue
} from "./chunk-2GXVIN57.js";
import {
  REGISTRATION_SURFACES,
  RULE_CODES,
  validateWURulesSync
} from "./chunk-L737LQ4C.js";
import {
  INVARIANT_TYPES,
  loadInvariants
} from "./chunk-EZ6ZBYBM.js";
import {
  WU_STATUS
} from "./chunk-V6OJGLBA.js";

// ../core/dist/wu-lint.js
import { existsSync } from "fs";
import { minimatch } from "minimatch";
var WU_LINT_ERROR_TYPES = {
  ACCEPTANCE_PATH_NOT_IN_CODE_PATHS: "acceptance_path_not_in_code_paths",
  CODE_PATH_CONFLICTS_INVARIANT: "code_path_conflicts_invariant",
  ACCEPTANCE_CONFLICTS_INVARIANT: "acceptance_conflicts_invariant",
  /** CLI registration parity surface missing */
  REGISTRATION_PARITY_MISSING: "registration_parity_missing",
  /** Backward-compatible key for minimum test intent */
  UNIT_TESTS_REQUIRED: "unit_tests_required",
  /** Canonical minimum test intent key */
  MINIMUM_TEST_INTENT_REQUIRED: "minimum_test_intent_required"
};
var REGISTRATION_SURFACES2 = {
  PUBLIC_MANIFEST: REGISTRATION_SURFACES.PUBLIC_MANIFEST,
  MCP_TOOLS: REGISTRATION_SURFACES.MCP_TOOLS
};
var CLI_COMMAND_EXCLUDE_PATTERNS = [
  "__tests__/",
  "/lib/",
  "/shared/",
  "/commands/",
  "/init.ts",
  REGISTRATION_SURFACES2.PUBLIC_MANIFEST,
  REGISTRATION_SURFACES2.MCP_TOOLS
];
var FILE_PATH_PATTERN = /(?:^|[\s'"`])([a-zA-Z0-9_-]+\/[a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+)/g;
function extractFilePaths(text) {
  const paths = [];
  let match;
  while ((match = FILE_PATH_PATTERN.exec(text)) !== null) {
    const captured = match[1];
    if (captured) {
      paths.push(captured);
    }
  }
  FILE_PATH_PATTERN.lastIndex = 0;
  return paths;
}
function pathMatchesCodePaths(filePath, codePaths) {
  for (const pattern of codePaths) {
    if (filePath === pattern) {
      return true;
    }
    if (minimatch(filePath, pattern)) {
      return true;
    }
  }
  return false;
}
function validateAcceptanceCodePaths(wu) {
  const { id, code_paths = [] } = wu;
  const acceptance = Array.isArray(wu.acceptance) ? wu.acceptance : [];
  const errors = [];
  for (const criterion of acceptance) {
    const referencedPaths = extractFilePaths(criterion);
    for (const referencedPath of referencedPaths) {
      if (!pathMatchesCodePaths(referencedPath, code_paths)) {
        errors.push({
          type: WU_LINT_ERROR_TYPES.ACCEPTANCE_PATH_NOT_IN_CODE_PATHS,
          wuId: id,
          path: referencedPath,
          criterion,
          message: `Acceptance criterion references '${referencedPath}' which is not in code_paths`,
          suggestion: `Add '${referencedPath}' to code_paths or remove the reference from acceptance criteria`
        });
      }
    }
  }
  return {
    valid: errors.length === 0,
    errors
  };
}
function checkForbiddenFileInvariant(invariant, wu) {
  const { id, code_paths = [] } = wu;
  const acceptance = Array.isArray(wu.acceptance) ? wu.acceptance : [];
  const errors = [];
  if (code_paths.includes(invariant.path)) {
    errors.push({
      type: WU_LINT_ERROR_TYPES.CODE_PATH_CONFLICTS_INVARIANT,
      wuId: id,
      invariantId: invariant.id,
      path: invariant.path,
      message: `code_paths includes '${invariant.path}' which conflicts with invariant ${invariant.id}: ${invariant.description}`,
      suggestion: invariant.message || `Remove '${invariant.path}' from code_paths`
    });
  }
  for (const criterion of acceptance) {
    if (criterion.includes(invariant.path)) {
      errors.push({
        type: WU_LINT_ERROR_TYPES.ACCEPTANCE_CONFLICTS_INVARIANT,
        wuId: id,
        invariantId: invariant.id,
        path: invariant.path,
        criterion,
        message: `Acceptance criterion references forbidden file '${invariant.path}' (${invariant.id}: ${invariant.description})`,
        suggestion: invariant.message
      });
    }
  }
  return errors;
}
function checkMutualExclusivityInvariant(invariant, wu) {
  const { id, code_paths = [] } = wu;
  const errors = [];
  const conflictingPaths = invariant.paths.filter((p) => code_paths.includes(p));
  if (conflictingPaths.length > 1) {
    errors.push({
      type: WU_LINT_ERROR_TYPES.CODE_PATH_CONFLICTS_INVARIANT,
      wuId: id,
      invariantId: invariant.id,
      paths: conflictingPaths,
      message: `code_paths includes multiple mutually exclusive files (${invariant.id}): ${conflictingPaths.join(", ")}`,
      suggestion: invariant.message || `Only one of these files should exist: ${invariant.paths.join(", ")}`
    });
  }
  return errors;
}
function validateInvariantsCompliance(wu, invariants) {
  const errors = [];
  for (const invariant of invariants) {
    if (invariant.type === INVARIANT_TYPES.FORBIDDEN_FILE) {
      errors.push(...checkForbiddenFileInvariant(invariant, wu));
    } else if (invariant.type === INVARIANT_TYPES.MUTUAL_EXCLUSIVITY) {
      errors.push(...checkMutualExclusivityInvariant(invariant, wu));
    }
  }
  return {
    valid: errors.length === 0,
    errors
  };
}
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
  WU_STATUS.DONE,
  WU_STATUS.CANCELLED,
  WU_STATUS.COMPLETED,
  WU_STATUS.ABANDONED,
  WU_STATUS.SUPERSEDED
]);
var LINT_TYPE_BY_RULE_CODE = {
  [RULE_CODES.MINIMUM_TEST_INTENT]: WU_LINT_ERROR_TYPES.MINIMUM_TEST_INTENT_REQUIRED,
  [RULE_CODES.PARITY_MISSING_SURFACE]: WU_LINT_ERROR_TYPES.REGISTRATION_PARITY_MISSING
};
function toLintIssue(wuId, issue) {
  const normalized = normalizeValidationIssue(issue, {
    wuId,
    typeByCode: LINT_TYPE_BY_RULE_CODE
  });
  return {
    type: normalized.type,
    wuId,
    message: normalized.message,
    suggestion: normalized.suggestion
  };
}
function lintWUSpec(wu, options = {}) {
  const allErrors = [];
  const allWarnings = [];
  const phase = options.phase || "structural";
  const acceptanceResult = validateAcceptanceCodePaths(wu);
  allErrors.push(...acceptanceResult.errors);
  let invariants = options.invariants || [];
  if (!options.invariants && options.invariantsPath) {
    try {
      if (existsSync(options.invariantsPath)) {
        invariants = loadInvariants(options.invariantsPath);
      }
    } catch {
    }
  }
  if (invariants.length > 0) {
    const invariantsResult = validateInvariantsCompliance(wu, invariants);
    allErrors.push(...invariantsResult.errors);
  }
  const rulesResult = validateWURulesSync({
    id: wu.id,
    type: wu.type,
    status: wu.status,
    code_paths: wu.code_paths,
    tests: wu.tests || wu.test_paths,
    cwd: options.context?.cwd,
    baseRef: options.context?.baseRef,
    headRef: options.context?.headRef
  }, { phase });
  for (const issue of rulesResult.errors) {
    allErrors.push(toLintIssue(wu.id, issue));
  }
  for (const issue of rulesResult.warnings) {
    allWarnings.push(toLintIssue(wu.id, issue));
  }
  return {
    valid: allErrors.length === 0,
    errors: allErrors,
    warnings: allWarnings
  };
}
function formatLintErrors(errors) {
  if (errors.length === 0) {
    return "";
  }
  const lines = ["WU SPEC LINT ERRORS:", ""];
  for (const error of errors) {
    lines.push(`- ${error.message}`);
    if (error.suggestion) {
      lines.push(`  Fix: ${error.suggestion}`);
    }
    lines.push("");
  }
  return lines.join("\n");
}

export {
  lintWUSpec,
  formatLintErrors
};
