import fs3 from 'node:fs';
import path2 from 'node:path';
import { builtinModules } from 'node:module';

// src/features/gen-html/infrastructure/local-server/dependencies/workspace.ts
var LOCAL_SERVER_SASS_VERSION = "^1.86.3";
var LOCAL_SERVER_REACT_QUERY_VERSION = "^5.81.2";
var LOCAL_SERVER_TYPES_NODE_VERSION = "^25.0.10";
var LOCAL_SERVER_TYPES_REACT_VERSION = "19.1.0";
var LOCAL_SERVER_TYPES_REACT_DOM_VERSION = "19.1.1";
var LOCAL_SERVER_TYPESCRIPT_VERSION = "5.8.2";
var LOCAL_SERVER_VITE_VERSION = "^6.3.1";
var STORYBOOK_VERSION = "8.6.14";
var IMPORT_SPECIFIER_PATTERN = /\b(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s*)?['"]([^'"`]+)['"]|\bimport\s*\(\s*['"]([^'"`]+)['"]\s*\)/g;
var SOURCE_FILE_EXTENSION_PATTERN = /\.[cm]?[jt]sx?$/i;
var WORKSPACE_PACKAGE_GROUP_NAMES = ["apps", "packages", "configs"];
var WORKSPACE_ROOT_MARKER_FILE_NAMES = ["pnpm-workspace.yaml", "pnpm-workspace.yml"];
var LOCAL_SERVER_RUNTIME_PACKAGE_NAMES = ["react", "react-dom", "@tanstack/react-query"];
var PACKAGE_MANIFEST_DEPENDENCY_FIELDS = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
var NODE_BUILTIN_MODULE_NAMES = new Set(
  builtinModules.flatMap((moduleName) => [moduleName, moduleName.replace(/^node:/, ""), `node:${moduleName.replace(/^node:/, "")}`])
);
var LOCAL_SERVER_DEFAULT_PACKAGE_JSON = {
  dependencies: {
    "@types/node": LOCAL_SERVER_TYPES_NODE_VERSION,
    "@types/react": LOCAL_SERVER_TYPES_REACT_VERSION,
    "@types/react-dom": LOCAL_SERVER_TYPES_REACT_DOM_VERSION,
    "@tanstack/react-query": LOCAL_SERVER_REACT_QUERY_VERSION,
    "@storybook/addon-essentials": STORYBOOK_VERSION,
    "@storybook/react": STORYBOOK_VERSION,
    "@storybook/react-vite": STORYBOOK_VERSION,
    react: "^19.1.0",
    "react-dom": "^19.1.0",
    sass: LOCAL_SERVER_SASS_VERSION,
    storybook: STORYBOOK_VERSION,
    typescript: LOCAL_SERVER_TYPESCRIPT_VERSION,
    vite: LOCAL_SERVER_VITE_VERSION
  }};
function isRecord(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}
function readJsonFile(filePath) {
  if (!fs3.existsSync(filePath)) {
    return void 0;
  }
  const raw = fs3.readFileSync(filePath, "utf8").trim();
  if (!raw) {
    return void 0;
  }
  return JSON.parse(raw);
}
function isBareImportSpecifier(specifier) {
  return Boolean(specifier) && !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.includes("://") && !specifier.startsWith("\0");
}
function getPackageNameFromImportSpecifier(specifier) {
  if (!isBareImportSpecifier(specifier) || NODE_BUILTIN_MODULE_NAMES.has(specifier)) {
    return "";
  }
  if (specifier.startsWith("@")) {
    const [scope, name] = specifier.split("/");
    return scope && name ? `${scope}/${name}` : "";
  }
  return specifier.split("/")[0] || "";
}
function listSourceFiles(directoryPath) {
  if (!fs3.existsSync(directoryPath) || !fs3.statSync(directoryPath).isDirectory()) {
    return [];
  }
  const collected = [];
  const queue = [directoryPath];
  while (queue.length > 0) {
    const currentDirectoryPath = queue.pop();
    if (!currentDirectoryPath) {
      continue;
    }
    for (const entry of fs3.readdirSync(currentDirectoryPath, { withFileTypes: true })) {
      const entryPath = path2.join(currentDirectoryPath, entry.name);
      if (entry.isDirectory()) {
        queue.push(entryPath);
        continue;
      }
      if (entry.isFile() && SOURCE_FILE_EXTENSION_PATTERN.test(entry.name)) {
        collected.push(entryPath);
      }
    }
  }
  return collected.sort((left, right) => left.localeCompare(right));
}
function isBundledLocalServerDependency(packageName) {
  return Object.prototype.hasOwnProperty.call(LOCAL_SERVER_DEFAULT_PACKAGE_JSON.dependencies, packageName);
}
function collectOutputDependencyNames(outputDirectory) {
  const packageNames = /* @__PURE__ */ new Set();
  for (const filePath of listSourceFiles(outputDirectory)) {
    const source = fs3.readFileSync(filePath, "utf8");
    let match = IMPORT_SPECIFIER_PATTERN.exec(source);
    while (match) {
      const packageName = getPackageNameFromImportSpecifier(match[1] || match[2] || "");
      if (packageName && !isBundledLocalServerDependency(packageName)) {
        packageNames.add(packageName);
      }
      match = IMPORT_SPECIFIER_PATTERN.exec(source);
    }
    IMPORT_SPECIFIER_PATTERN.lastIndex = 0;
  }
  return [...packageNames].sort((left, right) => left.localeCompare(right));
}

// src/features/gen-html/infrastructure/local-server/dependencies/manifest.ts
function normalizeDependencies(value) {
  if (!isRecord(value)) {
    return {};
  }
  return Object.entries(value).reduce((accumulator, [key, dependencyValue]) => {
    if (typeof dependencyValue === "string" && dependencyValue.trim()) {
      accumulator[key] = dependencyValue;
    }
    return accumulator;
  }, {});
}
function extractPackageManifestDependencies(value) {
  if (!isRecord(value)) {
    return {};
  }
  return PACKAGE_MANIFEST_DEPENDENCY_FIELDS.reduce((accumulator, fieldName) => {
    Object.assign(accumulator, normalizeDependencies(value[fieldName]));
    return accumulator;
  }, {});
}

// src/features/gen-html/infrastructure/local-server/dependencies/workspace.ts
function isWorkspaceRootDirectory(directoryPath) {
  if (!directoryPath) {
    return false;
  }
  if (WORKSPACE_ROOT_MARKER_FILE_NAMES.some((fileName) => fs3.existsSync(path2.join(directoryPath, fileName)))) {
    return true;
  }
  const packageJsonPath = path2.join(directoryPath, "package.json");
  const manifest = readJsonFile(packageJsonPath);
  if (!isRecord(manifest)) {
    return false;
  }
  return Boolean(manifest.workspaces);
}
function resolveWorkspaceRootDirectory(startDirectory) {
  let currentDirectoryPath = path2.resolve(startDirectory);
  while (!isWorkspaceRootDirectory(currentDirectoryPath)) {
    const parentDirectoryPath = path2.dirname(currentDirectoryPath);
    if (parentDirectoryPath === currentDirectoryPath) {
      return path2.resolve(startDirectory);
    }
    currentDirectoryPath = parentDirectoryPath;
  }
  return currentDirectoryPath;
}
function collectWorkspacePackageJsonPaths(rootDir) {
  const workspaceRootDir = resolveWorkspaceRootDirectory(rootDir);
  const packageJsonPaths = [path2.join(workspaceRootDir, "package.json")].filter((filePath) => fs3.existsSync(filePath));
  for (const groupName of WORKSPACE_PACKAGE_GROUP_NAMES) {
    const groupDirectoryPath = path2.join(workspaceRootDir, groupName);
    if (!fs3.existsSync(groupDirectoryPath) || !fs3.statSync(groupDirectoryPath).isDirectory()) {
      continue;
    }
    for (const entry of fs3.readdirSync(groupDirectoryPath, { withFileTypes: true })) {
      if (!entry.isDirectory()) {
        continue;
      }
      const packageJsonPath = path2.join(groupDirectoryPath, entry.name, "package.json");
      if (fs3.existsSync(packageJsonPath)) {
        packageJsonPaths.push(packageJsonPath);
      }
    }
  }
  return packageJsonPaths.sort((left, right) => left.localeCompare(right));
}
function listAncestorDirectories(startDirectory) {
  const directories = [];
  let currentDirectoryPath = path2.resolve(startDirectory);
  let parentDirectoryPath = path2.dirname(currentDirectoryPath);
  while (parentDirectoryPath !== currentDirectoryPath) {
    directories.push(currentDirectoryPath);
    currentDirectoryPath = parentDirectoryPath;
    parentDirectoryPath = path2.dirname(currentDirectoryPath);
  }
  directories.push(currentDirectoryPath);
  return directories;
}
function resolveInstalledPackageVersion(dependencyName, startDirectories) {
  const candidateDirectories = Array.from(
    new Set(
      startDirectories.flatMap((directoryPath) => {
        if (!directoryPath) {
          return [];
        }
        return listAncestorDirectories(directoryPath);
      })
    )
  );
  for (const directoryPath of candidateDirectories) {
    const packageJsonPath = path2.join(directoryPath, "node_modules", ...dependencyName.split("/"), "package.json");
    const manifest = readJsonFile(packageJsonPath);
    const version = typeof manifest?.version === "string" ? manifest.version.trim() : "";
    if (version) {
      return version;
    }
  }
  return "";
}
function resolveLocalServerRuntimeDependencies(_paths, _localServerDirectoryPath, trace) {
  const dependencyNames = [...LOCAL_SERVER_RUNTIME_PACKAGE_NAMES];
  const defaultDependencies = normalizeDependencies(LOCAL_SERVER_DEFAULT_PACKAGE_JSON.dependencies);
  const resolvedDependencies = Object.fromEntries(
    dependencyNames.map((dependencyName) => [dependencyName, defaultDependencies[dependencyName] || ""]).filter(([, version]) => Boolean(version))
  );
  trace(
    "local-server:setup:runtime-dependencies",
    Object.entries(resolvedDependencies).map(([dependencyName, version]) => `${dependencyName}@${version}`).join(", ")
  );
  return resolvedDependencies;
}
function toLocalFileDependencyValue(localServerDirectoryPath, packageDirectoryPath) {
  const relativePath = path2.relative(localServerDirectoryPath, packageDirectoryPath).split(path2.sep).join("/");
  return `file:${relativePath || "."}`;
}
function buildWorkspaceDependencyCatalog(rootDir, localServerDirectoryPath) {
  const packageJsonPaths = collectWorkspacePackageJsonPaths(rootDir);
  const catalog = /* @__PURE__ */ new Map();
  const workspacePackageDirectories = /* @__PURE__ */ new Map();
  for (const packageJsonPath of packageJsonPaths) {
    const manifest = readJsonFile(packageJsonPath);
    const packageName = typeof manifest?.name === "string" ? manifest.name.trim() : "";
    if (packageName) {
      workspacePackageDirectories.set(packageName, path2.dirname(packageJsonPath));
    }
  }
  for (const [packageName, packageDirectoryPath] of workspacePackageDirectories.entries()) {
    if (!catalog.has(packageName)) {
      catalog.set(packageName, toLocalFileDependencyValue(localServerDirectoryPath, packageDirectoryPath));
    }
  }
  for (const packageJsonPath of packageJsonPaths) {
    const manifest = readJsonFile(packageJsonPath);
    const dependencies = extractPackageManifestDependencies(manifest);
    for (const [dependencyName, version] of Object.entries(dependencies)) {
      if (catalog.has(dependencyName)) {
        continue;
      }
      if (version.startsWith("workspace:") && workspacePackageDirectories.has(dependencyName)) {
        catalog.set(
          dependencyName,
          toLocalFileDependencyValue(localServerDirectoryPath, workspacePackageDirectories.get(dependencyName) || "")
        );
        continue;
      }
      if (version.trim()) {
        catalog.set(dependencyName, version);
      }
    }
  }
  return Object.fromEntries([...catalog.entries()].sort(([left], [right]) => left.localeCompare(right)));
}
function resolveGeneratedOutputDependencies(paths, localServerDirectoryPath, outputDirectory, trace) {
  const dependencyNames = collectOutputDependencyNames(outputDirectory);
  if (dependencyNames.length === 0) {
    return {};
  }
  const workspaceCatalog = buildWorkspaceDependencyCatalog(paths.rootDir, localServerDirectoryPath);
  const workspaceRootDir = resolveWorkspaceRootDirectory(paths.rootDir);
  const resolvedDependencies = {};
  const unresolvedDependencyNames = [];
  for (const dependencyName of dependencyNames) {
    const version = workspaceCatalog[dependencyName] || resolveInstalledPackageVersion(dependencyName, [localServerDirectoryPath, paths.rootDir, workspaceRootDir]);
    if (!version) {
      unresolvedDependencyNames.push(dependencyName);
      continue;
    }
    resolvedDependencies[dependencyName] = version;
  }
  if (Object.keys(resolvedDependencies).length > 0) {
    trace(
      "local-server:setup:generated-dependencies",
      Object.entries(resolvedDependencies).map(([dependencyName, version]) => `${dependencyName}@${version}`).join(", ")
    );
  }
  if (unresolvedDependencyNames.length > 0) {
    trace("local-server:setup:unresolved-dependencies", unresolvedDependencyNames.join(", "));
  }
  return resolvedDependencies;
}

export { resolveGeneratedOutputDependencies, resolveLocalServerRuntimeDependencies };
