use anyhow::{bail, Context, Result};
use clap::{Parser, Subcommand};
use colored::Colorize;
use dialoguer::{Confirm, Input, Select, Password};
use std::path::PathBuf;

use crate::config::{Language, manager::ConfigManager, ExportData, EncryptedPat};
use crate::config::CommitFormat;
use crate::utils::keyring::{get_supported_providers, get_default_model, get_default_base_url, provider_needs_api_key};
use crate::utils::crypto::{encrypt, decrypt};

/// Mask API key with asterisks for security
fn mask_api_key(key: Option<&str>) -> String {
    match key {
        Some(k) => {
            if k.len() <= 8 {
                "*".repeat(k.len())
            } else {
                format!("{}***{}", &k[..4], &k[k.len()-4..])
            }
        }
        None => "✗ not set".red().to_string(),
    }
}

/// Manage configuration settings
#[derive(Parser)]
pub struct ConfigCommand {
    #[command(subcommand)]
    command: Option<ConfigSubcommand>,
}

#[derive(Subcommand)]
enum ConfigSubcommand {
    /// Show current configuration
    Show,
    
    /// List all configuration information (with masked API keys)
    List,
    
    /// Edit configuration file
    Edit,
    
    /// Set configuration value
    Set {
        /// Key (e.g., llm.provider, commit.format)
        key: String,
        /// Value
        value: String,
    },
    
    /// Get configuration value
    Get {
        /// Key
        key: String,
    },
    
    /// Configure LLM provider (interactive)
    SetLlm {
        /// Provider (ollama, openai, anthropic, kimi, deepseek, openrouter)
        #[arg(value_name = "PROVIDER")]
        provider: Option<String>,
        
        /// Model name
        #[arg(short, long)]
        model: Option<String>,
        
        /// API base URL (optional)
        #[arg(short, long)]
        base_url: Option<String>,
        
        /// API key (will be stored in system keyring)
        #[arg(short = 'k', long)]
        api_key: Option<String>,
    },
    
    /// Set API key for current provider (stored in system keyring)
    SetApiKey {
        /// API key
        key: String,
    },
    
    /// Delete API key from system keyring
    DeleteApiKey,
    
    /// Set commit format
    SetCommitFormat {
        /// Format (conventional, commitlint)
        format: String,
    },
    
    /// Set version prefix for tags
    SetVersionPrefix {
        /// Prefix (e.g., 'v')
        prefix: String,
    },
    
    /// Set changelog path
    SetChangelogPath {
        /// Path
        path: String,
    },

    /// Set output language
    SetLanguage {
        /// Language code (en, zh, ja, ko, es, fr, de)
        language: Option<String>,
    },

    /// Set whether to keep commit types in English
    SetKeepTypesEnglish {
        /// Keep types in English (true/false)
        keep: bool,
    },

    /// Set whether to keep changelog types in English
    SetKeepChangelogTypesEnglish {
        /// Keep types in English (true/false)
        keep: bool,
    },

    /// Reset configuration to defaults
    Reset {
        /// Skip confirmation
        #[arg(short, long)]
        force: bool,
    },
    
    /// Export configuration
    Export {
        /// Output file (defaults to stdout)
        #[arg(short, long)]
        output: Option<String>,
        
        /// Password for encryption (will prompt if not provided)
        #[arg(short = 'p', long)]
        password: Option<String>,
    },
    
    /// Import configuration
    Import {
        /// Input file
        #[arg(short, long)]
        file: String,
        
        /// Password for decryption (will prompt if file is encrypted)
        #[arg(short = 'p', long)]
        password: Option<String>,
    },
    
    /// List available LLM models
    ListModels,
    
    /// Test LLM connection
    TestLlm,
    
    /// Show config file path
    Path,
    
    /// Check keyring availability
    CheckKeyring,
}

impl ConfigCommand {
    pub async fn execute(&self, config_path: Option<PathBuf>) -> Result<()> {
        match &self.command {
            Some(ConfigSubcommand::Show) => self.show_config(&config_path).await,
            Some(ConfigSubcommand::List) => self.list_config(&config_path).await,
            Some(ConfigSubcommand::Edit) => self.edit_config(&config_path).await,
            Some(ConfigSubcommand::Set { key, value }) => self.set_value(key, value, &config_path).await,
            Some(ConfigSubcommand::Get { key }) => self.get_value(key, &config_path).await,
            Some(ConfigSubcommand::SetLlm { provider, model, base_url, api_key }) => {
                self.set_llm(provider.as_deref(), model.as_deref(), base_url.as_deref(), api_key.as_deref(), &config_path).await
            }
            Some(ConfigSubcommand::SetApiKey { key }) => self.set_api_key(key, &config_path).await,
            Some(ConfigSubcommand::DeleteApiKey) => self.delete_api_key(&config_path).await,
            Some(ConfigSubcommand::SetCommitFormat { format }) => self.set_commit_format(format, &config_path).await,
            Some(ConfigSubcommand::SetVersionPrefix { prefix }) => self.set_version_prefix(prefix, &config_path).await,
            Some(ConfigSubcommand::SetChangelogPath { path }) => self.set_changelog_path(path, &config_path).await,
            Some(ConfigSubcommand::SetLanguage { language }) => self.set_language(language.as_deref(), &config_path).await,
            Some(ConfigSubcommand::SetKeepTypesEnglish { keep }) => self.set_keep_types_english(*keep, &config_path).await,
            Some(ConfigSubcommand::SetKeepChangelogTypesEnglish { keep }) => self.set_keep_changelog_types_english(*keep, &config_path).await,
            Some(ConfigSubcommand::Reset { force }) => self.reset(*force, &config_path).await,
            Some(ConfigSubcommand::Export { output, password }) => self.export_config(output.as_deref(), password.as_deref(), &config_path).await,
            Some(ConfigSubcommand::Import { file, password }) => self.import_config(file, password.as_deref(), &config_path).await,
            Some(ConfigSubcommand::ListModels) => self.list_models(&config_path).await,
            Some(ConfigSubcommand::TestLlm) => self.test_llm(&config_path).await,
            Some(ConfigSubcommand::Path) => self.show_path(&config_path).await,
            Some(ConfigSubcommand::CheckKeyring) => self.check_keyring(&config_path).await,
            None => self.show_config(&config_path).await,
        }
    }

    fn get_manager(&self, config_path: &Option<PathBuf>) -> Result<ConfigManager> {
        match config_path {
            Some(path) => ConfigManager::with_path(path),
            None => ConfigManager::new(),
        }
    }

    async fn show_path(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        println!("{}", manager.path().display());
        Ok(())
    }

    async fn check_keyring(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let keyring = manager.keyring();
        
        println!("{}", "\nKeyring Status".bold());
        println!("{}", "─".repeat(40));
        
        if keyring.is_available() {
            println!("{} Keyring is available", "✓".green());
            println!("  {}", keyring.get_status_message());
        } else {
            println!("{} Keyring is not available", "✗".red());
            println!("  {}", keyring.get_status_message());
        }
        
        println!("\n{}", "Environment Variables:".bold());
        if let Ok(key) = std::env::var("QUICOMMIT_API_KEY") {
            println!("  QUICOMMIT_API_KEY: {}", mask_api_key(Some(&key)));
        } else {
            println!("  QUICOMMIT_API_KEY: {}", "not set".dimmed());
        }
        
        let provider = manager.llm_provider();
        let provider_env = format!("QUICOMMIT_{}_API_KEY", provider.to_uppercase());
        if let Ok(key) = std::env::var(&provider_env) {
            println!("  {}: {}", provider_env, mask_api_key(Some(&key)));
        } else {
            println!("  {}: {}", provider_env, "not set".dimmed());
        }
        
        Ok(())
    }

    async fn show_config(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let config = manager.config();

        println!("{}", "\nQuiCommit Configuration".bold());
        println!("{}", "─".repeat(60));
        
        println!("\n{}", "General:".bold());
        println!("  Config file: {}", manager.path().display());
        println!("  Default profile: {}", 
            config.default_profile.as_deref().unwrap_or("(none)").cyan());
        println!("  Profiles: {}", config.profiles.len());
        
        println!("\n{}", "LLM Configuration:".bold());
        println!("  Provider: {}", config.llm.provider.cyan());
        println!("  Model: {}", config.llm.model.cyan());
        
        let base_url = manager.llm_base_url();
        println!("  Base URL: {}", base_url);
        
        let api_key = manager.get_api_key();
        println!("  API key: {}", mask_api_key(api_key.as_deref()));
        
        println!("  Max tokens: {}", config.llm.max_tokens);
        println!("  Temperature: {}", config.llm.temperature);
        println!("  Timeout: {}s", config.llm.timeout);
        
        println!("\n{}", "Commit Configuration:".bold());
        println!("  Format: {}", config.commit.format.to_string().cyan());
        println!("  Auto-generate: {}", if config.commit.auto_generate { "yes".green() } else { "no".red() });
        println!("  GPG sign: {}", if config.commit.gpg_sign { "yes".green() } else { "no".red() });
        println!("  Max subject length: {}", config.commit.max_subject_length);
        
        println!("\n{}", "Tag Configuration:".bold());
        println!("  Version prefix: '{}'", config.tag.version_prefix);
        println!("  Auto-generate: {}", if config.tag.auto_generate { "yes".green() } else { "no".red() });
        println!("  GPG sign: {}", if config.tag.gpg_sign { "yes".green() } else { "no".red() });
        println!("  Include changelog: {}", if config.tag.include_changelog { "yes".green() } else { "no".red() });
        
        println!("\n{}", "Language Configuration:".bold());
        let language = manager.get_language().unwrap_or(Language::English);
        println!("  Output language: {}", language.display_name().cyan());
        println!("  Keep commit types in English: {}", if manager.keep_types_english() { "yes".green() } else { "no".red() });
        println!("  Keep changelog types in English: {}", if manager.keep_changelog_types_english() { "yes".green() } else { "no".red() });
        
        println!("\n{}", "Changelog Configuration:".bold());
        println!("  Path: {}", config.changelog.path);
        println!("  Auto-generate: {}", if config.changelog.auto_generate { "yes".green() } else { "no".red() });
        println!("  Include hashes: {}", if config.changelog.include_hashes { "yes".green() } else { "no".red() });
        println!("  Include authors: {}", if config.changelog.include_authors { "yes".green() } else { "no".red() });
        println!("  Group by type: {}", if config.changelog.group_by_type { "yes".green() } else { "no".red() });

        Ok(())
    }

    async fn list_config(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let config = manager.config();

        println!("{}", "\nQuiCommit Configuration".bold());
        println!("{}", "═".repeat(80));
        
        println!("\n{}", "📁 General Configuration:".bold().blue());
        println!("  Config file: {}", manager.path().display());
        println!("  Default profile: {}", 
            config.default_profile.as_deref().unwrap_or("(none)").cyan());
        println!("  Profiles: {} profile(s)", config.profiles.len());
        println!("  Repository mappings: {} mapping(s)", config.repo_profiles.len());
        
        println!("\n{}", "🤖 LLM Configuration:".bold().blue());
        println!("  Provider: {}", config.llm.provider.cyan());
        println!("  Model: {}", config.llm.model.cyan());
        println!("  Base URL: {}", manager.llm_base_url());
        println!("  API Key: {}", mask_api_key(manager.get_api_key().as_deref()));
        println!("  Max tokens: {}", config.llm.max_tokens);
        println!("  Temperature: {}", config.llm.temperature);
        println!("  Timeout: {}s", config.llm.timeout);
        
        println!("\n{}", "📝 Commit Configuration:".bold().blue());
        println!("  Format: {}", config.commit.format.to_string().cyan());
        println!("  Auto-generate: {}", if config.commit.auto_generate { "✓ yes".green() } else { "✗ no".red() });
        println!("  Allow empty: {}", if config.commit.allow_empty { "✓ yes".green() } else { "✗ no".red() });
        println!("  GPG sign: {}", if config.commit.gpg_sign { "✓ yes".green() } else { "✗ no".red() });
        println!("  Default scope: {}", config.commit.default_scope.as_deref().unwrap_or("(none)").cyan());
        println!("  Max subject length: {}", config.commit.max_subject_length);
        println!("  Require scope: {}", if config.commit.require_scope { "✓ yes".green() } else { "✗ no".red() });
        println!("  Require body: {}", if config.commit.require_body { "✓ yes".green() } else { "✗ no".red() });
        if !config.commit.body_required_types.is_empty() {
            println!("  Body required types: {}", config.commit.body_required_types.join(", ").cyan());
        }
        
        println!("\n{}", "🏷️  Tag Configuration:".bold().blue());
        println!("  Version prefix: '{}'", config.tag.version_prefix.cyan());
        println!("  Auto-generate: {}", if config.tag.auto_generate { "✓ yes".green() } else { "✗ no".red() });
        println!("  GPG sign: {}", if config.tag.gpg_sign { "✓ yes".green() } else { "✗ no".red() });
        println!("  Include changelog: {}", if config.tag.include_changelog { "✓ yes".green() } else { "✗ no".red() });
        println!("  Annotation template: {}", config.tag.annotation_template.as_deref().unwrap_or("(none)").cyan());
        
        println!("\n{}", "📋 Changelog Configuration:".bold().blue());
        println!("  Path: {}", config.changelog.path);
        println!("  Auto-generate: {}", if config.changelog.auto_generate { "✓ yes".green() } else { "✗ no".red() });
        println!("  Format: {}", format!("{:?}", config.changelog.format).cyan());
        println!("  Include hashes: {}", if config.changelog.include_hashes { "✓ yes".green() } else { "✗ no".red() });
        println!("  Include authors: {}", if config.changelog.include_authors { "✓ yes".green() } else { "✗ no".red() });
        println!("  Group by type: {}", if config.changelog.group_by_type { "✓ yes".green() } else { "✗ no".red() });
        if !config.changelog.custom_categories.is_empty() {
            println!("  Custom categories: {} category(ies)", config.changelog.custom_categories.len());
        }
        
        println!("\n{}", "🎨 Theme Configuration:".bold().blue());
        println!("  Colors: {}", if config.theme.colors { "✓ enabled".green() } else { "✗ disabled".red() });
        println!("  Icons: {}", if config.theme.icons { "✓ enabled".green() } else { "✗ disabled".red() });
        println!("  Date format: {}", config.theme.date_format.cyan());
        
        println!("\n{}", "🔒 Security:".bold().blue());
        println!("  Encrypt sensitive: {}", if config.encrypt_sensitive { "✓ yes".green() } else { "✗ no".red() });
        
        println!("\n{}", "🔑 Keyring:".bold().blue());
        let keyring = manager.keyring();
        if keyring.is_available() {
            println!("  Status: {}", "✓ available".green());
            println!("  Backend: {}", keyring.get_status_message());
        } else {
            println!("  Status: {}", "✗ unavailable".red());
            println!("  Note: {}", keyring.get_status_message());
        }

        Ok(())
    }

    async fn edit_config(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        crate::utils::editor::edit_file(manager.path())?;
        println!("{} Configuration updated", "✓".green());
        Ok(())
    }

    async fn set_value(&self, key: &str, value: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        match key {
            "llm.provider" => manager.set_llm_provider(value.to_string()),
            "llm.model" => manager.set_llm_model(value.to_string()),
            "llm.base_url" => manager.set_llm_base_url(Some(value.to_string())),
            "llm.max_tokens" => {
                let tokens: u32 = value.parse()?;
                manager.config_mut().llm.max_tokens = tokens;
            }
            "llm.temperature" => {
                let temp: f32 = value.parse()?;
                manager.config_mut().llm.temperature = temp;
            }
            "llm.timeout" => {
                let timeout: u64 = value.parse()?;
                manager.config_mut().llm.timeout = timeout;
            }
            "llm.api_key_storage" => {
                let valid_values = vec!["keyring", "config", "environment"];
                if !valid_values.contains(&value) {
                    bail!("Invalid value: {}. Use: {}", value, valid_values.join(", "));
                }
                manager.config_mut().llm.api_key_storage = value.to_string();
            }
            "commit.format" => {
                let format = match value {
                    "conventional" => CommitFormat::Conventional,
                    "commitlint" => CommitFormat::Commitlint,
                    _ => bail!("Invalid format: {}. Use: conventional, commitlint", value),
                };
                manager.set_commit_format(format);
            }
            "commit.auto_generate" => {
                manager.set_auto_generate_commits(value == "true");
            }
            "tag.version_prefix" => manager.set_version_prefix(value.to_string()),
            "changelog.path" => manager.set_changelog_path(value.to_string()),
            _ => bail!("Unknown configuration key: {}", key),
        }
        
        manager.save()?;
        println!("{} Set {} = {}", "✓".green(), key.cyan(), value);
        
        Ok(())
    }

    async fn get_value(&self, key: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let config = manager.config();
        
        let value = match key {
            "llm.provider" => config.llm.provider.clone(),
            "llm.model" => config.llm.model.clone(),
            "llm.base_url" => manager.llm_base_url(),
            "llm.max_tokens" => config.llm.max_tokens.to_string(),
            "llm.temperature" => config.llm.temperature.to_string(),
            "llm.timeout" => config.llm.timeout.to_string(),
            "llm.api_key_storage" => config.llm.api_key_storage.clone(),
            "commit.format" => config.commit.format.to_string(),
            "commit.auto_generate" => config.commit.auto_generate.to_string(),
            "tag.version_prefix" => config.tag.version_prefix.clone(),
            "changelog.path" => config.changelog.path.clone(),
            _ => bail!("Unknown configuration key: {}", key),
        };
        
        println!("{}", value);
        Ok(())
    }

    async fn set_llm(&self, provider: Option<&str>, model: Option<&str>, base_url: Option<&str>, api_key: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        let selected_provider = if let Some(p) = provider {
            let providers = get_supported_providers();
            if !providers.contains(&p) {
                bail!("Invalid provider: {}. Valid options: {}", p, providers.join(", "));
            }
            p.to_string()
        } else {
            println!("{}", "Select LLM Provider:".bold());
            let provider_display_names = vec![
                "Ollama (local)",
                "OpenAI",
                "Anthropic Claude",
                "Kimi (Moonshot AI)",
                "DeepSeek",
                "OpenRouter"
            ];
            
            let provider_idx = Select::new()
                .items(&provider_display_names)
                .default(0)
                .interact()?;
            
            let providers = get_supported_providers();
            providers[provider_idx].to_string()
        };

        let keyring = manager.keyring();
        let keyring_available = keyring.is_available();
        
        if !keyring_available && provider_needs_api_key(&selected_provider) {
            println!("\n{}", "⚠ Keyring is not available on this system.".yellow());
            println!("{}", keyring.get_status_message().yellow());
        }

        let selected_model = if let Some(m) = model {
            m.to_string()
        } else {
            let default_model = get_default_model(&selected_provider);
            Input::new()
                .with_prompt("Model name")
                .default(default_model.to_string())
                .interact_text()?
        };

        let selected_base_url = if let Some(u) = base_url {
            Some(u.to_string())
        } else if selected_provider == "ollama" {
            let url: String = Input::new()
                .with_prompt("Ollama server URL")
                .default("http://localhost:11434".to_string())
                .interact_text()?;
            Some(url)
        } else {
            let use_custom = Confirm::new()
                .with_prompt("Use custom API base URL?")
                .default(false)
                .interact()?;
            
            if use_custom {
                let default_url = get_default_base_url(&selected_provider);
                let url: String = Input::new()
                    .with_prompt("Base URL")
                    .default(default_url.to_string())
                    .interact_text()?;
                Some(url)
            } else {
                None
            }
        };

        let selected_api_key = if provider_needs_api_key(&selected_provider) {
            if let Some(k) = api_key {
                Some(k.to_string())
            } else if keyring_available {
                let existing_key = manager.get_api_key();
                if existing_key.is_some() {
                    let overwrite = Confirm::new()
                        .with_prompt("API key already exists. Update it?")
                        .default(false)
                        .interact()?;
                    
                    if overwrite {
                        let key: String = Input::new()
                            .with_prompt("API key")
                            .interact_text()?;
                        Some(key)
                    } else {
                        None
                    }
                } else {
                    let key: String = Input::new()
                        .with_prompt("API key")
                        .interact_text()?;
                    Some(key)
                }
            } else {
                println!("\n{}", "Please set the QUICOMMIT_API_KEY environment variable.".yellow());
                None
            }
        } else {
            None
        };

        manager.set_llm_provider(selected_provider.clone());
        manager.set_llm_model(selected_model);
        manager.set_llm_base_url(selected_base_url);

        if let Some(key) = selected_api_key {
            manager.set_api_key(&key)?;
            println!("\n{} API key stored securely in system keyring", "✓".green());
        }

        manager.save()?;
        
        println!("\n{} LLM configuration updated", "✓".green());
        println!("  Provider: {}", manager.llm_provider().cyan());
        println!("  Model: {}", manager.llm_model().cyan());
        println!("  Base URL: {}", manager.llm_base_url());
        
        Ok(())
    }

    async fn set_api_key(&self, key: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        let provider = manager.llm_provider().to_string();
        if !provider_needs_api_key(&provider) {
            println!("{} {} does not require an API key", "ℹ".blue(), provider);
            return Ok(());
        }
        
        let storage_method = manager.config().llm.api_key_storage.to_string();
        
        match storage_method.as_str() {
            "keyring" => {
                if !manager.keyring().is_available() {
                    bail!("Keyring is not available. Set QUICOMMIT_API_KEY environment variable instead or change api_key_storage to 'config'.");
                }
                
                manager.set_api_key(key)?;
                println!("{} API key stored securely in system keyring for {}", "✓".green(), provider.cyan());
            },
            "config" => {
                // Store API key directly in config file
                manager.config_mut().llm.api_key = Some(key.to_string());
                manager.save()?;
                println!("{} API key stored in configuration file for {}", "✓".green(), provider.cyan());
                println!("{} Note: API key is stored in plain text. Consider using 'keyring' storage for better security.", "⚠".yellow());
            },
            "environment" => {
                bail!("API key storage set to 'environment'. Please set QUICOMMIT_{}_API_KEY environment variable.", provider.to_uppercase());
            },
            _ => {
                bail!("Invalid API key storage method: {}", storage_method);
            }
        }
        
        Ok(())
    }

    async fn delete_api_key(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        let provider = manager.llm_provider().to_string();
        let storage_method = manager.config().llm.api_key_storage.to_string();
        
        match storage_method.as_str() {
            "keyring" => {
                if !manager.keyring().is_available() {
                    bail!("Keyring is not available.");
                }
                
                manager.delete_api_key()?;
                println!("{} API key deleted from system keyring for {}", "✓".green(), provider.cyan());
            },
            "config" => {
                // Remove API key from config file
                manager.config_mut().llm.api_key = None;
                manager.save()?;
                println!("{} API key deleted from configuration file for {}", "✓".green(), provider.cyan());
            },
            "environment" => {
                println!("{} API key storage set to 'environment'. Please remove QUICOMMIT_{}_API_KEY environment variable manually.", "ℹ".blue(), provider.to_uppercase());
            },
            _ => {
                bail!("Invalid API key storage method: {}", storage_method);
            }
        }
        
        Ok(())
    }

    async fn set_commit_format(&self, format: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        let format = match format {
            "conventional" => CommitFormat::Conventional,
            "commitlint" => CommitFormat::Commitlint,
            _ => bail!("Invalid format: {}. Use: conventional, commitlint", format),
        };
        
        manager.set_commit_format(format);
        manager.save()?;
        
        println!("{} Commit format set to {}", "✓".green(), format.to_string().cyan());
        Ok(())
    }

    async fn set_version_prefix(&self, prefix: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        manager.set_version_prefix(prefix.to_string());
        manager.save()?;
        
        println!("{} Version prefix set to '{}'", "✓".green(), prefix.cyan());
        Ok(())
    }

    async fn set_changelog_path(&self, path: &str, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        manager.set_changelog_path(path.to_string());
        manager.save()?;
        
        println!("{} Changelog path set to {}", "✓".green(), path.cyan());
        Ok(())
    }

    async fn set_language(&self, language: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        
        let lang_code = if let Some(l) = language {
            l.to_string()
        } else {
            println!("{}", "Select Output Language:".bold());
            let languages = vec![
                ("en", "English"),
                ("zh", "中文"),
                ("ja", "日本語"),
                ("ko", "한국어"),
                ("es", "Español"),
                ("fr", "Français"),
                ("de", "Deutsch"),
            ];
            
            let lang_names: Vec<&str> = languages.iter().map(|(_, n)| *n).collect();
            let idx = Select::new()
                .items(&lang_names)
                .default(0)
                .interact()?;
            
            languages[idx].0.to_string()
        };
        
        manager.set_output_language(lang_code.clone());
        manager.save()?;
        
        println!("{} Output language set to {}", "✓".green(), lang_code.cyan());
        Ok(())
    }

    async fn set_keep_types_english(&self, keep: bool, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        manager.set_keep_types_english(keep);
        manager.save()?;
        
        println!("{} Keep commit types in English: {}", "✓".green(), keep.to_string().cyan());
        Ok(())
    }

    async fn set_keep_changelog_types_english(&self, keep: bool, config_path: &Option<PathBuf>) -> Result<()> {
        let mut manager = self.get_manager(config_path)?;
        manager.set_keep_changelog_types_english(keep);
        manager.save()?;
        
        println!("{} Keep changelog types in English: {}", "✓".green(), keep.to_string().cyan());
        Ok(())
    }

    async fn reset(&self, force: bool, config_path: &Option<PathBuf>) -> Result<()> {
        if !force {
            let confirm = Confirm::new()
                .with_prompt("Reset all configuration to defaults?")
                .default(false)
                .interact()?;
            
            if !confirm {
                println!("Reset cancelled.");
                return Ok(());
            }
        }
        
        let mut manager = self.get_manager(config_path)?;
        manager.reset();
        manager.save()?;
        
        println!("{} Configuration reset to defaults", "✓".green());
        Ok(())
    }

    async fn export_config(&self, output: Option<&str>, password: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let toml = manager.export()?;
        
        let export_content = if let Some(_path) = output {
            let pwd = if let Some(p) = password {
                p.to_string()
            } else {
                let confirm = Confirm::new()
                    .with_prompt("Encrypt the exported configuration?")
                    .default(true)
                    .interact()?;
                
                if confirm {
                    let pwd1 = Password::new()
                        .with_prompt("Enter encryption password")
                        .interact()?;
                    let pwd2 = Password::new()
                        .with_prompt("Confirm encryption password")
                        .interact()?;
                    
                    if pwd1 != pwd2 {
                        bail!("Passwords do not match");
                    }
                    pwd1
                } else {
                    String::new()
                }
            };
            
            if pwd.is_empty() {
                let mut has_pats = false;
                for (profile_name, profile) in manager.config().profiles.iter() {
                    for service in profile.tokens.keys() {
                        if manager.has_pat_for_profile(profile_name, service) {
                            has_pats = true;
                            break;
                        }
                    }
                }
                
                if has_pats {
                    println!("{} {}", "⚠".yellow(), "WARNING: Exporting without encryption.".bold());
                    println!("  {}", "Personal Access Tokens (PATs) stored in keyring will NOT be exported.".yellow());
                    println!("  {}", "To export PATs securely, please enable encryption.".yellow());
                    println!();
                }
                
                toml
            } else {
                let mut encrypted_pats: Vec<EncryptedPat> = Vec::new();
                
                for (profile_name, profile) in manager.config().profiles.iter() {
                    for service in profile.tokens.keys() {
                        if let Ok(Some(pat_value)) = manager.get_pat_for_profile(profile_name, service) {
                            let encrypted_token = encrypt(pat_value.as_bytes(), &pwd)?;
                            encrypted_pats.push(EncryptedPat {
                                profile_name: profile_name.clone(),
                                service: service.clone(),
                                user_email: profile.user_email.clone(),
                                encrypted_token,
                            });
                        }
                    }
                }
                
                let export_data = ExportData::with_encrypted_pats(toml, encrypted_pats);
                let export_json = serde_json::to_string(&export_data)
                    .context("Failed to serialize export data")?;
                let encrypted = encrypt(export_json.as_bytes(), &pwd)?;
                format!("ENCRYPTED:{}", encrypted)
            }
        } else {
            toml
        };
        
        match output {
            Some(path) => {
                std::fs::write(path, &export_content)?;
                if export_content.starts_with("ENCRYPTED:") {
                    println!("{} Configuration encrypted and exported to {}", "✓".green(), path);
                } else {
                    println!("{} Configuration exported to {}", "✓".green(), path);
                }
            }
            None => {
                println!("{}", export_content);
            }
        }
        
        Ok(())
    }

    async fn import_config(&self, file: &str, password: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
        let content = std::fs::read_to_string(file)?;
        
        let (config_content, encrypted_pats, pwd) = if content.starts_with("ENCRYPTED:") {
            let encrypted_data = content.strip_prefix("ENCRYPTED:").unwrap();
            
            let pwd = if let Some(p) = password {
                p.to_string()
            } else {
                Password::new()
                    .with_prompt("Enter decryption password")
                    .interact()?
            };
            
            let decrypted = match decrypt(encrypted_data, &pwd) {
                Ok(d) => d,
                Err(e) => {
                    bail!("Failed to decrypt configuration: {}. Please check your password.", e);
                }
            };
            
            let decrypted_str = String::from_utf8(decrypted)
                .map_err(|e| anyhow::anyhow!("Invalid UTF-8 in decrypted content: {}", e))?;
            
            match serde_json::from_str::<ExportData>(&decrypted_str) {
                Ok(export_data) => {
                    (export_data.config, Some(export_data.encrypted_pats), Some(pwd))
                }
                Err(_) => {
                    (decrypted_str, None, Some(pwd))
                }
            }
        } else {
            (content, None, None)
        };
        
        let mut manager = self.get_manager(config_path)?;
        manager.import(&config_content)?;
        manager.save()?;
        
        if let (Some(pats), Some(pwd)) = (encrypted_pats, pwd) {
            if !pats.is_empty() {
                println!();
                println!("{}", "Importing Personal Access Tokens...".bold());
                
                let mut imported_count = 0;
                let mut failed_count = 0;
                
                for pat in pats {
                    match decrypt(&pat.encrypted_token, &pwd) {
                        Ok(token_bytes) => {
                            match String::from_utf8(token_bytes) {
                                Ok(token_value) => {
                                    if manager.keyring().is_available() {
                                        match manager.store_pat_for_profile(
                                            &pat.profile_name,
                                            &pat.service,
                                            &token_value
                                        ) {
                                            Ok(_) => {
                                                println!("  {} Token for {} ({}) imported to keyring", 
                                                    "✓".green(), 
                                                    pat.profile_name.cyan(), 
                                                    pat.service.yellow());
                                                imported_count += 1;
                                            }
                                            Err(e) => {
                                                println!("  {} Failed to store token for {} ({}): {}", 
                                                    "✗".red(), 
                                                    pat.profile_name, 
                                                    pat.service, 
                                                    e);
                                                failed_count += 1;
                                            }
                                        }
                                    } else {
                                        println!("  {} Keyring not available, cannot store token for {} ({})", 
                                            "⚠".yellow(), 
                                            pat.profile_name, 
                                            pat.service);
                                        failed_count += 1;
                                    }
                                }
                                Err(e) => {
                                    println!("  {} Invalid token format for {} ({}): {}", 
                                        "✗".red(), 
                                        pat.profile_name, 
                                        pat.service, 
                                        e);
                                    failed_count += 1;
                                }
                            }
                        }
                        Err(e) => {
                            println!("  {} Failed to decrypt token for {} ({}): {}", 
                                "✗".red(), 
                                pat.profile_name, 
                                pat.service, 
                                e);
                            failed_count += 1;
                        }
                    }
                }
                
                println!();
                if imported_count > 0 {
                    println!("{} {} token(s) imported to keyring", "✓".green(), imported_count);
                }
                if failed_count > 0 {
                    println!("{} {} token(s) failed to import", "⚠".yellow(), failed_count);
                }
            }
        }
        
        println!("{} Configuration imported from {}", "✓".green(), file);
        Ok(())
    }

    async fn list_models(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        let provider = manager.llm_provider();
        
        println!("{}", "\nAvailable Models".bold());
        println!("{}", "─".repeat(40));
        
        match provider {
            "ollama" => {
                println!("Ollama models (local):");
                println!("  llama2, llama2-uncensored, llama2:13b");
                println!("  codellama, codellama:34b");
                println!("  mistral, mixtral");
                println!("  phi, gemma");
                println!("\nRun 'ollama list' to see installed models");
            }
            "openai" => {
                println!("OpenAI models:");
                println!("  gpt-4, gpt-4-turbo, gpt-4o");
                println!("  gpt-3.5-turbo, gpt-3.5-turbo-16k");
            }
            "anthropic" => {
                println!("Anthropic Claude models:");
                println!("  claude-3-opus-20240229");
                println!("  claude-3-sonnet-20240229");
                println!("  claude-3-haiku-20240307");
            }
            "kimi" => {
                println!("Kimi (Moonshot AI) models:");
                println!("  moonshot-v1-8k");
                println!("  moonshot-v1-32k");
                println!("  moonshot-v1-128k");
            }
            "deepseek" => {
                println!("DeepSeek models:");
                println!("  deepseek-chat");
                println!("  deepseek-reasoner");
            }
            "openrouter" => {
                println!("OpenRouter models (examples):");
                println!("  openai/gpt-4, openai/gpt-3.5-turbo");
                println!("  anthropic/claude-3-opus");
                println!("  google/gemini-pro");
                println!("  meta-llama/llama-2-70b-chat");
                println!("\nSee https://openrouter.ai/models for full list");
            }
            _ => {
                println!("Unknown provider: {}", provider);
            }
        }
        
        println!("\nCurrent model: {}", manager.llm_model().cyan());
        
        Ok(())
    }

    async fn test_llm(&self, config_path: &Option<PathBuf>) -> Result<()> {
        let manager = self.get_manager(config_path)?;
        
        println!("{}", "\nTesting LLM Connection...".bold());
        println!("  Provider: {}", manager.llm_provider().cyan());
        println!("  Model: {}", manager.llm_model().cyan());
        println!("  Base URL: {}", manager.llm_base_url());
        
        let has_key = manager.has_api_key();
        if provider_needs_api_key(manager.llm_provider()) {
            println!("  API Key: {}", if has_key { "✓ configured".green() } else { "✗ not set".red() });
        }
        
        println!("\n{}", "Sending test request...".dimmed());
        
        match crate::llm::test_connection(&manager).await {
            Ok(response) => {
                println!("{} Connection successful!", "✓".green());
                println!("\n{}", "Response:".bold());
                println!("  {}", response);
            }
            Err(e) => {
                println!("{} Connection failed: {}", "✗".red(), e);
                return Err(e);
            }
        }
        
        Ok(())
    }
}
