"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var sync_exports = {};
__export(sync_exports, {
  getChangedFiles: () => getChangedFiles,
  hashContent: () => hashContent,
  scanDirectory: () => scanDirectory,
  shouldIncludeFile: () => shouldIncludeFile
});
module.exports = __toCommonJS(sync_exports);
var path = __toESM(require("path"));
var fs = __toESM(require("fs"));
var crypto = __toESM(require("crypto"));
var import_child_process = require("child_process");
var import_picomatch = __toESM(require("picomatch"));
var import_languages = require("../extraction/languages");
function buildExcludeMatchers(config) {
  const patterns = [...config.exclude];
  return patterns.map((p) => {
    try {
      return (0, import_picomatch.default)(p);
    } catch {
      return () => false;
    }
  });
}
function buildIncludeMatcher(config) {
  if (!config.include || config.include.length === 0) return null;
  const matchers = config.include.map((p) => {
    try {
      return (0, import_picomatch.default)(p);
    } catch {
      return () => false;
    }
  });
  return (s) => matchers.some((m) => m(s));
}
function scanDirectoryWalk(root, config, signal, visited = /* @__PURE__ */ new Set()) {
  const results = [];
  const walk = (dir) => {
    if (signal?.aborted) return;
    let realDir;
    try {
      realDir = fs.realpathSync(dir);
    } catch {
      return;
    }
    if (visited.has(realDir)) return;
    visited.add(realDir);
    const ignoreFile = path.join(dir, ".kirographignore");
    if (fs.existsSync(ignoreFile)) return;
    let entries;
    try {
      entries = fs.readdirSync(dir, { withFileTypes: true });
    } catch {
      return;
    }
    for (const entry of entries) {
      if (signal?.aborted) return;
      const full = path.join(dir, entry.name);
      const rel = path.relative(root, full).replace(/\\/g, "/");
      if (entry.isDirectory()) {
        walk(full);
      } else if (entry.isFile()) {
        if (shouldIncludeFile(rel, config)) {
          const lang = (0, import_languages.detectLanguage)(full);
          if (lang !== "unknown") results.push(full);
        }
      }
    }
  };
  walk(root);
  return results;
}
function findGitRoots(root) {
  const roots = [];
  const walk = (dir) => {
    if (fs.existsSync(path.join(dir, ".git"))) {
      roots.push(dir);
      return;
    }
    let entries;
    try {
      entries = fs.readdirSync(dir, { withFileTypes: true });
    } catch {
      return;
    }
    for (const entry of entries) {
      if (entry.isDirectory()) walk(path.join(dir, entry.name));
    }
  };
  walk(root);
  return roots.length > 0 ? roots : [root];
}
function shouldIncludeFile(relPath, config) {
  const excludeMatchers = buildExcludeMatchers(config);
  if (excludeMatchers.some((m) => {
    try {
      return m(relPath) || m(relPath + "/");
    } catch {
      return false;
    }
  })) return false;
  const includeMatcher = buildIncludeMatcher(config);
  if (includeMatcher && !includeMatcher(relPath)) return false;
  return true;
}
function hashContent(content) {
  return crypto.createHash("sha256").update(content).digest("hex");
}
async function scanDirectory(root, config, signal) {
  if (signal?.aborted) return [];
  const gitRoots = findGitRoots(root);
  const allFiles = [];
  for (const gitRoot of gitRoots) {
    if (signal?.aborted) return allFiles;
    try {
      const output = (0, import_child_process.execFileSync)("git", ["ls-files", "--cached", "--others", "--exclude-standard"], {
        cwd: gitRoot,
        encoding: "utf8",
        timeout: 1e4,
        stdio: ["ignore", "pipe", "ignore"]
      });
      if (signal?.aborted) return allFiles;
      const files = output.split("\n").filter(Boolean).map((rel) => path.join(gitRoot, rel)).filter((abs) => {
        const rel = path.relative(root, abs).replace(/\\/g, "/");
        return shouldIncludeFile(rel, config) && (0, import_languages.detectLanguage)(abs) !== "unknown";
      });
      allFiles.push(...files);
    } catch {
      allFiles.push(...scanDirectoryWalk(gitRoot, config, signal));
    }
  }
  return allFiles;
}
async function getChangedFiles(root, config) {
  const added = [];
  const modified = [];
  const removed = [];
  const gitRoots = findGitRoots(root);
  for (const gitRoot of gitRoots) {
    try {
      const output = (0, import_child_process.execFileSync)("git", ["status", "--porcelain", "--no-renames"], {
        cwd: gitRoot,
        encoding: "utf8",
        timeout: 1e4,
        stdio: ["ignore", "pipe", "ignore"]
      });
      for (const line of output.split("\n").filter(Boolean)) {
        const statusCode = line.slice(0, 2);
        const relPath = line.slice(3).trim();
        const absPath = path.join(gitRoot, relPath);
        if ((0, import_languages.detectLanguage)(absPath) === "unknown") continue;
        if (statusCode === "??") {
          added.push(absPath);
        } else if (statusCode[0] === "D" || statusCode[1] === "D") {
          removed.push(absPath);
        } else {
          modified.push(absPath);
        }
      }
    } catch {
    }
  }
  return { added, modified, removed };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  getChangedFiles,
  hashContent,
  scanDirectory,
  shouldIncludeFile
});
//# sourceMappingURL=index.js.map
