import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
import { ConfigSchema, init_schema } from "../../config/schema.js";
import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
import { formatExamples, register } from "../registry.js";
import { existsSync, readFileSync } from "fs";
import { Command } from "commander";
//#region src/cli/commands/config.ts
init_write_file_atomic();
init_schema();
const MISSING_CONFIG_HINT = "Run: xopc setup, xopc onboard, or xopc init";
async function loadConfigDeps() {
	const [{ loadConfig }, { createLogger }] = await Promise.all([import("../../config/index.js"), import("../../utils/logger.js")]);
	return {
		loadConfig,
		log: createLogger("ConfigCommand")
	};
}
async function runConfigShow(configPath) {
	const { loadConfig, log } = await loadConfigDeps();
	if (!existsSync(configPath)) {
		log.warn(`No config file found. ${MISSING_CONFIG_HINT}`);
		return;
	}
	const config = loadConfig(configPath);
	const maskedConfig = JSON.stringify(config, (key, value) => {
		if (key === "api_key" || key === "token") return value ? "********" : value;
		return value;
	}, 2);
	console.log(maskedConfig);
}
async function runConfigValidate(configPath) {
	const { log } = await loadConfigDeps();
	if (!existsSync(configPath)) {
		log.error("Config file not found. Run: xopc onboard");
		return false;
	}
	let json;
	try {
		json = JSON.parse(readFileSync(configPath, "utf-8"));
	} catch {
		log.error("Config file is not valid JSON.");
		return false;
	}
	const parsed = ConfigSchema.safeParse(json);
	if (!parsed.success) {
		log.error("Config does not match the expected schema.");
		for (const issue of parsed.error.issues) console.error(`  - ${issue.path.join(".") || "(root)"}: ${issue.message}`);
		return false;
	}
	const { validateChannelPluginConfigs } = await import("../../config/validate-channel-configs.js");
	const channelErrors = validateChannelPluginConfigs(parsed.data);
	if (channelErrors.length > 0) {
		log.error("Channel configuration failed validation.");
		for (const err of channelErrors) console.error(`  - ${err}`);
		return false;
	}
	log.info({ path: configPath }, "Config is valid");
	console.log("✅ Configuration is valid");
	return true;
}
function getNestedValue(obj, path) {
	return path.split(".").reduce((current, key) => {
		if (current && typeof current === "object" && key in current) return current[key];
	}, obj);
}
function setNestedValue(obj, path, value) {
	const keys = path.split(".");
	const lastKey = keys.pop();
	const target = keys.reduce((current, key) => {
		if (!current[key] || typeof current[key] !== "object") current[key] = {};
		return current[key];
	}, obj);
	target[lastKey] = value;
	return obj;
}
function createConfigCommand(ctx) {
	const cmd = new Command("config").description("View and edit configuration").option("--show", "Show full configuration (alias for `config show`)").option("--validate", "Validate configuration file (alias for `config validate`)").addHelpText("after", formatExamples([
		"xopc config get agents.defaults.model",
		"xopc config set agents.defaults.temperature 0.8",
		"xopc config unset agents.defaults.max_tokens",
		"xopc config show",
		"xopc config validate",
		"xopc config token              # Show gateway token info",
		"xopc config token --show       # Show full token",
		"xopc config token --generate   # Generate new token"
	])).action(async (options) => {
		if (options.show) {
			await runConfigShow(ctx.configPath);
			return;
		}
		if (options.validate) {
			if (!await runConfigValidate(ctx.configPath)) process.exit(1);
			return;
		}
		cmd.outputHelp();
	});
	cmd.command("get <path>").description("Get a config value by dot path").action(async (path) => {
		const { loadConfig, log } = await loadConfigDeps();
		if (!existsSync(ctx.configPath)) {
			log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
			process.exit(1);
		}
		const value = getNestedValue(loadConfig(ctx.configPath), path);
		if (value === void 0) {
			log.error({ path }, `Config path not found`);
			process.exit(1);
		}
		console.log(typeof value === "object" ? JSON.stringify(value, null, 2) : value);
	});
	cmd.command("set <path> <value>").description("Set a config value by dot path").action(async (path, value) => {
		const { loadConfig, log } = await loadConfigDeps();
		if (!existsSync(ctx.configPath)) {
			log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
			process.exit(1);
		}
		let parsedValue;
		try {
			parsedValue = JSON.parse(value);
		} catch {
			parsedValue = value;
		}
		const config = loadConfig(ctx.configPath);
		setNestedValue(config, path, parsedValue);
		await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));
		log.info({ path }, `Config updated`);
	});
	cmd.command("unset <path>").description("Remove a config value by dot path").action(async (path) => {
		const { loadConfig, log } = await loadConfigDeps();
		if (!existsSync(ctx.configPath)) {
			log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
			process.exit(1);
		}
		const config = loadConfig(ctx.configPath);
		const keys = path.split(".");
		const lastKey = keys.pop();
		const target = keys.reduce((current, key) => {
			return current && current[key];
		}, config);
		if (target && typeof target === "object" && lastKey in target) {
			delete target[lastKey];
			await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));
			log.info({ path }, `Config removed`);
		} else {
			log.error({ path }, `Config path not found`);
			process.exit(1);
		}
	});
	cmd.command("show").description("Show full configuration (sensitive values masked)").action(async () => {
		await runConfigShow(ctx.configPath);
	});
	cmd.command("validate").description("Validate configuration file against schema and channel plugins").action(async () => {
		if (!await runConfigValidate(ctx.configPath)) process.exit(1);
	});
	cmd.command("token").description("Generate or view the gateway auth token").option("--generate", "Generate a new token").option("--show", "Show the current token (unmasked)").action(async (options) => {
		const { loadConfig, log } = await loadConfigDeps();
		if (!existsSync(ctx.configPath)) {
			log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
			process.exit(1);
		}
		const config = loadConfig(ctx.configPath);
		if (options.show) {
			const token = config?.gateway?.auth?.token;
			if (token) console.log(token);
			else console.log("No token configured. Gateway auth mode:", config?.gateway?.auth?.mode || "not set");
			return;
		}
		if (options.generate) {
			const newToken = (await import("crypto")).randomBytes(24).toString("hex");
			config.gateway = config.gateway || {};
			config.gateway.auth = {
				mode: "token",
				token: newToken
			};
			await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));
			log.info("New gateway token generated");
			console.log(`Token: ${newToken.slice(0, 8)}...${newToken.slice(-8)}`);
			console.log("\nUse \"xopc config token --show\" to view the full token");
			return;
		}
		const token = config?.gateway?.auth?.token;
		const mode = config?.gateway?.auth?.mode;
		const bind = config?.gateway?.bind ?? "loopback";
		const port = config?.gateway?.port || 18790;
		const clientHost = config ? resolveGatewayLocalClientHost(config) : "127.0.0.1";
		console.log("Gateway Configuration:");
		console.log(`  Bind: ${bind}`);
		console.log(`  Local URL: http://${clientHost}:${port}`);
		console.log(`  Auth Mode: ${mode || "not set"}`);
		if (token) {
			console.log(`  Token: ${token.slice(0, 8)}...${token.slice(-8)}`);
			console.log("\nUse \"xopc config token --show\" to view the full token");
			console.log("Use \"xopc config token --generate\" to generate a new token");
		} else if (mode === "token") console.log("  Token: not set (will be auto-generated on first `xopc gateway` run)");
	});
	cmd.command("path").description("Show configuration file path").action(() => {
		console.log(ctx.configPath);
	});
	return cmd;
}
register({
	id: "config",
	name: "config",
	description: "View and edit configuration",
	factory: createConfigCommand,
	metadata: {
		category: "utility",
		examples: [
			"xopc config get agents.defaults.model",
			"xopc config set agents.defaults.temperature 0.8",
			"xopc config show",
			"xopc config validate",
			"xopc config token",
			"xopc config token --show",
			"xopc config token --generate"
		]
	}
});
//#endregion
export {};

//# sourceMappingURL=config.js.map