import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as fs from 'fs';
import * as path from 'path';

export interface Skill {
  name: string;
  description: string;
  promptTemplate: string;
  allowedTools?: string[];
  maxRiskLevel?: number;
}

@Injectable()
export class SkillManagerService {
  private readonly logger = new Logger(SkillManagerService.name);
  private skills = new Map<string, Skill>();

  constructor(private readonly configService: ConfigService) {
    this.loadSkills();
  }

  private loadSkills(): void {
    const skillsDir = this.configService.get<string>(
      'SKILLS_DIR',
      path.join(process.cwd(), 'skills'),
    );

    if (!fs.existsSync(skillsDir)) {
      this.logger.warn(`Skills directory not found: ${skillsDir}`);
      return;
    }

    const files = fs.readdirSync(skillsDir).filter((f) => f.endsWith('.md'));

    for (const file of files) {
      try {
        const content = fs.readFileSync(path.join(skillsDir, file), 'utf-8');
        const skill = this.parseSkillFile(content);
        if (skill) {
          this.skills.set(skill.name, skill);
          this.logger.log(`Loaded skill: ${skill.name}`);
        }
      } catch (err: any) {
        this.logger.error(`Failed to load skill from ${file}: ${err.message}`);
      }
    }

    this.logger.log(`Loaded ${this.skills.size} skill(s)`);
  }

  private parseSkillFile(content: string): Skill | null {
    const frontMatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
    if (!frontMatterMatch) return null;

    const frontMatter = frontMatterMatch[1];
    const promptTemplate = frontMatterMatch[2].trim();

    const name = this.extractField(frontMatter, 'name');
    const description = this.extractField(frontMatter, 'description');

    if (!name || !description) return null;

    const allowedToolsRaw = this.extractField(frontMatter, 'allowedTools');
    const allowedTools = allowedToolsRaw
      ? allowedToolsRaw.split(',').map((t) => t.trim())
      : undefined;

    const maxRiskLevelRaw = this.extractField(frontMatter, 'maxRiskLevel');
    const maxRiskLevel = maxRiskLevelRaw ? parseInt(maxRiskLevelRaw, 10) : undefined;

    return { name, description, promptTemplate, allowedTools, maxRiskLevel };
  }

  private extractField(frontMatter: string, field: string): string | undefined {
    const match = frontMatter.match(new RegExp(`^${field}:\\s*(.+)$`, 'm'));
    return match ? match[1].trim() : undefined;
  }

  getSkill(name: string): Skill | undefined {
    return this.skills.get(name);
  }

  listSkills(): Skill[] {
    return Array.from(this.skills.values());
  }

  buildSkillPrompt(skillName: string, context: Record<string, string>): string {
    const skill = this.skills.get(skillName);
    if (!skill) {
      throw new Error(`Skill not found: ${skillName}`);
    }

    let prompt = skill.promptTemplate;
    for (const [key, value] of Object.entries(context)) {
      prompt = prompt.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
    }
    return prompt;
  }
}
