use crate::skills::{SkillGapAnalyzer, Skill, SkillLevel, GapAnalysis, get_common_job_profiles};
use anyhow::Result;
use clap::Parser;
#[derive(Parser)]
pub struct SkillsCommand {
#[arg(short, long)]
pub job: Option<String>,
#[arg(short, long)]
pub list_jobs: bool,
#[arg(short, long)]
pub add_skill: Option<String>,
#[arg(short, long)]
pub level: Option<String>,
}
impl SkillsCommand {
pub async fn run(&self) -> Result<()> {
if self.list_jobs {
println!("\n=== Available Job Profiles ===\n");
let jobs = get_common_job_profiles();
for (idx, job) in jobs.iter().enumerate() {
println!("{}. {}", idx + 1, job.title);
println!(" Required skills: {}", job.required_skills
.iter()
.map(|s| s.skill_name.as_str())
.collect::<Vec<_>>()
.join(", "));
println!();
}
return Ok(());
}
let mut analyzer = SkillGapAnalyzer::new();
let skills = load_current_skills()?;
analyzer.load_from_profile(skills);
if let Some(ref job_title) = self.job {
let jobs = get_common_job_profiles();
let job = jobs.iter().find(|j| j.title.to_lowercase().contains(&job_title.to_lowercase()));
if let Some(job) = job {
let analysis = analyzer.analyze_job(job);
print_gap_analysis(&analysis);
} else {
println!("Job profile '{}' not found. Use --list-jobs to see available profiles.", job_title);
}
return Ok(());
}
println!("\n=== Your Skills ===\n");
let summary = analyzer.get_skill_summary();
for (name, skill) in summary {
println!("{}: {} ({} projects)", name, skill.level.label(), skill.projects_count);
}
Ok(())
}
}
fn load_current_skills() -> Result<Vec<Skill>> {
let mut skills = Vec::new();
skills.push(Skill {
name: "Rust".to_string(),
level: SkillLevel::Advanced,
years_experience: Some(3.0),
last_used: Some("2024-01".to_string()),
projects_count: 15,
});
skills.push(Skill {
name: "Python".to_string(),
level: SkillLevel::Advanced,
years_experience: Some(5.0),
last_used: Some("2024-01".to_string()),
projects_count: 25,
});
skills.push(Skill {
name: "JavaScript".to_string(),
level: SkillLevel::Advanced,
years_experience: Some(6.0),
last_used: Some("2024-01".to_string()),
projects_count: 20,
});
skills.push(Skill {
name: "TypeScript".to_string(),
level: SkillLevel::Intermediate,
years_experience: Some(2.0),
last_used: Some("2024-01".to_string()),
projects_count: 8,
});
skills.push(Skill {
name: "Docker".to_string(),
level: SkillLevel::Intermediate,
years_experience: Some(2.0),
last_used: Some("2024-01".to_string()),
projects_count: 10,
});
Ok(skills)
}
fn print_gap_analysis(analysis: &GapAnalysis) {
println!("\n=== Gap Analysis: {} ===\n", analysis.job_title);
println!("Overall Match: {:.1}%\n", analysis.overall_match_percentage);
if !analysis.strengths.is_empty() {
println!("✓ Strengths:");
for skill in &analysis.strengths {
println!(" - {}", skill);
}
println!();
}
if !analysis.gaps.is_empty() {
println!("⚠ Skill Gaps:");
for gap in &analysis.gaps {
let critical = if gap.is_critical { " [CRITICAL]" } else { "" };
println!(" - {}: {} → {}{}",
gap.skill_name,
gap.current_level.label(),
gap.required_level.label(),
critical);
println!(" {}", gap.recommendation);
}
println!();
}
if !analysis.missing_critical_skills.is_empty() {
println!("✗ Missing Critical Skills:");
for skill in &analysis.missing_critical_skills {
println!(" - {}", skill);
}
println!();
}
if !analysis.recommendations.is_empty() {
println!("Recommendations:");
for rec in &analysis.recommendations {
println!(" • {}", rec);
}
}
}