// @bun
import {
  resolveCommandContext,
  resolveEnvironmentRemoteContext
} from "./chunk-2jcqy5j6.js";
import {
  DEPENDENCY_ERROR_CODES,
  DependencyError
} from "./chunk-g85b0ce9.js";
import {
  createCliLogger
} from "./chunk-t993tmz7.js";
import {
  isAdkError
} from "./chunk-px7fts59.js";
import {
  __require
} from "./chunk-dhs2bg35.js";

// src/utils/dependency-cli.ts
import readline from "readline";
function isDependencyErrorLike(err) {
  if (err instanceof DependencyError) {
    return true;
  }
  if (!err || typeof err !== "object") {
    return false;
  }
  const code = err.code;
  const message = err.message;
  return typeof code === "string" && DEPENDENCY_ERROR_CODES.includes(code) && typeof message === "string";
}
function formatJsonError(err) {
  if (isDependencyErrorLike(err)) {
    const body = {
      ok: false,
      error: {
        code: err.code,
        message: err.message,
        ...err.details !== undefined && { details: err.details },
        ...err.suggestion !== undefined && { suggestion: err.suggestion }
      }
    };
    return JSON.stringify(body, null, 2);
  }
  if (isAdkError(err)) {
    const body = {
      ok: false,
      error: {
        code: err.code,
        message: err.message,
        ...err.details !== undefined && { details: err.details },
        ...err.suggestion !== undefined && { suggestion: err.suggestion }
      }
    };
    return JSON.stringify(body, null, 2);
  }
  const message = err instanceof Error ? err.message : String(err);
  return JSON.stringify({ ok: false, error: { code: "SYSTEM_ERROR", message } }, null, 2);
}
var USER_ERROR_CODES = new Set([
  "AUTH_REQUIRED",
  "INTEGRATION_NOT_FOUND",
  "PLUGIN_NOT_FOUND",
  "INTERFACE_NOT_FOUND",
  "VERSION_NOT_FOUND",
  "MISSING_INPUT",
  "MISSING_DEPENDENCY",
  "AMBIGUOUS_DEPENDENCY",
  "INTERFACE_NOT_IMPLEMENTED",
  "SAME_SOURCE_TARGET",
  "SOURCE_LOCK_MISSING",
  "INVALID_CONFIG",
  "BOT_NOT_FOUND",
  "BUILTIN_INTERFACE_IMMUTABLE"
]);
var STATE_ERROR_CODES = new Set([
  "LOCK_DRIFT",
  "MIGRATION_CONFLICT",
  "PROD_CONFIRMATION_REQUIRED",
  "UNINSTALL_REQUIRES_CONFIRMATION"
]);
function exitCodeFor(err) {
  if (isDependencyErrorLike(err)) {
    if (STATE_ERROR_CODES.has(err.code))
      return 3;
    if (USER_ERROR_CODES.has(err.code))
      return 1;
    return 2;
  }
  return 2;
}
function parseTarget(raw) {
  const value = raw ?? process.env.ADK_TARGET ?? "dev";
  if (value !== "dev" && value !== "prod" && value !== "all") {
    throw new DependencyError({
      code: "MISSING_INPUT",
      message: `Invalid --target value '${value}'. Expected 'dev', 'prod', or 'all'.`
    });
  }
  return value;
}
function expandTarget(target) {
  return target === "all" ? ["dev", "prod"] : [target];
}
function parseFormat(raw) {
  const value = raw ?? "text";
  if (value !== "text" && value !== "json") {
    throw new DependencyError({
      code: "MISSING_INPUT",
      message: `Invalid --format value '${value}'. Expected 'text' or 'json'.`
    });
  }
  return value;
}
function parseKeyValueOptions(values, optionName) {
  const parsed = {};
  for (const kv of values ?? []) {
    const eq = kv.indexOf("=");
    if (eq < 0) {
      throw new DependencyError({ code: "MISSING_INPUT", message: `${optionName} expects key=value, got '${kv}'` });
    }
    const key = kv.slice(0, eq);
    if (!key) {
      throw new DependencyError({ code: "MISSING_INPUT", message: `${optionName} expects a non-empty key` });
    }
    parsed[key] = parseKeyValueValue(kv.slice(eq + 1), optionName);
  }
  return parsed;
}
function parseKeyValueValue(raw, optionName) {
  const value = raw.trim();
  if (value === "true")
    return true;
  if (value === "false")
    return false;
  if (value === "null")
    return null;
  if (/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(value))
    return Number(value);
  const first = value[0];
  if (first === "{" || first === "[" || first === '"') {
    try {
      return JSON.parse(value);
    } catch (err) {
      throw new DependencyError({
        code: "INVALID_CONFIG",
        message: `${optionName} value '${raw}' looks like JSON but could not be parsed: ${err instanceof Error ? err.message : String(err)}`
      });
    }
  }
  return raw;
}
function emitDeprecation(opts) {
  const message = `${opts.oldCommand} is deprecated; use ${opts.newCommand}`;
  if (opts.format === "json") {
    return { warning: { code: "DEPRECATED_COMMAND", message } };
  }
  return { stderrLine: message };
}
var pendingWarnings = [];
function pushPendingWarning(warning) {
  pendingWarnings.push(warning);
}
function drainPendingWarnings() {
  return pendingWarnings.splice(0);
}
async function promptYesNo(question) {
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      rl.close();
      resolve(answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes");
    });
  });
}
async function confirmProdAndRetry(call, runWithYes, logger) {
  try {
    return await call();
  } catch (err) {
    if (!isDependencyErrorLike(err) || err.code !== "PROD_CONFIRMATION_REQUIRED" && err.code !== "UNINSTALL_REQUIRES_CONFIRMATION") {
      throw err;
    }
    if (logger.format === "json" || !process.stderr.isTTY) {
      throw err;
    }
    const planned = err.details?.planned ?? err.details?.destructive ?? [];
    const header = err.code === "PROD_CONFIRMATION_REQUIRED" ? "Apply targets production." : "Apply would uninstall resources from cloud.";
    if (planned.length === 0) {
      logger.warn(header);
    } else {
      logger.warn(`${header} Planned changes:`);
      for (const a of planned) {
        logger.warn(`  ${a.action} ${a.type}:${a.alias}`);
      }
    }
    const confirmed = await promptYesNo("Proceed? [y/N] ");
    if (!confirmed) {
      throw new DependencyError({ code: "MISSING_INPUT", message: "Aborted by user." });
    }
    return runWithYes();
  }
}
async function loadProjectDM(env) {
  const context = await resolveCommandContext({
    target: env,
    require: ["project", "credentials", "workspace", "bot"]
  });
  const { dependencies } = await import("./chunk-fkfymm49.js");
  const dm = await dependencies.DependencyManager.fromProject({
    projectPath: context.project.path,
    env,
    client: context.client
  });
  return { dm, project: context.project, context };
}
async function resolveDependencyRegistryManagerOptions() {
  const context = await resolveEnvironmentRemoteContext();
  return {
    credentials: context.credentials,
    apiUrl: context.apiUrl
  };
}
async function runApplyCommand(options) {
  await runDependencyCommand({
    options,
    run: async (logger) => {
      const format = parseFormat(options.format);
      const target = parseTarget(options.target);
      const envs = expandTarget(target);
      const results = [];
      for (const env of envs) {
        const { dm } = await loadProjectDM(env);
        const applyOpts = { dryRun: options.dryRun, yes: options.yes };
        const result = await confirmProdAndRetry(() => dm.apply(applyOpts), () => dm.apply({ ...applyOpts, yes: true }), logger);
        results.push({ env, ...result });
      }
      if (format === "text") {
        for (const result of results) {
          const prefix = envs.length > 1 ? `[${result.env}] ` : "";
          if (result.dryRun) {
            logger.info(`${prefix}Dry-run plan:`);
            for (const a of result.skipped) {
              logger.info(`  ${a.action} ${a.type}:${a.alias}`);
            }
          } else {
            for (const a of result.applied) {
              logger.info(`${prefix}\u2713 ${a.action} ${a.type}:${a.alias}`, "green");
            }
            for (const e of result.errors) {
              logger.info(`${prefix}\u2717 ${e.action.action} ${e.action.type}:${e.action.alias} \u2014 ${e.code}: ${e.message}`, "red");
              if (e.suggestion) {
                logger.info(`${prefix}  hint: ${e.suggestion}`, "gray");
              }
            }
          }
        }
        const hasErrors = results.some((r) => r.errors.length > 0);
        if (hasErrors) {
          throw new DependencyError({
            code: "INVALID_CONFIG",
            message: `Apply completed with errors`
          });
        }
        return {};
      }
      return { data: { results }, extras: { target } };
    }
  });
}
async function runCopyCommand(options) {
  await runDependencyCommand({
    options,
    run: async (logger) => {
      const format = parseFormat(options.format);
      if (!options.from || !options.to) {
        const { DependencyError: DE } = await import("./chunk-q1scss64.js");
        throw new DE({ code: "MISSING_INPUT", message: "--from and --to are required" });
      }
      const fromParsed = parseTarget(options.from);
      const toParsed = parseTarget(options.to);
      if (fromParsed === "all" || toParsed === "all") {
        const { DependencyError: DE } = await import("./chunk-q1scss64.js");
        throw new DE({
          code: "MISSING_INPUT",
          message: `'all' is not a valid value for --from or --to on copy. Use 'dev' or 'prod'.`
        });
      }
      const from = fromParsed;
      const to = toParsed;
      const { dm } = await loadProjectDM(to);
      const copyOpts = { from, to, dryRun: options.dryRun, yes: options.yes };
      const result = await confirmProdAndRetry(() => dm.copy(copyOpts), () => dm.copy({ ...copyOpts, yes: true }), logger);
      if (format === "text") {
        const verb = result.dryRun ? "Plan" : "Applied";
        logger.info(`${verb} ${from} \u2192 ${to}:`);
        for (const a of result.applied.length ? result.applied : result.skipped) {
          logger.info(`  ${a.action} ${a.type}:${a.alias}`);
        }
        for (const e of result.errors) {
          logger.info(`  \u2717 ${e.action.action} ${e.action.type}:${e.action.alias} \u2014 ${e.code}: ${e.message}`, "red");
        }
        if (result.errors.length > 0) {
          throw new DependencyError({
            code: "INVALID_CONFIG",
            message: `Copy completed with errors`
          });
        }
        return {};
      }
      return { data: { result } };
    }
  });
}
async function runDiffCommand(options) {
  await runDependencyCommand({
    options,
    run: async (logger) => {
      const format = parseFormat(options.format);
      const target = parseTarget(options.target);
      const envs = expandTarget(target);
      const results = [];
      for (const env of envs) {
        const { dm } = await loadProjectDM(env);
        results.push({ env, ...await dm.diff() });
      }
      if (format === "text") {
        for (const result of results) {
          const prefix = envs.length > 1 ? `[${result.env}] ` : "";
          if (result.lockReflectsCloud) {
            logger.info(`${prefix}Lock matches cloud (${result.env}).`);
          } else {
            for (const a of result.delta.addedInLock)
              logger.info(`${prefix}  + ${a.type}:${a.alias}`);
            for (const a of result.delta.removedInLock)
              logger.info(`${prefix}  - ${a.type}:${a.alias}`);
            for (const a of result.delta.changedInLock)
              logger.info(`${prefix}  ~ ${a.type}:${a.alias}`);
          }
        }
        return {};
      }
      return { data: { results }, extras: { target } };
    }
  });
}
async function runSyncCommand(options, typeFilter) {
  await runDependencyCommand({
    options,
    run: async (logger) => {
      const format = parseFormat(options.format);
      const target = parseTarget(options.target);
      const envs = expandTarget(target);
      const results = [];
      for (const env of envs) {
        const { dm } = await loadProjectDM(env);
        results.push({ env, ...await dm.sync({ dryRun: options.dryRun }) });
      }
      if (format === "text") {
        for (const result of results) {
          const filter = typeFilter ? (x) => x.type === typeFilter : () => true;
          const adds = result.added.filter(filter).map((x) => `+${typeFilter ? x.alias : `${x.type}:${x.alias}`}`);
          const rems = result.removed.filter(filter).map((x) => `-${typeFilter ? x.alias : `${x.type}:${x.alias}`}`);
          const upds = result.updated.filter(filter).map((x) => `~${typeFilter ? x.alias : `${x.type}:${x.alias}`}`);
          const summary = [...adds, ...rems, ...upds].join(" ");
          const prefix = envs.length > 1 ? `[${result.env}] ` : "";
          logger.info(summary ? `${prefix}Lock updated: ${summary}` : `${prefix}Lock up to date.`);
        }
        return {};
      }
      return { data: { results }, extras: { target } };
    }
  });
}
async function runDependencyCommand(opts) {
  const format = parseFormat(opts.options.format);
  const logger = createCliLogger({ format });
  try {
    const result = await opts.run(logger);
    if (format === "json") {
      const drained = drainPendingWarnings();
      const body = { ok: true, ...result.extras ?? {} };
      if (result.data !== undefined)
        body.data = result.data;
      const allWarnings = [...result.warnings ?? [], ...drained];
      if (allWarnings.length > 0)
        body.warnings = allWarnings;
      logger.info("").result(body);
    } else if (result.data !== undefined) {
      logger.info(JSON.stringify(result.data, null, 2));
    }
  } catch (err) {
    const code = exitCodeFor(err);
    const json = JSON.parse(formatJsonError(err));
    const drained = drainPendingWarnings();
    if (drained.length > 0)
      json.warnings = drained;
    const wrapped = err instanceof Error ? err : new Error(String(err));
    wrapped.exitCode = code;
    wrapped.json = json;
    if (isDependencyErrorLike(err) && err.suggestion) {
      wrapped.suggestion = err.suggestion;
    }
    throw wrapped;
  }
}

export { formatJsonError, exitCodeFor, parseTarget, parseFormat, parseKeyValueOptions, emitDeprecation, pushPendingWarning, loadProjectDM, resolveDependencyRegistryManagerOptions, runApplyCommand, runCopyCommand, runDiffCommand, runSyncCommand, runDependencyCommand };
