i-self 0.4.3

Personal developer-companion CLI: scans your repos, indexes code semantically, watches your activity, and moves AI-agent sessions between tools (Claude Code, Aider, Goose, OpenAI Codex CLI, Continue.dev, OpenCode).
use crate::storage::{Storage, DeveloperProfile};
use anyhow::Result;
use colored::Colorize;

pub struct QueryCommand;

impl QueryCommand {
    pub fn new() -> Self {
        Self
    }

    pub async fn run(&self, query: &str) -> Result<()> {
        let storage = Storage::new()?;
        
        // Load profile and knowledge
        let profile = storage.load_profile().await?;
        let _knowledge = storage.load_knowledge().await?;

        println!("{}", format!("🔍 Query: {}", query).bold().cyan());
        println!();

        // Simple keyword-based matching for now
        let query_lower = query.to_lowercase();

        if query_lower.contains("language") || query_lower.contains("tech") {
            self.show_languages(&profile);
        }

        if query_lower.contains("project") || query_lower.contains("repo") {
            self.show_projects(&profile);
        }

        if query_lower.contains("recent") || query_lower.contains("work") || query_lower.contains("activity") {
            self.show_recent_activity(&profile);
        }

        if query_lower.contains("pattern") || query_lower.contains("style") {
            self.show_patterns(&profile);
        }

        if query_lower.contains("skill") || query_lower.contains("experience") {
            self.show_skills(&profile);
        }

        // If no specific keywords matched, show general summary
        if query_lower == "query" || query_lower.split_whitespace().count() < 2 {
            self.show_general_summary(&profile);
        }

        Ok(())
    }

    fn show_languages(&self, profile: &DeveloperProfile) {
        println!("{}", "💻 Programming Languages".bold().underline());
        
        if profile.github.primary_languages.is_empty() {
            println!("  No language data available yet. Run 'i-self setup' first.");
            return;
        }

        for (lang, percentage) in &profile.github.primary_languages {
            let bar = self.create_bar(*percentage, 20);
            println!("  {:15} {:6.1}% {}", lang, percentage, bar);
        }
        println!();
    }

    fn show_projects(&self, profile: &DeveloperProfile) {
        println!("{}", "📁 Recent Projects".bold().underline());
        
        if profile.github.most_active_repos.is_empty() {
            println!("  No project data available yet. Run 'i-self setup' first.");
            return;
        }

        for repo in &profile.github.most_active_repos {
            let lang = repo.language.as_deref().unwrap_or("Unknown");
            println!("  • {:25} ({}) - {} commits in last 30 days", 
                repo.name.cyan(), 
                lang.dimmed(),
                repo.commits_30d
            );
        }
        println!();
    }

    fn show_recent_activity(&self, profile: &DeveloperProfile) {
        println!("{}", "📊 Recent Activity (30 days)".bold().underline());
        println!("  Total commits: {}", profile.github.total_contributions_30d);
        println!("  Active repositories: {}", profile.github.most_active_repos.len());
        println!("  Recent pull requests: {}", profile.github.recent_prs.len());
        
        if !profile.github.recent_prs.is_empty() {
            println!("\n  Recent PRs:");
            for pr in profile.github.recent_prs.iter().take(5) {
                let state_icon = match pr.state.as_str() {
                    "open" => "🟢",
                    "merged" => "🟣",
                    "closed" => "🔴",
                    _ => "",
                };
                println!("    {} #{}: {}", state_icon, pr.number, pr.title);
            }
        }
        println!();
    }

    fn show_patterns(&self, profile: &DeveloperProfile) {
        println!("{}", "🎨 Coding Patterns".bold().underline());
        
        if profile.coding_patterns.preferred_languages.is_empty() {
            println!("  No pattern data available yet.");
            return;
        }

        println!("  Preferred languages: {}", 
            profile.coding_patterns.preferred_languages.join(", "));
        
        if let Some(style) = &profile.coding_patterns.code_style.indentation {
            println!("  Indentation: {}", style);
        }
        
        if let Some(style) = &profile.coding_patterns.commit_patterns.message_style {
            println!("  Commit style: {}", style);
        }

        println!("  Common libraries:");
        for (lang, libs) in &profile.coding_patterns.common_libraries {
            println!("    {}: {}", lang, libs.join(", "));
        }
        println!();
    }

    fn show_skills(&self, profile: &DeveloperProfile) {
        println!("{}", "🎯 Skills Profile".bold().underline());
        
        if profile.skills.languages.is_empty() {
            println!("  No skills data available yet.");
            return;
        }

        for skill in &profile.skills.languages {
            let level = match skill.proficiency {
                crate::storage::profile::Proficiency::Beginner => "Beginner",
                crate::storage::profile::Proficiency::Intermediate => "Intermediate",
                crate::storage::profile::Proficiency::Advanced => "Advanced",
                crate::storage::profile::Proficiency::Expert => "Expert",
            };
            
            let bar = self.create_bar(skill.proficiency_score * 100.0, 15);
            println!("  {:15} {:12} {} ({} years est.)", 
                skill.name, 
                level.dimmed(),
                bar,
                skill.years_experience
            );
        }
        println!();
    }

    fn show_general_summary(&self, profile: &DeveloperProfile) {
        println!("{}", "👤 Developer Profile Summary".bold().underline());
        
        if let Some(name) = &profile.identity.name {
            println!("  Name: {}", name);
        }
        
        if let Some(github) = &profile.identity.github_username {
            println!("  GitHub: @{}", github.cyan());
        }

        println!("  Repositories: {}", profile.github.total_repositories);
        println!("  Last updated: {}", profile.last_updated.format("%Y-%m-%d %H:%M"));
        
        println!("\nTry asking about:");
        println!("  • 'What languages do I use?'");
        println!("  • 'Show my recent projects'");
        println!("  • 'What are my coding patterns?'");
        println!("  • 'What are my skills?'");
    }

    fn create_bar(&self, percentage: f64, width: usize) -> String {
        let filled = ((percentage / 100.0) * width as f64) as usize;
        let empty = width - filled;
        
        let filled_str = "".repeat(filled);
        let empty_str = "".repeat(empty);
        
        format!("[{}{}]", filled_str.green(), empty_str)
    }
}