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

// src/features/gen-html/infrastructure/local-server/dependencies/published-install.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";
}
var REQUIRED_LOCAL_SERVER_PUBLISHED_PACKAGE_NAMES = [
  "sales-frontend-api",
  "sales-frontend-assets",
  "sales-frontend-bridge",
  "sales-frontend-components",
  "sales-frontend-design-system",
  "sales-frontend-hooks",
  "sales-frontend-solution",
  "sales-frontend-stores",
  "sales-frontend-typescript-config"
];
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")
  };
}
function isRecord(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

// 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;
  }, {});
}

// src/features/gen-html/infrastructure/local-server/dependencies/published-install.ts
var LATEST_VERSION_TAG = "latest";
var PUBLISHED_INSTALL_BASE_ARGS = ["install", "--legacy-peer-deps", "--no-audit", "--no-fund"];
var PACKAGE_CUSTOM_JSON_TEMPLATE = `// package-custom.json
// local-server \uC758 package.json \uC744 \uC0DD\uC131\uD560 \uB54C \uC6B0\uC120 \uC801\uC6A9\uD560 \uCEE4\uC2A4\uD140 \uC124\uC815 \uD30C\uC77C\uC785\uB2C8\uB2E4.
//
// - dependencies: \uD2B9\uC815 \uD328\uD0A4\uC9C0\uB97C \uC9C0\uC815\uD55C \uBC84\uC804\uC73C\uB85C \uC124\uCE58\uD569\uB2C8\uB2E4.
//   (\uC9C0\uC815\uD558\uC9C0 \uC54A\uC73C\uBA74 sales-frontend-* \uACF5\uC6A9 \uD328\uD0A4\uC9C0\uB294 latest \uB85C \uC124\uCE58\uB429\uB2C8\uB2E4)
// - \uADF8 \uC678 package.json \uC18D\uC131(scripts, type \uB4F1)\uC740 \uC0DD\uC131\uB418\uB294 package.json \uC5D0 \uBCD1\uD569\uB429\uB2C8\uB2E4. (\uCEE4\uC2A4\uD140 \uC6B0\uC120)
//
// \uC0AC\uC6A9 \uC608\uC2DC:
// {
//   "dependencies": {
//     "sales-frontend-design-system": "1.2.3"
//   },
//   "scripts": {
//     "custom": "echo hello"
//   }
// }
{}
`;
function stripJsonComments(input) {
  let result = "";
  let insideString = false;
  let insideLineComment = false;
  let insideBlockComment = false;
  for (let index = 0; index < input.length; index += 1) {
    const character = input[index];
    const nextCharacter = input[index + 1];
    if (insideLineComment) {
      if (character === "\n") {
        insideLineComment = false;
        result += character;
      }
      continue;
    }
    if (insideBlockComment) {
      if (character === "*" && nextCharacter === "/") {
        insideBlockComment = false;
        index += 1;
      }
      continue;
    }
    if (insideString) {
      result += character;
      if (character === "\\") {
        result += nextCharacter ?? "";
        index += 1;
      } else if (character === '"') {
        insideString = false;
      }
      continue;
    }
    if (character === '"') {
      insideString = true;
      result += character;
      continue;
    }
    if (character === "/" && nextCharacter === "/") {
      insideLineComment = true;
      index += 1;
      continue;
    }
    if (character === "/" && nextCharacter === "*") {
      insideBlockComment = true;
      index += 1;
      continue;
    }
    result += character;
  }
  return result;
}
function ensureLocalServerPackageCustomFile(paths, trace) {
  const { packageCustomJsonPath } = getLocalServerPaths(paths);
  if (fs.existsSync(packageCustomJsonPath)) {
    return false;
  }
  fs.mkdirSync(path.dirname(packageCustomJsonPath), { recursive: true });
  fs.writeFileSync(packageCustomJsonPath, PACKAGE_CUSTOM_JSON_TEMPLATE, "utf8");
  trace("local-server:package-custom:created", packageCustomJsonPath);
  return true;
}
function readLocalServerPackageCustom(paths, trace) {
  const { packageCustomJsonPath } = getLocalServerPaths(paths);
  if (!fs.existsSync(packageCustomJsonPath)) {
    return {};
  }
  const raw = stripJsonComments(fs.readFileSync(packageCustomJsonPath, "utf8")).trim();
  if (!raw) {
    return {};
  }
  let parsed;
  try {
    parsed = JSON.parse(raw);
  } catch (error) {
    trace("local-server:package-custom:parse-failed", getErrorSummary(error));
    throw new Error(
      `package-custom.json \uC744 \uD574\uC11D\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. JSON \uD615\uC2DD\uC744 \uD655\uC778\uD558\uC138\uC694: ${packageCustomJsonPath} (${getErrorSummary(error)})`
    );
  }
  if (!isRecord(parsed)) {
    trace("local-server:package-custom:invalid-shape", typeof parsed);
    throw new Error(
      `package-custom.json \uC758 \uCD5C\uC0C1\uC704\uB294 JSON \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4. \uD615\uC2DD\uC744 \uD655\uC778\uD558\uC138\uC694: ${packageCustomJsonPath}`
    );
  }
  return parsed;
}
function applyLocalServerPackageCustomManifest(packageJson, custom) {
  const manifestOverrides = { ...custom };
  delete manifestOverrides.dependencies;
  if (Object.keys(manifestOverrides).length === 0) {
    return packageJson;
  }
  return {
    ...packageJson,
    ...manifestOverrides
  };
}
function resolveInstalledVersionInDirectory(directoryPath, dependencyName) {
  const manifestPath = path.join(directoryPath, "node_modules", ...dependencyName.split("/"), "package.json");
  if (!fs.existsSync(manifestPath)) {
    return "";
  }
  try {
    const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
    return typeof manifest.version === "string" ? manifest.version.trim() : "";
  } catch {
    return "";
  }
}
function resolveRequiredPublishedInstallTargets(custom) {
  const customDependencies = normalizeDependencies(custom.dependencies);
  const targetNames = /* @__PURE__ */ new Set([...REQUIRED_LOCAL_SERVER_PUBLISHED_PACKAGE_NAMES, ...Object.keys(customDependencies)]);
  const targets = {};
  for (const dependencyName of targetNames) {
    targets[dependencyName] = customDependencies[dependencyName] || LATEST_VERSION_TAG;
  }
  return targets;
}
function resolvePendingInstallSpecs(directoryPath, targets, force) {
  const specs = [];
  for (const [dependencyName, version] of Object.entries(targets)) {
    const installedVersion = resolveInstalledVersionInDirectory(directoryPath, dependencyName);
    if (force) {
      specs.push(`${dependencyName}@${version}`);
      continue;
    }
    if (!installedVersion) {
      specs.push(`${dependencyName}@${version}`);
      continue;
    }
    if (version !== LATEST_VERSION_TAG && version !== installedVersion) {
      specs.push(`${dependencyName}@${version}`);
    }
  }
  return specs;
}
function installRequiredPublishedDependencies(paths, trace, force = false) {
  const { directoryPath } = getLocalServerPaths(paths);
  const custom = readLocalServerPackageCustom(paths, trace);
  const targets = resolveRequiredPublishedInstallTargets(custom);
  const specs = resolvePendingInstallSpecs(directoryPath, targets, force);
  if (specs.length === 0) {
    trace("local-server:published-install:skip", `force=${force}`);
    return [];
  }
  trace("local-server:published-install:start", `npm install ${specs.join(" ")}`);
  const result = spawnSync("npm", [...PUBLISHED_INSTALL_BASE_ARGS, ...specs], {
    cwd: directoryPath,
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 20,
    stdio: "inherit"
  });
  if (result.error || result.status !== 0) {
    trace("local-server:published-install:failed", getErrorSummary(result.error || result.stderr || result.status));
    throw new Error("\uB85C\uCEEC \uD504\uB9AC\uBDF0 \uC11C\uBC84 \uACF5\uC6A9 \uD328\uD0A4\uC9C0 \uC124\uCE58\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
  }
  trace("local-server:published-install:done", specs.join(" "));
  return specs;
}

export { applyLocalServerPackageCustomManifest, ensureLocalServerPackageCustomFile, installRequiredPublishedDependencies, readLocalServerPackageCustom, resolveRequiredPublishedInstallTargets, stripJsonComments };
