import {
  WorkspaceControlPlaneConfigSchema,
  resolvePackManifestPaths,
  resolvePackSchemaMetadata
} from "./chunk-HANJXVKW.js";
import {
  runCLI,
  withMicroWorktree
} from "./chunk-2GXVIN57.js";
import {
  FILE_SYSTEM
} from "./chunk-DWMLTXKQ.js";
import {
  LumenFlowConfigSchema,
  MANAGED_ROOT_KEYS,
  WORKSPACE_CONFIG_FILE_NAME,
  WRITABLE_ROOT_KEYS,
  clearConfigCache,
  findProjectRoot,
  normalizeConfigKeys
} from "./chunk-V6OJGLBA.js";
import {
  ErrorCodes,
  createError,
  die
} from "./chunk-RXRKBBSM.js";

// src/config-set.ts
import path from "path";
import { existsSync, readFileSync, writeFileSync } from "fs";
import YAML from "yaml";
var LOG_PREFIX = "[config:set]";
var OPERATION_NAME = "config-set";
var ARG_KEY = "--key";
var ARG_VALUE = "--value";
var ARG_HELP = "--help";
var COMMIT_PREFIX = "chore: config:set";
var WORKSPACE_INIT_COMMAND = "pnpm workspace-init --yes";
var WORKSPACE_FILE_NAME = WORKSPACE_CONFIG_FILE_NAME;
var KNOWN_SD_SUBKEYS = [
  "version",
  "methodology",
  "gates",
  "directories",
  "state",
  "git",
  "wu",
  "memory",
  "ui",
  "yaml",
  "agents",
  "experimental",
  "cleanup",
  "telemetry",
  "cloud",
  "lanes",
  "escalation",
  "package_manager",
  "test_runner",
  "build_command"
];
var SD_PACK_ID = "software-delivery";
var SET_HELP_TEXT = `Usage: pnpm config:set --key <dotpath> --value <value>

Safely update ${WORKSPACE_FILE_NAME} via micro-worktree commit.
Keys must be fully qualified from the workspace root.
Validates against schema before writing.

Required:
  ${ARG_KEY} <dotpath>    Config key in dot notation (fully qualified)
  ${ARG_VALUE} <value>    Value to set (comma-separated for arrays)

Examples:
  pnpm config:set --key software_delivery.methodology.testing --value test-after
  pnpm config:set --key software_delivery.gates.minCoverage --value 85
  pnpm config:set --key control_plane.sync_interval --value 60
  pnpm config:set --key memory_namespace --value my-project
`;
var GET_HELP_TEXT = `Usage: pnpm config:get --key <dotpath>

Read and display a value from ${WORKSPACE_FILE_NAME}.
Keys must be fully qualified from the workspace root.

Required:
  ${ARG_KEY} <dotpath>    Config key in dot notation (fully qualified)

Examples:
  pnpm config:get --key software_delivery.methodology.testing
  pnpm config:get --key software_delivery.gates.minCoverage
  pnpm config:get --key control_plane.sync_interval
`;
function parseConfigSetArgs(argv) {
  if (argv.includes(ARG_HELP)) {
    console.log(SET_HELP_TEXT);
    process.exit(0);
  }
  let key;
  let value;
  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i];
    const next = argv[i + 1];
    switch (arg) {
      case ARG_KEY:
        key = next;
        i++;
        break;
      case ARG_VALUE:
        value = next;
        i++;
        break;
      default:
        break;
    }
  }
  if (!key) {
    throw createError(
      ErrorCodes.INVALID_ARGUMENT,
      `${ARG_KEY} is required. Run with ${ARG_HELP} for usage.`
    );
  }
  if (value === void 0) {
    throw createError(
      ErrorCodes.INVALID_ARGUMENT,
      `${ARG_VALUE} is required. Run with ${ARG_HELP} for usage.`
    );
  }
  return { key, value };
}
function parseConfigGetArgs(argv) {
  if (argv.includes(ARG_HELP)) {
    console.log(GET_HELP_TEXT);
    process.exit(0);
  }
  let key;
  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i];
    const next = argv[i + 1];
    if (arg === ARG_KEY) {
      key = next;
      i++;
    }
  }
  if (!key) {
    throw createError(
      ErrorCodes.INVALID_ARGUMENT,
      `${ARG_KEY} is required. Run with ${ARG_HELP} for usage.`
    );
  }
  return { key };
}
function routeConfigKey(key, packConfigKeys) {
  const segments = key.split(".");
  const firstSegment = segments[0];
  const subPath = segments.slice(1).join(".");
  if (WRITABLE_ROOT_KEYS.has(firstSegment)) {
    return { type: "workspace-root", rootKey: firstSegment, subPath };
  }
  const packId = packConfigKeys.get(firstSegment);
  if (packId !== void 0) {
    return { type: "pack-config", rootKey: firstSegment, subPath, packId };
  }
  if (firstSegment in MANAGED_ROOT_KEYS) {
    const managedCommand = MANAGED_ROOT_KEYS[firstSegment];
    return { type: "managed-error", rootKey: firstSegment, command: managedCommand };
  }
  const suggestion = buildDidYouMeanSuggestion(key, firstSegment, packConfigKeys);
  return { type: "unknown-error", rootKey: firstSegment, suggestion };
}
function buildDidYouMeanSuggestion(fullKey, firstSegment, packConfigKeys) {
  if (KNOWN_SD_SUBKEYS.includes(firstSegment)) {
    for (const [configKey] of packConfigKeys) {
      return `Did you mean "${configKey}.${fullKey}"?`;
    }
  }
  return void 0;
}
function getConfigValue(obj, dotpath) {
  const segments = dotpath.split(".");
  let current = obj;
  for (const segment of segments) {
    if (current === null || current === void 0 || typeof current !== "object") {
      return void 0;
    }
    current = current[segment];
  }
  return current;
}
function setNestedValue(obj, dotpath, value) {
  const result = JSON.parse(JSON.stringify(obj));
  const segments = dotpath.split(".");
  let current = result;
  for (let i = 0; i < segments.length - 1; i++) {
    const segment = segments[i];
    if (current[segment] === void 0 || current[segment] === null || typeof current[segment] !== "object") {
      current[segment] = {};
    }
    current = current[segment];
  }
  const lastSegment = segments[segments.length - 1];
  current[lastSegment] = value;
  return result;
}
function isNumericString(value) {
  if (value === "" || value.trim() !== value) return false;
  const num = Number(value);
  return !isNaN(num) && isFinite(num);
}
function coerceValue(value, existingValue) {
  if (value === "true") return true;
  if (value === "false") return false;
  if (typeof existingValue === "number" || isNumericString(value)) {
    const numValue = Number(value);
    if (!isNaN(numValue)) return numValue;
  }
  if (Array.isArray(existingValue)) {
    const newItems = value.split(",").map((s) => s.trim());
    return [...existingValue, ...newItems];
  }
  return value;
}
function findStrippedKeys(input, parsed, prefix = "") {
  const stripped = [];
  for (const key of Object.keys(input)) {
    const fullPath = prefix ? `${prefix}.${key}` : key;
    if (!(key in parsed)) {
      stripped.push(fullPath);
      continue;
    }
    const inputVal = input[key];
    const parsedVal = parsed[key];
    if (inputVal !== null && inputVal !== void 0 && typeof inputVal === "object" && !Array.isArray(inputVal) && parsedVal !== null && parsedVal !== void 0 && typeof parsedVal === "object" && !Array.isArray(parsedVal)) {
      stripped.push(
        ...findStrippedKeys(
          inputVal,
          parsedVal,
          fullPath
        )
      );
    }
  }
  return stripped;
}
function applyConfigSet(workspace, key, rawValue, packConfigKeys, packSchemaOpts) {
  const route = routeConfigKey(key, packConfigKeys);
  switch (route.type) {
    case "managed-error":
      return {
        ok: false,
        error: `Key "${route.rootKey}" is managed by a dedicated command. Use \`pnpm ${route.command}\` instead.`
      };
    case "unknown-error": {
      const hint = route.suggestion ? ` ${route.suggestion}` : "";
      return {
        ok: false,
        error: `Unknown root key "${route.rootKey}".${hint} Valid root keys: ${[...WRITABLE_ROOT_KEYS].join(", ")}, or a pack config_key (${[...packConfigKeys.keys()].join(", ")}).`
      };
    }
    case "workspace-root":
      return applyWorkspaceRootSet(workspace, key, rawValue);
    case "pack-config":
      return applyPackConfigSet(workspace, route, rawValue, packSchemaOpts);
  }
}
var SCALAR_ROOT_KEYS = /* @__PURE__ */ new Set(["memory_namespace", "event_namespace"]);
function applyWorkspaceRootSet(workspace, key, rawValue) {
  const segments = key.split(".");
  const rootKey = segments[0];
  const subPath = segments.slice(1).join(".");
  if (SCALAR_ROOT_KEYS.has(rootKey)) {
    if (subPath) {
      return {
        ok: false,
        error: `"${rootKey}" is a scalar value and does not support sub-path writes. Use: config:set --key ${rootKey} --value <string>`
      };
    }
    return { ok: true, config: setNestedValue(workspace, key, rawValue) };
  }
  if (rootKey === "control_plane") {
    if (!subPath) {
      return {
        ok: false,
        error: `Cannot overwrite "control_plane" with a scalar value. Set individual sub-keys instead (e.g., control_plane.sync_interval).`
      };
    }
    const existingCP = workspace.control_plane;
    const cpConfig = existingCP && typeof existingCP === "object" && !Array.isArray(existingCP) ? JSON.parse(JSON.stringify(existingCP)) : {};
    const existingValue2 = getConfigValue(cpConfig, subPath);
    const coercedValue2 = coerceValue(rawValue, existingValue2);
    const updatedCP = setNestedValue(cpConfig, subPath, coercedValue2);
    const parseResult = WorkspaceControlPlaneConfigSchema.partial().strict().safeParse(updatedCP);
    if (!parseResult.success) {
      const issues = parseResult.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
      return {
        ok: false,
        error: `Validation failed for ${key}=${rawValue}: ${issues}`
      };
    }
    const updatedWorkspace2 = { ...workspace, control_plane: updatedCP };
    return { ok: true, config: updatedWorkspace2 };
  }
  const existingValue = getConfigValue(workspace, key);
  const coercedValue = coerceValue(rawValue, existingValue);
  const updatedWorkspace = setNestedValue(workspace, key, coercedValue);
  return { ok: true, config: updatedWorkspace };
}
function validateJsonSchemaPath(schema, dotpath) {
  const segments = dotpath.split(".");
  let currentSchema = schema;
  const unrecognized = [];
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i];
    const properties = currentSchema.properties;
    if (!properties || !(segment in properties)) {
      unrecognized.push(segments.slice(0, i + 1).join("."));
      break;
    }
    currentSchema = properties[segment];
  }
  return unrecognized;
}
function applyPackConfigSet(workspace, route, rawValue, packSchemaOpts) {
  const packSection = workspace[route.rootKey];
  const packConfig = packSection && typeof packSection === "object" && !Array.isArray(packSection) ? packSection : {};
  if (!route.subPath) {
    return {
      ok: false,
      error: `Key must target a nested field under ${route.rootKey} (e.g., ${route.rootKey}.methodology.testing).`
    };
  }
  const existingValue = getConfigValue(packConfig, route.subPath);
  const coercedValue = coerceValue(rawValue, existingValue);
  const updatedPackConfig = setNestedValue(packConfig, route.subPath, coercedValue);
  if (route.packId === SD_PACK_ID || !packSchemaOpts) {
    return applyPackConfigSetWithZod(workspace, route, rawValue, updatedPackConfig);
  }
  const hasSchema = packSchemaOpts.packSchemaMap.get(route.packId);
  if (!hasSchema) {
    return {
      ok: false,
      error: `Pack "${route.packId}" declares no config_schema. Config writes to "${route.rootKey}" are rejected because the pack has not declared a schema for validation.`
    };
  }
  const jsonSchema = packSchemaOpts.jsonSchemas.get(route.packId);
  if (!jsonSchema) {
    return {
      ok: false,
      error: `Pack "${route.packId}" declares a config_schema but the schema could not be loaded. Config writes to "${route.rootKey}" are rejected.`
    };
  }
  return applyPackConfigSetWithJsonSchema(workspace, route, updatedPackConfig, jsonSchema);
}
function applyPackConfigSetWithZod(workspace, route, rawValue, updatedPackConfig) {
  const normalized = normalizeConfigKeys(updatedPackConfig);
  const parseResult = LumenFlowConfigSchema.safeParse(normalized);
  if (!parseResult.success) {
    const issues = parseResult.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
    return {
      ok: false,
      error: `Validation failed for ${route.rootKey}.${route.subPath}=${rawValue}: ${issues}`
    };
  }
  const parsedData = parseResult.data;
  const writeTargetKey = route.subPath.split(".")[0];
  let strippedKeys;
  if (writeTargetKey && typeof normalized[writeTargetKey] === "object" && normalized[writeTargetKey] !== null && !Array.isArray(normalized[writeTargetKey]) && typeof parsedData[writeTargetKey] === "object" && parsedData[writeTargetKey] !== null && !Array.isArray(parsedData[writeTargetKey])) {
    strippedKeys = findStrippedKeys(
      normalized[writeTargetKey],
      parsedData[writeTargetKey],
      writeTargetKey
    );
  } else {
    strippedKeys = writeTargetKey && writeTargetKey in normalized && !(writeTargetKey in parsedData) ? [writeTargetKey] : [];
  }
  if (strippedKeys.length > 0) {
    return {
      ok: false,
      error: `Unknown config key(s) rejected: ${strippedKeys.join(", ")}. These keys are not recognized by the ${route.rootKey} schema.`
    };
  }
  const updatedWorkspace = {
    ...workspace,
    [route.rootKey]: updatedPackConfig
  };
  return { ok: true, config: updatedWorkspace };
}
function applyPackConfigSetWithJsonSchema(workspace, route, updatedPackConfig, jsonSchema) {
  const unrecognized = validateJsonSchemaPath(jsonSchema, route.subPath);
  if (unrecognized.length > 0) {
    return {
      ok: false,
      error: `Unknown config key(s) rejected for pack "${route.packId}": ${unrecognized.join(", ")}. These keys are not recognized by the ${route.rootKey} schema.`
    };
  }
  const updatedWorkspace = {
    ...workspace,
    [route.rootKey]: updatedPackConfig
  };
  return { ok: true, config: updatedWorkspace };
}
function readRawWorkspace(workspacePath) {
  const content = readFileSync(workspacePath, FILE_SYSTEM.UTF8);
  const parsed = YAML.parse(content);
  return parsed && typeof parsed === "object" ? parsed : {};
}
function writeRawWorkspace(workspacePath, workspace) {
  const nextContent = YAML.stringify(workspace);
  writeFileSync(workspacePath, nextContent, FILE_SYSTEM.UTF8);
}
function loadPackConfigKeys(projectRoot, workspace) {
  const packs = workspace.packs;
  if (!Array.isArray(packs)) {
    return /* @__PURE__ */ new Map();
  }
  return resolvePackManifestPaths({ projectRoot, packs });
}
function loadPackSchemaOpts(projectRoot, workspace) {
  const packs = workspace.packs;
  const packSchemaMap = /* @__PURE__ */ new Map();
  const jsonSchemas = /* @__PURE__ */ new Map();
  if (!Array.isArray(packs)) {
    return { packSchemaMap, jsonSchemas };
  }
  packSchemaMap.set(SD_PACK_ID, true);
  const schemaMetadata = resolvePackSchemaMetadata({ projectRoot, packs });
  for (const [packId, meta] of schemaMetadata) {
    if (packId === SD_PACK_ID) {
      continue;
    }
    if (meta.hasSchema && meta.schemaPath) {
      packSchemaMap.set(packId, true);
      if (existsSync(meta.schemaPath)) {
        try {
          const schemaContent = readFileSync(meta.schemaPath, "utf8");
          const parsed = JSON.parse(schemaContent);
          jsonSchemas.set(packId, parsed);
        } catch {
        }
      }
    } else {
      packSchemaMap.set(packId, false);
    }
  }
  return { packSchemaMap, jsonSchemas };
}
async function main() {
  const userArgs = process.argv.slice(2);
  const options = parseConfigSetArgs(userArgs);
  const projectRoot = findProjectRoot();
  const workspacePath = path.join(projectRoot, WORKSPACE_FILE_NAME);
  if (!existsSync(workspacePath)) {
    die(`${LOG_PREFIX} Missing ${WORKSPACE_FILE_NAME}. Run \`${WORKSPACE_INIT_COMMAND}\` first.`);
  }
  const rawWorkspace = readRawWorkspace(workspacePath);
  const packConfigKeys = loadPackConfigKeys(projectRoot, rawWorkspace);
  const route = routeConfigKey(options.key, packConfigKeys);
  if (route.type === "managed-error") {
    die(
      `${LOG_PREFIX} Key "${route.rootKey}" is managed by a dedicated command. Use \`pnpm ${route.command}\` instead.`
    );
  }
  if (route.type === "unknown-error") {
    const hint = route.suggestion ? ` ${route.suggestion}` : "";
    die(
      `${LOG_PREFIX} Unknown root key "${route.rootKey}".${hint} Valid root keys: ${[...WRITABLE_ROOT_KEYS].join(", ")}, or a pack config_key (${[...packConfigKeys.keys()].join(", ")}).`
    );
  }
  console.log(
    `${LOG_PREFIX} Setting ${options.key}=${options.value} in ${WORKSPACE_FILE_NAME} via micro-worktree isolation`
  );
  await withMicroWorktree({
    operation: OPERATION_NAME,
    id: `config-set-${Date.now()}`,
    logPrefix: LOG_PREFIX,
    pushOnly: true,
    async execute({ worktreePath }) {
      const workspaceRelPath = WORKSPACE_FILE_NAME;
      const mwWorkspacePath = path.join(worktreePath, workspaceRelPath);
      if (!existsSync(mwWorkspacePath)) {
        die(`${LOG_PREFIX} Config file not found in micro-worktree: ${workspaceRelPath}`);
      }
      const workspace = readRawWorkspace(mwWorkspacePath);
      const mwPackConfigKeys = loadPackConfigKeys(worktreePath, workspace);
      const mwPackSchemaOpts = loadPackSchemaOpts(worktreePath, workspace);
      const result = applyConfigSet(
        workspace,
        options.key,
        options.value,
        mwPackConfigKeys,
        mwPackSchemaOpts
      );
      if (!result.ok) {
        die(`${LOG_PREFIX} ${result.error}`);
      }
      writeRawWorkspace(mwWorkspacePath, result.config);
      console.log(`${LOG_PREFIX} Config validated and written successfully.`);
      return {
        commitMessage: `${COMMIT_PREFIX} ${options.key}=${options.value}`,
        files: [workspaceRelPath]
      };
    }
  });
  clearConfigCache();
  console.log(`${LOG_PREFIX} Successfully set ${options.key}=${options.value}`);
}
if (import.meta.main) {
  void runCLI(main);
}

export {
  WORKSPACE_FILE_NAME,
  parseConfigSetArgs,
  parseConfigGetArgs,
  routeConfigKey,
  getConfigValue,
  applyConfigSet,
  loadPackConfigKeys,
  loadPackSchemaOpts,
  main
};
