import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
import { parseWorkflowScript } from "./parser.js";
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
import { join } from "node:path";
//#region src/agent/workflow/catalog.ts
/**
* Catalog for named workflows.
*
* Resolution order (built-ins are starting points, user workflows win):
*   1. `~/.xopc/workflows/<name>.js` (or `<name>.workflow.js`)
*   2. {@link BUILTIN_WORKFLOWS}
*
* The user dir is discovered via {@link resolveStateDir}, so `XOPC_STATE_DIR`
* overrides apply automatically (matches how skills / extensions are wired).
*
* Listing is filesystem-cheap (single `readdir`) and runs synchronously — the
* `/workflows` slash command is interactive and should return immediately.
*
* Validation: on load we re-parse the script to make sure `meta.name` matches
* the filename. This prevents copy-pasted scripts from being silently
* mis-addressed when invoked by name.
*/
init_paths_state();
const NAME_RE = /^[a-z][a-z0-9_-]*$/;
function createWorkflowCatalog(opts = {}) {
	const userDir = opts.userDir ?? defaultUserDir();
	const list = () => {
		const entries = /* @__PURE__ */ new Map();
		for (const b of BUILTIN_WORKFLOWS) {
			const meta = safeMeta(b.script);
			entries.set(b.name, {
				name: b.name,
				source: "builtin",
				path: null,
				description: meta?.description ?? "(unparseable)",
				whenToUse: meta?.whenToUse,
				tags: meta?.tags,
				estimatedAgents: meta?.estimatedAgents
			});
		}
		for (const file of safeListUserFiles(userDir)) {
			const name = stripExt(file);
			if (!isValidName(name)) continue;
			const full = join(userDir, file);
			const meta = safeMeta(readScript(full));
			entries.set(name, {
				name,
				source: "user",
				path: full,
				description: meta?.description ?? "(unparseable)",
				whenToUse: meta?.whenToUse,
				tags: meta?.tags,
				estimatedAgents: meta?.estimatedAgents
			});
		}
		return [...entries.values()].sort((a, b) => a.name.localeCompare(b.name));
	};
	const load = (name) => {
		requireValidName(name);
		const userPath = findUserPath(userDir, name);
		if (userPath) {
			const script = readScript(userPath);
			const { meta } = parseWorkflowScript(script);
			ensureMetaNameMatches(meta, name, userPath);
			return {
				name,
				source: "user",
				script,
				meta,
				path: userPath
			};
		}
		const builtin = BUILTIN_WORKFLOWS.find((b) => b.name === name);
		if (builtin) {
			const { meta } = parseWorkflowScript(builtin.script);
			ensureMetaNameMatches(meta, name, "<builtin>");
			return {
				name,
				source: "builtin",
				script: builtin.script,
				meta,
				path: null
			};
		}
		throw new Error(`workflow not found: ${name}. Drop a script at ${join(userDir, `${name}.js`)} or pick one of: ${list().map((e) => e.name).join(", ")}`);
	};
	const save = (name, script) => {
		requireValidName(name);
		const { meta } = parseWorkflowScript(script);
		if (meta.name !== name) throw new Error(`meta.name "${meta.name}" does not match save name "${name}". Adjust one to match the other.`);
		if (!existsSync(userDir)) mkdirSync(userDir, { recursive: true });
		const path = join(userDir, `${name}.js`);
		writeFileSync(path, normalizeNewlines(script), "utf-8");
		return { path };
	};
	const remove = (name) => {
		requireValidName(name);
		const userPath = findUserPath(userDir, name);
		if (!userPath) return false;
		unlinkSync(userPath);
		return true;
	};
	return {
		list,
		load,
		save,
		remove,
		userDir
	};
}
function defaultUserDir() {
	return join(resolveStateDir(), "workflows");
}
function safeListUserFiles(dir) {
	try {
		if (!existsSync(dir)) return [];
		if (!statSync(dir).isDirectory()) return [];
		return readdirSync(dir).filter((f) => /\.(js|workflow\.js)$/i.test(f));
	} catch {
		return [];
	}
}
function findUserPath(dir, name) {
	for (const candidate of [`${name}.js`, `${name}.workflow.js`]) {
		const full = join(dir, candidate);
		if (existsSync(full)) return full;
	}
	return null;
}
function readScript(path) {
	return readFileSync(path, "utf-8");
}
function safeMeta(script) {
	try {
		return parseWorkflowScript(script).meta;
	} catch {
		return null;
	}
}
function stripExt(filename) {
	return filename.replace(/\.workflow\.js$/i, "").replace(/\.js$/i, "");
}
function isValidName(name) {
	return NAME_RE.test(name);
}
function requireValidName(name) {
	if (!isValidName(name)) throw new Error(`invalid workflow name "${name}". Use lowercase snake_case, e.g. "audit_repo".`);
}
function ensureMetaNameMatches(meta, name, locator) {
	if (meta.name !== name) throw new Error(`workflow ${locator}: meta.name "${meta.name}" disagrees with addressable name "${name}". Rename the file or the meta.name to match.`);
}
function normalizeNewlines(s) {
	return s.endsWith("\n") ? s : `${s}\n`;
}
//#endregion
export { createWorkflowCatalog, defaultUserDir };

//# sourceMappingURL=catalog.js.map