#!/usr/bin/env node
import {
  hashContent,
  isAllowedGamePath,
  isDynamicGeneratedPath,
  isLibraryPath,
  materializeManifest,
  writeManifestSource
} from "./chunk-C3VW3DTA.mjs";
import {
  atomicWriteFile
} from "./chunk-TAEQKBJB.mjs";
import {
  readJsonFile,
  readTextFile,
  readTextFileIfExists,
  writeTextFile
} from "./chunk-IAYRNVUC.mjs";
import {
  LOCAL_IGNORE_DIRS,
  MANIFEST_FILE,
  PROJECT_DIR_NAME,
  RULE_FILE,
  SNAPSHOT_FILE
} from "./chunk-H76MT5UR.mjs";

// src/services/project/local-files.ts
import { readdir, unlink } from "fs/promises";
import path from "path";
function isAllowedGamePath2(filePath) {
  return isAllowedGamePath(filePath);
}
function isLibraryPath2(filePath) {
  return isLibraryPath(filePath);
}
function shouldWriteScaffoldFile(filePath, existingContent) {
  if (isLibraryPath2(filePath)) return "write";
  const hasContent = existingContent !== null && existingContent.trim().length > 0;
  return hasContent ? "skip" : "write";
}
async function writeSourceFiles(rootDir, files) {
  for (const [relativePath, content] of Object.entries(files)) {
    if (content === null || content === void 0) continue;
    const filePath = path.join(rootDir, relativePath);
    await writeTextFile(filePath, content);
  }
}
async function writeScaffoldFiles(rootDir, files) {
  const written = [];
  const skipped = [];
  for (const [relativePath, content] of Object.entries(files)) {
    if (content === null || content === void 0) continue;
    const fullPath = path.join(rootDir, relativePath);
    const existingContent = await readTextFileIfExists(fullPath);
    const decision = shouldWriteScaffoldFile(relativePath, existingContent);
    if (decision === "skip") {
      skipped.push(relativePath);
      continue;
    }
    await writeTextFile(fullPath, content);
    if (existingContent !== content) {
      written.push(relativePath);
    }
  }
  written.sort();
  skipped.sort();
  return { written, skipped };
}
async function removeExtraneousFiles(rootDir, keep) {
  const localFiles = await collectLocalFiles(rootDir);
  for (const filePath of Object.keys(localFiles)) {
    if (filePath === MANIFEST_FILE || filePath === RULE_FILE) continue;
    if (!keep.has(filePath)) {
      await unlink(path.join(rootDir, filePath));
    }
  }
}
async function collectLocalFiles(rootDir) {
  const result = {};
  await walkDir(rootDir, rootDir, result);
  return result;
}
async function walkDir(rootDir, currentDir, result) {
  const entries = await readdir(currentDir, { withFileTypes: true });
  for (const entry of entries) {
    if (entry.isDirectory()) {
      if (LOCAL_IGNORE_DIRS.has(entry.name)) continue;
      await walkDir(rootDir, path.join(currentDir, entry.name), result);
    } else if (entry.isFile()) {
      const filePath = path.join(currentDir, entry.name);
      const relativePath = path.relative(rootDir, filePath);
      result[relativePath] = await readTextFile(filePath);
    }
  }
}
async function writeManifest(rootDir, manifest) {
  await writeManifestSource(rootDir, manifest);
}
async function writeRule(rootDir, ruleText) {
  const filePath = path.join(rootDir, RULE_FILE);
  await writeTextFile(filePath, ruleText);
}
async function loadManifest(rootDir) {
  return materializeManifest(rootDir);
}
async function loadRule(rootDir) {
  const filePath = path.join(rootDir, RULE_FILE);
  return readTextFile(filePath);
}
async function writeSnapshot(rootDir) {
  const files = await collectLocalFiles(rootDir);
  await writeSnapshotFromFiles(rootDir, files);
}
async function writeSnapshotFromFiles(rootDir, files) {
  const snapshot = {
    files: {}
  };
  for (const [filePath, content] of Object.entries(files)) {
    if (filePath.startsWith(`${PROJECT_DIR_NAME}/`)) continue;
    if (isDynamicGeneratedPath(filePath)) continue;
    snapshot.files[filePath] = hashContent(content);
  }
  const snapshotPath = path.join(rootDir, PROJECT_DIR_NAME, SNAPSHOT_FILE);
  await atomicWriteFile(
    snapshotPath,
    `${JSON.stringify(snapshot, null, 2)}
`,
    { mode: 420 }
  );
}
function isIgnorableLocalDiffPath(filePath) {
  return filePath.startsWith("test/generated/") || filePath.startsWith(".playwright-cli/");
}
async function getLocalDiff(rootDir) {
  const snapshotPath = path.join(rootDir, PROJECT_DIR_NAME, SNAPSHOT_FILE);
  const snapshot = await readJsonFile(snapshotPath).catch(() => null);
  if (!snapshot) {
    return { modified: [], added: [], deleted: [] };
  }
  const files = await collectLocalFiles(rootDir);
  const currentHashes = {};
  for (const [filePath, content] of Object.entries(files)) {
    if (filePath.startsWith(`${PROJECT_DIR_NAME}/`)) continue;
    if (isIgnorableLocalDiffPath(filePath)) continue;
    if (isDynamicGeneratedPath(filePath)) continue;
    currentHashes[filePath] = hashContent(content);
  }
  const modified = [];
  const added = [];
  const deleted = [];
  for (const [filePath, hash] of Object.entries(currentHashes)) {
    const prevHash = snapshot.files[filePath];
    if (!prevHash) {
      added.push(filePath);
    } else if (prevHash !== hash) {
      modified.push(filePath);
    }
  }
  for (const filePath of Object.keys(snapshot.files)) {
    if (isIgnorableLocalDiffPath(filePath)) continue;
    if (isDynamicGeneratedPath(filePath)) continue;
    if (!currentHashes[filePath]) {
      deleted.push(filePath);
    }
  }
  return { modified, added, deleted };
}

export {
  isAllowedGamePath2 as isAllowedGamePath,
  isLibraryPath2 as isLibraryPath,
  writeSourceFiles,
  writeScaffoldFiles,
  removeExtraneousFiles,
  collectLocalFiles,
  walkDir,
  writeManifest,
  writeRule,
  loadManifest,
  loadRule,
  writeSnapshot,
  writeSnapshotFromFiles,
  getLocalDiff
};
//# sourceMappingURL=chunk-27EEIZCI.mjs.map