import fs from 'node:fs';
import path from 'node:path';
import { inspect } from 'node:util';
import { builtinModules } from 'node:module';

// src/features/retouch/application/retouch-files.ts
function stringifyUnknown(value) {
  if (value === void 0 || value === null) {
    return "";
  }
  if (typeof value === "string") {
    return value;
  }
  if (Buffer.isBuffer(value)) {
    return value.toString("utf8");
  }
  if (value instanceof Error) {
    return value.stack || value.message;
  }
  return inspect(value, { depth: 6, breakLength: 120 });
}
function getErrorSummary(error) {
  if (error instanceof Error) {
    return `${error.name}: ${error.message}`;
  }
  return stringifyUnknown(error) || "Unknown error";
}
new Set(
  builtinModules.flatMap((moduleName) => [moduleName, moduleName.replace(/^node:/, ""), `node:${moduleName.replace(/^node:/, "")}`])
);
function getLocalServerPaths(paths) {
  const directoryPath = path.join(paths.baseDir, "local-server");
  const generatedDirectoryPath = path.join(directoryPath, "generated");
  const multipleDirectoryPath = path.join(directoryPath, "multiple");
  const storybookConfigDirectoryPath = path.join(directoryPath, ".storybook");
  return {
    directoryPath,
    generatedDirectoryPath,
    generatedRegistryPath: path.join(directoryPath, "generated-registry.json"),
    multipleDirectoryPath,
    logPath: path.join(directoryPath, "server.log"),
    packageJsonPath: path.join(directoryPath, "package.json"),
    packageCustomJsonPath: path.join(directoryPath, "package-custom.json"),
    previewTargetPath: path.join(directoryPath, "preview-target.json"),
    refreshLockPath: path.join(directoryPath, "refresh.lock"),
    scssModuleDeclarationPath: path.join(directoryPath, "scss.d.ts"),
    serverLockPath: path.join(directoryPath, "server.lock"),
    statePath: path.join(directoryPath, "server-state.json"),
    storybookConfigDirectoryPath,
    storybookMainConfigPath: path.join(storybookConfigDirectoryPath, "main.ts"),
    storybookManagerConfigPath: path.join(storybookConfigDirectoryPath, "manager.tsx"),
    storybookPreviewConfigPath: path.join(storybookConfigDirectoryPath, "preview.ts"),
    tsconfigPath: path.join(directoryPath, "tsconfig.json")
  };
}

// src/features/retouch/application/retouch-files.ts
var RETOUCH_SOURCE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".ts", ".jsx", ".js", ".scss", ".css"]);
function collectRetouchSourceFiles(directory) {
  if (!fs.existsSync(directory)) {
    return [];
  }
  return fs.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && RETOUCH_SOURCE_FILE_EXTENSIONS.has(path.extname(entry.name))).map((entry) => {
    const absolutePath = path.join(directory, entry.name);
    return {
      absolutePath,
      content: fs.readFileSync(absolutePath, "utf8"),
      relativePath: entry.name
    };
  }).sort((left, right) => left.relativePath.localeCompare(right.relativePath));
}
function computeRetouchFileChanges(directory, beforeFiles, afterFiles) {
  const beforeMap = new Map(beforeFiles.map((file) => [file.relativePath, file.content]));
  const afterMap = new Map(afterFiles.map((file) => [file.relativePath, file.content]));
  const relativePaths = Array.from(/* @__PURE__ */ new Set([...beforeMap.keys(), ...afterMap.keys()])).sort((left, right) => left.localeCompare(right));
  return relativePaths.map((relativePath) => ({
    absolutePath: path.join(directory, relativePath),
    after: afterMap.get(relativePath) ?? "",
    before: beforeMap.get(relativePath) ?? "",
    relativePath
  })).filter((change) => change.before !== change.after);
}
function resolveRetouchTargetFile(paths, importPath) {
  const localServerPaths = getLocalServerPaths(paths);
  const absolutePath = path.resolve(localServerPaths.directoryPath, importPath);
  const relativeToGenerated = path.relative(localServerPaths.generatedDirectoryPath, absolutePath);
  if (relativeToGenerated === "" || relativeToGenerated.startsWith("..") || path.isAbsolute(relativeToGenerated)) {
    throw new Error(`generated \uB514\uB809\uD130\uB9AC \uBC16\uC758 \uD30C\uC77C\uC740 \uD3B8\uC9D1\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. importPath=${importPath}`);
  }
  if (!fs.existsSync(absolutePath)) {
    throw new Error(`\uB300\uC0C1 \uC2A4\uD1A0\uB9AC \uD30C\uC77C\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. ${absolutePath}`);
  }
  return { absolutePath, directory: path.dirname(absolutePath) };
}
function applyRetouchFiles(paths, files, trace) {
  const { generatedDirectoryPath } = getLocalServerPaths(paths);
  const written = [];
  for (const file of files) {
    const normalizedPath = path.normalize(file.absolutePath);
    const relativeToGenerated = path.relative(generatedDirectoryPath, normalizedPath);
    if (relativeToGenerated === "" || relativeToGenerated.startsWith("..") || path.isAbsolute(relativeToGenerated)) {
      throw new Error(`generated \uB514\uB809\uD130\uB9AC \uBC16\uC758 \uD30C\uC77C\uC740 \uC800\uC7A5\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. ${file.absolutePath}`);
    }
    try {
      fs.mkdirSync(path.dirname(normalizedPath), { recursive: true });
      fs.writeFileSync(normalizedPath, file.content, "utf8");
      written.push(normalizedPath);
    } catch (error) {
      trace("retouch:apply:failed", `${normalizedPath} ${getErrorSummary(error)}`);
      throw error;
    }
  }
  trace("retouch:apply:done", `written=${written.length}`);
  return written;
}

export { applyRetouchFiles, collectRetouchSourceFiles, computeRetouchFileChanges, resolveRetouchTargetFile };
