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

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

/// 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,

    /// 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::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!("\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!("\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!("\n{}", "Security:".bold());
        println!("  Repository mappings: {} mapping(s)", config.repo_profiles.len());
        println!(
            "  Keyring: {}",
            if manager.keyring().is_available() {
                "available".green()
            } else {
                "unavailable".red()
            }
        );

        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.thinking_enabled" => {
                manager.config_mut().llm.thinking_enabled = value == "true";
            }
            "llm.thinking_budget_tokens" => {
                let budget: u32 = value.parse()?;
                manager.config_mut().llm.thinking_budget_tokens = Some(budget);
            }
            "llm.api_key_storage" => {
                let valid_values = ["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()),
            "tag.auto_generate" => {
                manager.config_mut().tag.auto_generate = value == "true";
            }
            "changelog.path" => manager.set_changelog_path(value.to_string()),
            "changelog.auto_generate" => {
                manager.config_mut().changelog.auto_generate = value == "true";
            }
            "language.output_language" => {
                manager.set_output_language(value.to_string());
            }
            "language.keep_types_english" => {
                manager.set_keep_types_english(value == "true");
            }
            "language.keep_changelog_types_english" => {
                manager.set_keep_changelog_types_english(value == "true");
            }
            _ => 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.thinking_enabled" => config.llm.thinking_enabled.to_string(),
            "llm.thinking_budget_tokens" => config
                .llm
                .thinking_budget_tokens
                .map(|v| v.to_string())
                .unwrap_or_else(|| "none".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(),
            "tag.auto_generate" => config.tag.auto_generate.to_string(),
            "changelog.path" => config.changelog.path.clone(),
            "changelog.auto_generate" => config.changelog.auto_generate.to_string(),
            "language.output_language" => config.language.output_language.clone(),
            "language.keep_types_english" => config.language.keep_types_english.to_string(),
            "language.keep_changelog_types_english" => {
                config.language.keep_changelog_types_english.to_string()
            }
            _ => 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 = [
                ("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)
            && !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, phi, gemma");
                println!("\nRun 'ollama list' to see installed models");
            }
            "openai" => {
                println!("OpenAI models:");
                println!("  o-series (reasoning): o4-mini, o3, o3-mini, o1, o1-mini, o1-pro");
                println!("  GPT-4: gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini");
                println!("  Legacy: gpt-4-turbo, gpt-4, gpt-3.5-turbo");
                println!("\nUse --think/-t with o-series models for reasoning mode.");
            }
            "anthropic" => {
                println!("Anthropic Claude models:");
                println!(
                    "  Claude 4 (thinking): claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5"
                );
                println!(
                    "  Claude 3.5: claude-3-opus-20240229, claude-3-sonnet-20240229, claude-3-haiku-20240307"
                );
                println!("  Legacy: claude-2.1, claude-2.0, claude-instant-1.2");
                println!("\nUse --think/-t with Claude 4 models for extended thinking.");
            }
            "kimi" => {
                println!("Kimi (Moonshot AI) models:");
                println!(
                    "  K2 (thinking): kimi-k2.6, kimi-k2.5, kimi-k2-thinking, kimi-k2-thinking-turbo"
                );
                println!("  K2 instruct: kimi-k2-instruct, kimi-k2-instruct-0905");
                println!("  Legacy: moonshot-v1-8k, moonshot-v1-32k, moonshot-v1-128k");
                println!("\nUse --think/-t with K2 models for thinking mode.");
            }
            "deepseek" => {
                println!("DeepSeek models:");
                println!("  V4: deepseek-v4-flash, deepseek-v4-pro");
                println!("  Legacy: deepseek-chat, deepseek-reasoner (deprecated 2026-07-24)");
                println!("\nUse --think/-t for reasoning mode.");
            }
            "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(())
    }
}
