// src/actions/claude-rules.ts
import { spawnSync } from "child_process";
import {
  existsSync as existsSync3,
  mkdirSync,
  readdirSync as readdirSync2,
  readFileSync as readFileSync3,
  unlinkSync,
  writeFileSync
} from "fs";
import PATH3 from "path";
import chalk from "chalk";

// src/lib/claudeMdTemplate.ts
import {
  readdirSync,
  readFileSync,
  statSync
} from "fs";
import { createRequire } from "module";
import PATH from "path";
var require2 = createRequire(import.meta.url);
var packageRoot = PATH.dirname(require2.resolve("@xylabs/toolchain/package.json"));
var templatesDir = PATH.resolve(packageRoot, "templates", "claude");
function applyPackageManager(content, pm) {
  const xyCommand = pm === "npm" ? "npm exec -- xy" : pm === "bun" ? "bun run xy" : `${pm} xy`;
  const addCommand = pm === "npm" ? "npm install" : pm === "bun" ? "bun add" : `${pm} add`;
  return content.replaceAll("yarn xy", xyCommand).replaceAll("pnpm xy", xyCommand).replaceAll("yarn add", addCommand).replaceAll("pnpm add", addCommand);
}
var XYLABS_RULES_PREFIX = "xylabs-";
var claudeMdRuleTemplates = () => {
  const rulesDir = PATH.resolve(templatesDir, "rules");
  const files = readdirSync(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md"));
  const result = {};
  for (const file of files) {
    result[file] = readFileSync(PATH.resolve(rulesDir, file), "utf8");
  }
  return result;
};
var claudeMdLocalTemplate = () => readFileSync(PATH.resolve(templatesDir, "CLAUDE-local.md"), "utf8");

// src/pm/workspaces.ts
import { existsSync, readFileSync as readFileSync2 } from "fs";
import PATH2 from "path";
import { globSync } from "glob";
function readJsonFile(path) {
  if (!existsSync(path)) return void 0;
  try {
    return JSON.parse(readFileSync2(path, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH2.resolve(cwd, "package.json"));
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!packageManager) return void 0;
  return packageManager.split("@")[0];
}

// src/pm/detectPackageManager.ts
import { existsSync as existsSync2 } from "fs";
var knownPackageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
function detectPackageManager() {
  const packageManager = detectPackageManagerFromPackageJson();
  if (packageManager && knownPackageManagers.has(packageManager)) {
    return packageManager;
  }
  if (existsSync2("pnpm-lock.yaml") || existsSync2("pnpm-workspace.yaml")) return "pnpm";
  if (existsSync2("bun.lock") || existsSync2("bun.lockb")) return "bun";
  if (existsSync2("yarn.lock") || existsSync2(".yarnrc.yml")) return "yarn";
  if (existsSync2("package-lock.json") || existsSync2("npm-shrinkwrap.json")) return "npm";
  return "yarn";
}

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/actions/claude-rules.ts
var syncRuleFiles = (rulesDir) => {
  const pm = detectPackageManager();
  const rawTemplates = claudeMdRuleTemplates();
  const templates = {};
  for (const [name, content] of Object.entries(rawTemplates)) {
    templates[name] = applyPackageManager(content, pm);
  }
  const templateNames = new Set(Object.keys(templates));
  let updated = 0;
  let created = 0;
  for (const [filename, content] of Object.entries(templates)) {
    const targetPath = PATH3.resolve(rulesDir, filename);
    const existing = existsSync3(targetPath) ? readFileSync3(targetPath, "utf8") : void 0;
    if (existing === content) continue;
    writeFileSync(targetPath, content, "utf8");
    if (existing) {
      updated++;
    } else {
      created++;
    }
  }
  return {
    created,
    templateNames,
    updated
  };
};
var removeStaleRules = (rulesDir, templateNames) => {
  const existingRules = readdirSync2(rulesDir).filter((f) => f.startsWith(XYLABS_RULES_PREFIX) && f.endsWith(".md"));
  let removed = 0;
  for (const file of existingRules) {
    if (!templateNames.has(file)) {
      unlinkSync(PATH3.resolve(rulesDir, file));
      removed++;
    }
  }
  return removed;
};
var logRulesResult = (created, updated, removed) => {
  if (created || updated || removed) {
    const parts = [
      created ? `${created} created` : "",
      updated ? `${updated} updated` : "",
      removed ? `${removed} removed` : ""
    ].filter(Boolean);
    console.log(chalk.green(`.claude/rules/${XYLABS_RULES_PREFIX}*.md: ${parts.join(", ")}`));
  } else {
    console.log(chalk.gray(`.claude/rules/${XYLABS_RULES_PREFIX}*.md: already up to date`));
  }
};
var ensureProjectClaudeMd = (cwd, force) => {
  const projectPath = PATH3.resolve(cwd, "CLAUDE.md");
  if (!existsSync3(projectPath) || force) {
    if (force && existsSync3(projectPath)) {
      console.log(chalk.yellow("Regenerating CLAUDE.md"));
    }
    console.log(chalk.green("Generating CLAUDE.md via claude /init..."));
    const result = spawnSync("claude", ["-p", "/init", "--allowedTools", "Read", "Write", "Glob", "Grep"], {
      cwd,
      shell: true,
      stdio: "inherit"
    });
    if (result.status !== 0) {
      console.error(chalk.red("claude /init failed \u2014 is Claude Code installed?"));
      return 1;
    }
  } else {
    console.log(chalk.gray("CLAUDE.md already exists (skipped, use --force to regenerate)"));
  }
  return 0;
};
var ensureLocalClaudeMd = (cwd) => {
  const localPath = PATH3.resolve(cwd, "CLAUDE.local.md");
  if (existsSync3(localPath)) {
    console.log(chalk.gray("CLAUDE.local.md already exists (skipped)"));
  } else {
    writeFileSync(localPath, claudeMdLocalTemplate(), "utf8");
    console.log(chalk.green("Generated CLAUDE.local.md"));
  }
};
var claudeRules = ({ force } = {}) => {
  const cwd = INIT_CWD();
  const rulesDir = PATH3.resolve(cwd, ".claude", "rules");
  mkdirSync(rulesDir, { recursive: true });
  const {
    created,
    templateNames,
    updated
  } = syncRuleFiles(rulesDir);
  const removed = removeStaleRules(rulesDir, templateNames);
  logRulesResult(created, updated, removed);
  const claudeMdResult = ensureProjectClaudeMd(cwd, force);
  ensureLocalClaudeMd(cwd);
  return claudeMdResult ?? 0;
};
export {
  claudeRules
};
//# sourceMappingURL=claude-rules.mjs.map