import { resolveStateDir } from "../../config/paths-state.js";
import { init_paths, resolveBundledSkillsDir, resolveSkillsLockPath } from "../../config/paths.js";
import { findInstallSpec, getDefaultInstallerPreferences, hasBinary, installSkill } from "../../agent/skills/installer.js";
import { createSkillConfigManager, isSkillEnabled } from "../../agent/skills/config.js";
import { formatScanSummary, scanSkillDirectory } from "../../agent/skills/scanner.js";
import { loadSkillsLock } from "../../agent/skills/hub-lock.js";
import { createSkillLoader } from "../../agent/skills/index.js";
import { register } from "../registry.js";
import { pullSkillFromSource, updateSkillFromLock } from "../../agent/skills/hub-pull.js";
import { createSkillsTestCommand } from "./skills-test.js";
import { Command } from "commander";
//#region src/cli/commands/skills.ts
/**
* Skills CLI Command
* 
* Manage skills: list, install, enable/disable, configure, test
*/
init_paths();
function loadWorkspaceSkillEntries(workspaceDir) {
	const loader = createSkillLoader();
	loader.init(workspaceDir, resolveBundledSkillsDir());
	return loader.load().skills.map((skill) => ({
		skill,
		metadata: skill.metadata,
		enabled: true
	}));
}
function createSkillsCommand(ctx) {
	const command = new Command("skills");
	command.description("Manage skills");
	command.command("list").description("List available skills").option("-v, --verbose", "Show detailed information").option("--json", "Output as JSON").action(async (options) => {
		const loader = createSkillLoader();
		const workspaceDir = ctx.workspacePath;
		loader.init(workspaceDir, resolveBundledSkillsDir());
		const result = loader.load();
		if (options.json) {
			console.log(JSON.stringify({
				skills: result.skills.map((s) => ({
					name: s.name,
					description: s.description,
					source: s.source,
					path: s.filePath,
					enabled: true,
					metadata: s.metadata
				})),
				diagnostics: result.diagnostics
			}, null, 2));
			return;
		}
		console.log(`\nFound ${result.skills.length} skill(s):\n`);
		for (const skill of result.skills) {
			const emoji = skill.metadata.xopc?.emoji || "📦";
			const source = `[${skill.source}]`;
			console.log(`${emoji} ${skill.name} ${source}`);
			console.log(`   ${skill.description}`);
			if (options.verbose) {
				console.log(`   Path: ${skill.filePath}`);
				const requires = skill.metadata.xopc?.requires;
				if (requires?.bins) {
					const binsStatus = requires.bins.map((bin) => {
						return `${bin} ${hasBinary(bin) ? "✓" : "✗"}`;
					}).join(", ");
					console.log(`   Requires: ${binsStatus}`);
				}
				const install = skill.metadata.xopc?.install;
				if (install && install.length > 0) console.log(`   Install options: ${install.map((i) => i.label || i.kind).join(", ")}`);
				console.log();
			}
		}
		if (result.diagnostics.length > 0) {
			console.log("\nDiagnostics:");
			for (const diag of result.diagnostics) {
				const icon = diag.type === "error" ? "❌" : diag.type === "warning" ? "⚠️" : "ℹ️";
				console.log(`${icon} ${diag.message}`);
			}
		}
		console.log();
	});
	command.command("install <skill-name>").description("Install a skill dependency").option("-i, --id <install-id>", "Install spec ID to use").option("--timeout <ms>", "Installation timeout in ms", "300000").option("--dry-run", "Show what would be installed without executing").action(async (skillName, options) => {
		const workspaceDir = ctx.workspacePath;
		const entry = loadWorkspaceSkillEntries(workspaceDir).find((e) => e.skill.name === skillName);
		if (!entry) {
			console.error(`Error: Skill "${skillName}" not found in workspace`);
			console.log("\nAvailable skills:");
			const result = createSkillLoader().load();
			for (const skill of result.skills) console.log(`  - ${skill.name}`);
			process.exit(1);
		}
		const installSpecs = entry.metadata.xopc?.install || entry.metadata.install || [];
		if (installSpecs.length === 0) {
			console.log(`Skill "${skillName}" has no install specs`);
			process.exit(0);
		}
		let installSpec = options.id ? findInstallSpec(entry, options.id) : installSpecs[0];
		if (!installSpec) {
			console.error(`Error: Install spec "${options.id}" not found`);
			console.log("\nAvailable install specs:");
			for (const [index, spec] of installSpecs.entries()) {
				const id = spec.id || `${spec.kind}-${index}`;
				const label = spec.label || id;
				console.log(`  ${id}: ${label}`);
			}
			process.exit(1);
		}
		if (options.dryRun) {
			console.log("Dry run - would install:");
			console.log(`  Skill: ${skillName}`);
			console.log(`  Method: ${installSpec.kind}`);
			if (installSpec.package) console.log(`  Package: ${installSpec.package}`);
			if (installSpec.formula) console.log(`  Formula: ${installSpec.formula}`);
			if (installSpec.module) console.log(`  Module: ${installSpec.module}`);
			if (installSpec.bins) console.log(`  Expected binaries: ${installSpec.bins.join(", ")}`);
			return;
		}
		console.log(`Installing dependency for "${skillName}"...`);
		const result = await installSkill({
			workspaceDir,
			skillEntry: entry,
			installSpec,
			timeoutMs: parseInt(options.timeout, 10),
			preferences: getDefaultInstallerPreferences()
		});
		if (result.ok) {
			console.log("✓ Installation successful");
			if (result.stdout) console.log(result.stdout);
		} else {
			console.error("✗ Installation failed");
			console.error(result.message);
			if (result.stderr) console.error(result.stderr);
			process.exit(1);
		}
		if (result.warnings && result.warnings.length > 0) {
			console.log("\nWarnings:");
			for (const warning of result.warnings) console.log(`  ⚠️  ${warning}`);
		}
	});
	command.command("enable <skill-name>").description("Enable a skill").action(async (skillName) => {
		createSkillConfigManager(resolveStateDir()).setSkillEnabled(skillName, true);
		console.log(`✓ Skill "${skillName}" enabled`);
	});
	command.command("disable <skill-name>").description("Disable a skill").action(async (skillName) => {
		createSkillConfigManager(resolveStateDir()).setSkillEnabled(skillName, false);
		console.log(`✓ Skill "${skillName}" disabled`);
	});
	command.command("status [skill-name]").description("Show skill status").option("--json", "Output as JSON").action(async (skillName, options) => {
		const loader = createSkillLoader();
		const workspaceDir = ctx.workspacePath;
		loader.init(workspaceDir, resolveBundledSkillsDir());
		const result = loader.load();
		const config = createSkillConfigManager(resolveStateDir()).load();
		if (skillName) {
			const skill = result.skills.find((s) => s.name === skillName);
			if (!skill) {
				console.error(`Error: Skill "${skillName}" not found`);
				process.exit(1);
			}
			const skillConfig = config.entries?.[skillName];
			const enabled = isSkillEnabled(skill, config);
			if (options.json) {
				console.log(JSON.stringify({
					name: skill.name,
					enabled,
					config: skillConfig,
					metadata: skill.metadata,
					path: skill.filePath
				}, null, 2));
				return;
			}
			const emoji = skill.metadata.xopc?.emoji || skill.metadata.emoji || "📦";
			console.log(`\n${emoji} ${skill.name}`);
			console.log(`   Description: ${skill.description}`);
			console.log(`   Enabled: ${enabled ? "✓" : "✗"}`);
			console.log(`   Source: ${skill.source}`);
			console.log(`   Path: ${skill.filePath}`);
			if (skillConfig?.apiKey) console.log(`   API Key: ${skillConfig.apiKey.slice(0, 8)}...`);
			const requires = skill.metadata.xopc?.requires;
			if (requires) {
				if (requires.bins) {
					console.log(`   Required binaries: ${requires.bins.join(", ")}`);
					for (const bin of requires.bins) {
						const available = hasBinary(bin);
						console.log(`     ${bin}: ${available ? "✓" : "✗"}`);
					}
				}
				if (requires.anyBins) {
					console.log(`   Any of: ${requires.anyBins.join(", ")}`);
					const hasAny = requires.anyBins.some((bin) => hasBinary(bin));
					console.log(`     Status: ${hasAny ? "✓" : "✗"}`);
				}
			}
			console.log();
		} else {
			const skillsStatus = result.skills.map((skill) => ({
				name: skill.name,
				enabled: isSkillEnabled(skill, config),
				source: skill.source
			}));
			if (options.json) {
				console.log(JSON.stringify({
					total: skillsStatus.length,
					enabled: skillsStatus.filter((s) => s.enabled).length,
					skills: skillsStatus
				}, null, 2));
				return;
			}
			const enabledCount = skillsStatus.filter((s) => s.enabled).length;
			console.log(`\nSkills: ${enabledCount}/${skillsStatus.length} enabled\n`);
			for (const status of skillsStatus) {
				const icon = status.enabled ? "✓" : "✗";
				console.log(`${icon} ${status.name} [${status.source}]`);
			}
			console.log();
		}
	});
	command.command("audit [skill-name]").description("Security audit for skills").option("--deep", "Show detailed findings").action(async (skillName, options) => {
		const loader = createSkillLoader();
		const workspaceDir = ctx.workspacePath;
		loader.init(workspaceDir, resolveBundledSkillsDir());
		const result = loader.load();
		async function auditSkill(skill) {
			const summary = await scanSkillDirectory(skill.baseDir);
			console.log(`\n${formatScanSummary(summary, skill.name)}\n`);
			if (options.deep && summary.findings.length > 0) {
				console.log("Detailed findings:");
				for (const finding of summary.findings) {
					const icon = finding.severity === "critical" ? "❌" : finding.severity === "warning" ? "⚠️" : "ℹ️";
					console.log(`  ${icon} ${finding.message}`);
					console.log(`     File: ${finding.file}:${finding.line}`);
					if (finding.pattern) console.log(`     Pattern: ${finding.pattern}`);
				}
				console.log();
			}
		}
		if (skillName) {
			const skill = result.skills.find((s) => s.name === skillName);
			if (!skill) {
				console.error(`Error: Skill "${skillName}" not found`);
				process.exit(1);
			}
			await auditSkill(skill);
		} else {
			console.log("Auditing all skills...\n");
			for (const skill of result.skills) await auditSkill(skill);
		}
	});
	command.command("config <skill-name>").description("Configure a skill").option("--api-key <key>", "Set API key").option("--env <KEY=VALUE>", "Set environment variable", (val, prev = []) => [...prev, val], []).option("--show", "Show current configuration").action(async (skillName, options) => {
		const configManager = createSkillConfigManager(resolveStateDir());
		if (options.show) {
			const config = configManager.getSkillConfig(skillName);
			if (config) console.log(JSON.stringify(config, null, 2));
			else console.log(`No configuration for skill "${skillName}"`);
			return;
		}
		const updates = {};
		if (options.apiKey) updates.apiKey = options.apiKey;
		if (options.env && options.env.length > 0) {
			const env = {};
			for (const entry of options.env) {
				const [key, ...valueParts] = entry.split("=");
				if (key && valueParts.length > 0) env[key] = valueParts.join("=");
			}
			if (Object.keys(env).length > 0) updates.env = env;
		}
		if (Object.keys(updates).length === 0) {
			console.log("No configuration changes specified. Use --api-key, --env, or --show.");
			return;
		}
		configManager.updateSkillConfig(skillName, updates);
		console.log(`✓ Updated configuration for skill "${skillName}"`);
	});
	const hub = new Command("hub").description("Install or update skills from git or archives (writes ~/.xopc/skills + skills-lock.json)");
	hub.command("pull").argument("<source>", "Git URL, https(s) .zip/.tar.gz, file:// URL, or local archive path").option("--ref <ref>", "Git branch or tag (optional)").option("--path <dir>", "Subdirectory inside the cloned repo containing SKILL.md").option("--id <skillId>", "Target folder name under ~/.xopc/skills (default: SKILL.md name or repo folder)").option("--force", "Replace existing managed skill directory", false).option("--strict-scan", "Fail install if security scanner reports critical findings", false).action(async (source, opts) => {
		try {
			const result = await pullSkillFromSource(source, {
				ref: opts.ref,
				subpath: opts.path,
				skillId: opts.id,
				force: Boolean(opts.force),
				strictScan: Boolean(opts.strictScan)
			});
			console.log(`\n✓ Installed skill "${result.skillId}"`);
			console.log(`  Path: ${result.path}`);
			console.log(`  Source: ${result.source} (${result.kind})`);
			console.log(`  Tree hash: ${result.contentHash.slice(0, 16)}…\n`);
		} catch (e) {
			console.error(e instanceof Error ? e.message : String(e));
			process.exit(1);
		}
	});
	hub.command("update").argument("<skillId>", "Managed skill id (folder name under ~/.xopc/skills)").option("--strict-scan", "Fail if security scanner reports critical findings", false).action(async (skillId, opts) => {
		try {
			const result = await updateSkillFromLock(skillId, { strictScan: Boolean(opts.strictScan) });
			console.log(`\n✓ Updated skill "${result.skillId}"`);
			console.log(`  Path: ${result.path}`);
			console.log(`  Source: ${result.source} (${result.kind})`);
			console.log(`  Tree hash: ${result.contentHash.slice(0, 16)}…\n`);
		} catch (e) {
			console.error(e instanceof Error ? e.message : String(e));
			process.exit(1);
		}
	});
	hub.command("lock").description("Show skills-lock.json (install sources + content hashes)").option("--json", "Print raw JSON", false).action((opts) => {
		const lock = loadSkillsLock();
		if (opts.json) {
			console.log(JSON.stringify(lock, null, 2));
			return;
		}
		const entries = Object.entries(lock.entries);
		console.log(`\n${resolveSkillsLockPath()}`);
		if (entries.length === 0) {
			console.log("(no hub-installed skills)\n");
			return;
		}
		for (const [id, e] of entries.sort((a, b) => a[0].localeCompare(b[0]))) {
			console.log(`\n• ${id}`);
			console.log(`  kind: ${e.kind}`);
			console.log(`  source: ${e.source}`);
			if (e.ref) console.log(`  ref: ${e.ref}`);
			if (e.subpath) console.log(`  subpath: ${e.subpath}`);
			console.log(`  contentHash: ${e.contentHash.slice(0, 16)}…`);
			console.log(`  updatedAt: ${e.updatedAt}`);
		}
		console.log();
	});
	command.addCommand(hub);
	const testCommand = createSkillsTestCommand(ctx);
	command.addCommand(testCommand);
	return command;
}
register({
	id: "skills",
	name: "skills",
	description: "Manage skills (install, enable, configure, test)",
	factory: createSkillsCommand,
	metadata: {
		category: "utility",
		examples: [
			"xopc skills hub pull https://github.com/org/repo.git   # Shallow-clone skill into ~/.xopc/skills",
			"xopc skills hub pull ./pack.zip --force               # Install or replace from local zip",
			"xopc skills hub update my-skill                       # Re-fetch using skills-lock.json",
			"xopc skills hub lock --json                           # Show hub lock file",
			"xopc skills list                        # List all available skills",
			"xopc skills list -v                     # List with detailed information",
			"xopc skills install weather             # Install weather skill dependencies",
			"xopc skills enable weather              # Enable a skill",
			"xopc skills disable weather             # Disable a skill",
			"xopc skills status                      # Show skill status summary",
			"xopc skills status weather              # Show detailed skill status",
			"xopc skills audit                       # Security audit all skills",
			"xopc skills audit weather --deep        # Detailed security audit",
			"xopc skills config weather --show       # Show skill configuration",
			"xopc skills config weather --api-key=KEY  # Set API key",
			"xopc skills test                        # Test all skills",
			"xopc skills test weather                # Test specific skill",
			"xopc skills test validate ./skills/weather/SKILL.md  # Validate SKILL.md file",
			"xopc skills test check-deps             # Check dependencies",
			"xopc skills test security --deep        # Security audit"
		]
	}
});
//#endregion
export { createSkillsCommand };

//# sourceMappingURL=skills.js.map