/**
 * Skill loader
 *
 * Purpose: load skills from `.agents/skills/` with frontmatter validation,
 * permission checking, and lazy content loading.
 *
 * Consumer: command handlers, auto-dispatch, and model context assembly.
 */
import { discoverAllSkills, readSkillFile } from "./directory.js";
import {
	buildSkillRecord,
	parseSkillFrontmatter,
	validateSkillFrontmatter,
} from "./frontmatter.js";

/**
 * Load all valid skills from all sources.
 *
 * Returns array of skill records with validation errors attached.
 */
export function loadSkills(projectPath, options = {}) {
	const discovered = discoverAllSkills(projectPath, options);
	const skills = [];

	for (const { name, path, source } of discovered) {
		const content = readSkillFile(path);
		if (!content) {
			skills.push({
				name,
				source,
				path,
				valid: false,
				errors: ["Could not read SKILL.md"],
			});
			continue;
		}

		const parsed = parseSkillFrontmatter(content);
		if (!parsed) {
			skills.push({
				name,
				source,
				path,
				valid: false,
				errors: ["No YAML frontmatter found"],
			});
			continue;
		}

		const validation =
			source === "bundled" || source === "workflow"
				? validateBundledSkillFrontmatter(parsed.frontmatter)
				: validateSkillFrontmatter(parsed.frontmatter);
		if (!validation.valid) {
			skills.push({
				name,
				source,
				path,
				valid: false,
				errors: validation.errors,
				frontmatter: parsed.frontmatter,
			});
			continue;
		}

		const record = buildSkillRecord(path, parsed.frontmatter, parsed.body);
		if (source === "bundled") {
			record.userInvocable = isUserVisibleBundledSkill(record.name);
		}
		if (source === "workflow") {
			record.userInvocable = false;
			record.locked = false;
		}
		skills.push({
			...record,
			source,
			valid: true,
			errors: [],
		});
	}

	return skills;
}

function validateBundledSkillFrontmatter(frontmatter) {
	const errors = [];
	if (!frontmatter.name || typeof frontmatter.name !== "string") {
		errors.push("Missing or invalid 'name' field");
	}
	if (!frontmatter.description || typeof frontmatter.description !== "string") {
		errors.push("Missing or invalid 'description' field");
	}
	return {
		valid: errors.length === 0,
		errors,
	};
}

function isUserVisibleBundledSkill(name) {
	return name === "create-skill";
}

/**
 * Get skills that are safe for the current permission profile.
 */
export function getPermittedSkills(skills, activeProfile) {
	const profileOrder = ["restricted", "normal", "trusted", "unrestricted"];
	const activeIndex = profileOrder.indexOf(activeProfile);
	if (activeIndex === -1) return [];

	return skills.filter((s) => {
		if (!s.valid) return false;
		const skillIndex = profileOrder.indexOf(s.permissionProfile);
		if (skillIndex === -1) return false;
		return skillIndex <= activeIndex;
	});
}

/**
 * Get SF runtime skills that should appear in the user-facing /skills catalog.
 *
 * Purpose: only show skills the user can actually invoke. Locked skills,
 * workflow-internal skills, and non-invocable bundled skills are all hidden —
 * they exist for the runtime, not the user.
 *
 * Consumer: /skills list mode in the SF command surface.
 */
export function getUserInvocableSkills(skills) {
	return skills.filter(
		(s) =>
			s.valid &&
			s.userInvocable &&
			!s.locked &&
			s.source !== "workflow" &&
			(s.source !== "bundled" || isUserVisibleBundledSkill(s.name)),
	);
}

/**
 * Get skills that can be invoked by the model for a given work mode.
 */
export function getModelInvocableSkills(skills, workMode) {
	return skills.filter(
		(s) => s.valid && s.modelInvocable && isSkillRelevant(s, workMode),
	);
}

/**
 * Check if a skill is relevant to the current work mode.
 */
function isSkillRelevant(skill, workMode) {
	if (!skill.triggers || skill.triggers.length === 0) return true;
	return skill.triggers.some(
		(t) =>
			t === workMode ||
			t === "*" ||
			(workMode === "build" && t === "code") ||
			(workMode === "verify" && t === "review") ||
			(workMode === "document" && t === "docs"),
	);
}
