import type { Skill } from './types.js';

/**
 * SkillRegistry holds loaded skills and generates system prompt additions.
 *
 * Skills are keyed by name. Managed/workspace skills may override bundled
 * skills by registering with the same name.
 */
export class SkillRegistry {
  private skills: Map<string, Skill> = new Map();

  /** Replace all registered skills with the provided set. */
  reset(skills: Skill[]): void {
    this.skills.clear();
    for (const skill of skills) {
      this.skills.set(skill.manifest.name, skill);
    }
  }

  /** Register a skill. Replaces any existing skill with the same name. */
  register(skill: Skill): void {
    this.skills.set(skill.manifest.name, skill);
    console.log(
      `Skill '${skill.manifest.name}' registered (${skill.manifest.tier}, ${skill.available ? 'available' : 'unavailable'})`,
    );
  }

  /** Unregister a skill by name. Returns true if the skill existed. */
  unregister(name: string): boolean {
    return this.skills.delete(name);
  }

  /** Look up a skill by name. */
  get(name: string): Skill | undefined {
    return this.skills.get(name);
  }

  /** Return all registered skills. */
  list(): Skill[] {
    return Array.from(this.skills.values());
  }

  /** Return only skills whose requirements are met (available === true). */
  listAvailable(): Skill[] {
    return this.list().filter(skill => skill.available);
  }

  /**
   * Generate system prompt additions from all available skills.
   *
   * Each skill's SKILL.md content is formatted as a markdown section:
   * ```
   * ## Skill: <name>
   * <instructions>
   * ```
   *
   * Returns an empty string if no skills are available.
   */
  getSystemPromptAdditions(): string {
    const available = this.listAvailable();
    if (available.length === 0) {
      return '';
    }

    return available
      .map(skill => `## Skill: ${skill.manifest.name}\n${skill.instructions}`)
      .join('\n\n');
  }

  /** Return the names of all available skills. */
  getSkillNames(): string[] {
    return this.listAvailable().map(skill => skill.manifest.name);
  }
}
