use crate::state::AppState;
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use tauri::{Manager, State};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GeneralSettings {
    pub launch_at_login: bool,
    pub show_dock_icon: bool,
    pub default_terminal: String,
    pub default_shell: String,
    pub show_welcome_on_startup: Option<bool>,
    pub theme: Option<String>,
    pub language: Option<String>,
    pub check_updates_automatically: Option<bool>,
    pub prompt_move_to_applications: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DashboardSettings {
    pub server_port: u16,
    pub enable_password: bool,
    pub password: String,
    pub access_mode: String,
    pub auto_cleanup: bool,
    pub session_limit: Option<u32>,
    pub idle_timeout_minutes: Option<u32>,
    pub enable_cors: Option<bool>,
    pub allowed_origins: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct AdvancedSettings {
    pub debug_mode: bool,
    pub log_level: String,
    pub session_timeout: u32,
    pub ngrok_auth_token: Option<String>,
    pub ngrok_region: Option<String>,
    pub ngrok_subdomain: Option<String>,
    pub enable_telemetry: Option<bool>,
    pub experimental_features: Option<bool>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TTYForwardSettings {
    pub enabled: bool,
    pub default_port: u16,
    pub bind_address: String,
    pub max_connections: u32,
    pub buffer_size: u32,
    pub keep_alive: bool,
    pub authentication: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MonitoringSettings {
    pub enabled: bool,
    pub collect_metrics: bool,
    pub metric_interval_seconds: u32,
    pub max_history_size: u32,
    pub alert_on_high_cpu: bool,
    pub alert_on_high_memory: bool,
    pub cpu_threshold_percent: Option<u8>,
    pub memory_threshold_percent: Option<u8>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NetworkSettings {
    pub preferred_interface: Option<String>,
    pub enable_ipv6: bool,
    pub dns_servers: Option<Vec<String>>,
    pub proxy_settings: Option<ProxySettings>,
    pub connection_timeout_seconds: u32,
    pub retry_attempts: u32,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ProxySettings {
    pub enabled: bool,
    pub proxy_type: String,
    pub host: String,
    pub port: u16,
    pub username: Option<String>,
    pub password: Option<String>,
    pub bypass_list: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PortSettings {
    pub auto_resolve_conflicts: bool,
    pub preferred_port_range_start: u16,
    pub preferred_port_range_end: u16,
    pub excluded_ports: Option<Vec<u16>>,
    pub conflict_resolution_strategy: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NotificationSettings {
    pub enabled: bool,
    pub show_in_system: bool,
    pub play_sound: bool,
    pub notification_types: HashMap<String, bool>,
    pub do_not_disturb_enabled: Option<bool>,
    pub do_not_disturb_start: Option<String>,
    pub do_not_disturb_end: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TerminalIntegrationSettings {
    pub enabled_terminals: HashMap<String, bool>,
    pub terminal_configs: HashMap<String, TerminalConfig>,
    pub default_terminal_override: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TerminalConfig {
    pub path: Option<String>,
    pub args: Option<Vec<String>>,
    pub env: Option<HashMap<String, String>>,
    pub working_directory: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UpdateSettings {
    pub channel: String,
    pub check_frequency: String,
    pub auto_download: bool,
    pub auto_install: bool,
    pub show_release_notes: bool,
    pub include_pre_releases: bool,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SecuritySettings {
    pub enable_encryption: bool,
    pub encryption_algorithm: Option<String>,
    pub require_authentication: bool,
    pub session_token_expiry_hours: Option<u32>,
    pub allowed_ip_addresses: Option<Vec<String>>,
    pub blocked_ip_addresses: Option<Vec<String>>,
    pub rate_limiting_enabled: bool,
    pub rate_limit_requests_per_minute: Option<u32>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DebugSettings {
    pub enable_debug_menu: bool,
    pub show_performance_stats: bool,
    pub enable_verbose_logging: bool,
    pub log_to_file: bool,
    pub log_file_path: Option<String>,
    pub max_log_file_size_mb: Option<u32>,
    pub enable_dev_tools: bool,
    pub show_internal_errors: bool,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Settings {
    pub general: GeneralSettings,
    pub dashboard: DashboardSettings,
    pub advanced: AdvancedSettings,
    pub tty_forward: Option<TTYForwardSettings>,
    pub monitoring: Option<MonitoringSettings>,
    pub network: Option<NetworkSettings>,
    pub port: Option<PortSettings>,
    pub notifications: Option<NotificationSettings>,
    pub terminal_integrations: Option<TerminalIntegrationSettings>,
    pub updates: Option<UpdateSettings>,
    pub security: Option<SecuritySettings>,
    pub debug: Option<DebugSettings>,
}

impl Default for Settings {
    fn default() -> Self {
        let mut default_notification_types = HashMap::new();
        default_notification_types.insert("info".to_string(), true);
        default_notification_types.insert("success".to_string(), true);
        default_notification_types.insert("warning".to_string(), true);
        default_notification_types.insert("error".to_string(), true);
        default_notification_types.insert("server_status".to_string(), true);
        default_notification_types.insert("update_available".to_string(), true);

        let mut enabled_terminals = HashMap::new();
        enabled_terminals.insert("Terminal".to_string(), true);
        enabled_terminals.insert("iTerm2".to_string(), true);
        enabled_terminals.insert("Hyper".to_string(), true);
        enabled_terminals.insert("Alacritty".to_string(), true);
        enabled_terminals.insert("Warp".to_string(), true);
        enabled_terminals.insert("Ghostty".to_string(), false);
        enabled_terminals.insert("WezTerm".to_string(), false);

        Self {
            general: GeneralSettings {
                launch_at_login: false,
                show_dock_icon: true,
                default_terminal: "system".to_string(),
                default_shell: "default".to_string(),
                show_welcome_on_startup: Some(true),
                theme: Some("auto".to_string()),
                language: Some("en".to_string()),
                check_updates_automatically: Some(true),
                prompt_move_to_applications: None,
            },
            dashboard: DashboardSettings {
                server_port: 4022,
                enable_password: false,
                password: String::new(),
                access_mode: "localhost".to_string(),
                auto_cleanup: true,
                session_limit: Some(10),
                idle_timeout_minutes: Some(30),
                enable_cors: Some(true),
                allowed_origins: Some(vec!["*".to_string()]),
            },
            advanced: AdvancedSettings {
                debug_mode: false,
                log_level: "info".to_string(),
                session_timeout: 0,
                ngrok_auth_token: None,
                ngrok_region: Some("us".to_string()),
                ngrok_subdomain: None,
                enable_telemetry: Some(false),
                experimental_features: Some(false),
            },
            tty_forward: Some(TTYForwardSettings {
                enabled: false,
                default_port: 8022,
                bind_address: "127.0.0.1".to_string(),
                max_connections: 5,
                buffer_size: 4096,
                keep_alive: true,
                authentication: None,
            }),
            monitoring: Some(MonitoringSettings {
                enabled: true,
                collect_metrics: true,
                metric_interval_seconds: 5,
                max_history_size: 1000,
                alert_on_high_cpu: false,
                alert_on_high_memory: false,
                cpu_threshold_percent: Some(80),
                memory_threshold_percent: Some(80),
            }),
            network: Some(NetworkSettings {
                preferred_interface: None,
                enable_ipv6: true,
                dns_servers: None,
                proxy_settings: None,
                connection_timeout_seconds: 30,
                retry_attempts: 3,
            }),
            port: Some(PortSettings {
                auto_resolve_conflicts: true,
                preferred_port_range_start: 4000,
                preferred_port_range_end: 5000,
                excluded_ports: None,
                conflict_resolution_strategy: "increment".to_string(),
            }),
            notifications: Some(NotificationSettings {
                enabled: true,
                show_in_system: true,
                play_sound: true,
                notification_types: default_notification_types,
                do_not_disturb_enabled: Some(false),
                do_not_disturb_start: None,
                do_not_disturb_end: None,
            }),
            terminal_integrations: Some(TerminalIntegrationSettings {
                enabled_terminals,
                terminal_configs: HashMap::new(),
                default_terminal_override: None,
            }),
            updates: Some(UpdateSettings {
                channel: "stable".to_string(),
                check_frequency: "weekly".to_string(),
                auto_download: false,
                auto_install: false,
                show_release_notes: true,
                include_pre_releases: false,
            }),
            security: Some(SecuritySettings {
                enable_encryption: false,
                encryption_algorithm: Some("aes-256-gcm".to_string()),
                require_authentication: false,
                session_token_expiry_hours: Some(24),
                allowed_ip_addresses: None,
                blocked_ip_addresses: None,
                rate_limiting_enabled: false,
                rate_limit_requests_per_minute: Some(60),
            }),
            debug: Some(DebugSettings {
                enable_debug_menu: false,
                show_performance_stats: false,
                enable_verbose_logging: false,
                log_to_file: false,
                log_file_path: None,
                max_log_file_size_mb: Some(50),
                enable_dev_tools: false,
                show_internal_errors: false,
            }),
        }
    }
}

impl Settings {
    pub fn load() -> Result<Self, String> {
        let config_path = Self::config_path()?;

        let mut settings = if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .map_err(|e| format!("Failed to read settings: {e}"))?;

            toml::from_str(&contents).map_err(|e| format!("Failed to parse settings: {e}"))?
        } else {
            Self::default()
        };

        // Load passwords from keychain
        if let Ok(Some(password)) = crate::keychain::KeychainManager::get_dashboard_password() {
            settings.dashboard.password = password;
        }

        if let Ok(Some(token)) = crate::keychain::KeychainManager::get_ngrok_auth_token() {
            settings.advanced.ngrok_auth_token = Some(token);
        }

        Ok(settings)
    }

    pub fn save(&self) -> Result<(), String> {
        let config_path = Self::config_path()?;

        // Ensure the config directory exists
        if let Some(parent) = config_path.parent() {
            std::fs::create_dir_all(parent)
                .map_err(|e| format!("Failed to create config directory: {e}"))?;
        }

        // Clone settings to remove sensitive data before saving
        let mut settings_to_save = self.clone();

        // Save passwords to keychain and remove from TOML
        if !self.dashboard.password.is_empty() {
            crate::keychain::KeychainManager::set_dashboard_password(&self.dashboard.password)
                .map_err(|e| {
                    format!(
                        "Failed to save dashboard password to keychain: {}",
                        e.message
                    )
                })?;
            settings_to_save.dashboard.password = String::new();
        }

        if let Some(ref token) = self.advanced.ngrok_auth_token {
            if !token.is_empty() {
                crate::keychain::KeychainManager::set_ngrok_auth_token(token).map_err(|e| {
                    format!("Failed to save ngrok token to keychain: {}", e.message)
                })?;
                settings_to_save.advanced.ngrok_auth_token = None;
            }
        }

        let contents = toml::to_string_pretty(&settings_to_save)
            .map_err(|e| format!("Failed to serialize settings: {e}"))?;

        std::fs::write(&config_path, contents)
            .map_err(|e| format!("Failed to write settings: {e}"))?;

        Ok(())
    }

    fn config_path() -> Result<PathBuf, String> {
        let proj_dirs = ProjectDirs::from("com", "vibetunnel", "VibeTunnel")
            .ok_or_else(|| "Failed to get project directories".to_string())?;

        Ok(proj_dirs.config_dir().join("settings.toml"))
    }

    /// Migrate passwords from settings file to keychain (one-time operation)
    #[allow(dead_code)]
    pub fn migrate_passwords_to_keychain(&self) -> Result<(), String> {
        // Check if we have passwords in the settings file that need migration
        let config_path = Self::config_path()?;
        if !config_path.exists() {
            return Ok(());
        }

        let contents = std::fs::read_to_string(&config_path)
            .map_err(|e| format!("Failed to read settings for migration: {e}"))?;

        let raw_settings: Self = toml::from_str(&contents)
            .map_err(|e| format!("Failed to parse settings for migration: {e}"))?;

        let mut migrated = false;

        // Migrate dashboard password if present in file
        if !raw_settings.dashboard.password.is_empty() {
            crate::keychain::KeychainManager::set_dashboard_password(
                &raw_settings.dashboard.password,
            )
            .map_err(|e| format!("Failed to migrate dashboard password: {}", e.message))?;
            migrated = true;
        }

        // Migrate ngrok token if present in file
        if let Some(ref token) = raw_settings.advanced.ngrok_auth_token {
            if !token.is_empty() {
                crate::keychain::KeychainManager::set_ngrok_auth_token(token)
                    .map_err(|e| format!("Failed to migrate ngrok token: {}", e.message))?;
                migrated = true;
            }
        }

        // If we migrated anything, save the settings again to remove passwords from file
        if migrated {
            self.save()?;
        }

        Ok(())
    }
}

#[tauri::command]
pub async fn get_settings(_state: State<'_, AppState>) -> Result<Settings, String> {
    Settings::load()
}

#[tauri::command]
pub async fn save_settings(
    settings: Settings,
    _state: State<'_, AppState>,
    app: tauri::AppHandle,
) -> Result<(), String> {
    settings.save()?;

    // Apply settings that need immediate effect
    if settings.general.launch_at_login {
        crate::auto_launch::enable_auto_launch()?;
    } else {
        crate::auto_launch::disable_auto_launch()?;
    }

    // Apply dock icon visibility on macOS
    #[cfg(target_os = "macos")]
    {
        // Check if any windows are visible
        let has_visible_windows = app
            .windows()
            .values()
            .any(|w| w.is_visible().unwrap_or(false));

        if !has_visible_windows && !settings.general.show_dock_icon {
            // Hide dock icon if no windows are visible and setting is disabled
            let _ = app.set_activation_policy(tauri::ActivationPolicy::Accessory);
        } else if settings.general.show_dock_icon && !has_visible_windows {
            // Show dock icon if setting is enabled (even with no windows)
            let _ = app.set_activation_policy(tauri::ActivationPolicy::Regular);
        }
        // Note: If windows are visible, we always show the dock icon regardless of setting
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn test_general_settings_default() {
        let settings = GeneralSettings {
            launch_at_login: false,
            show_dock_icon: true,
            default_terminal: "system".to_string(),
            default_shell: "default".to_string(),
            show_welcome_on_startup: Some(true),
            theme: Some("auto".to_string()),
            language: Some("en".to_string()),
            check_updates_automatically: Some(true),
            prompt_move_to_applications: None,
        };

        assert!(!settings.launch_at_login);
        assert!(settings.show_dock_icon);
        assert_eq!(settings.default_terminal, "system");
        assert_eq!(settings.default_shell, "default");
        assert_eq!(settings.show_welcome_on_startup, Some(true));
        assert_eq!(settings.theme, Some("auto".to_string()));
        assert_eq!(settings.language, Some("en".to_string()));
        assert_eq!(settings.check_updates_automatically, Some(true));
        assert!(settings.prompt_move_to_applications.is_none());
    }

    #[test]
    fn test_dashboard_settings_default() {
        let settings = DashboardSettings {
            server_port: 4022,
            enable_password: false,
            password: String::new(),
            access_mode: "localhost".to_string(),
            auto_cleanup: true,
            session_limit: Some(10),
            idle_timeout_minutes: Some(30),
            enable_cors: Some(true),
            allowed_origins: Some(vec!["*".to_string()]),
        };

        assert_eq!(settings.server_port, 4022);
        assert!(!settings.enable_password);
        assert_eq!(settings.password, "");
        assert_eq!(settings.access_mode, "localhost");
        assert!(settings.auto_cleanup);
        assert_eq!(settings.session_limit, Some(10));
        assert_eq!(settings.idle_timeout_minutes, Some(30));
        assert_eq!(settings.enable_cors, Some(true));
        assert_eq!(settings.allowed_origins, Some(vec!["*".to_string()]));
    }

    #[test]
    fn test_advanced_settings_default() {
        let settings = AdvancedSettings {
            debug_mode: false,
            log_level: "info".to_string(),
            session_timeout: 0,
            ngrok_auth_token: None,
            ngrok_region: Some("us".to_string()),
            ngrok_subdomain: None,
            enable_telemetry: Some(false),
            experimental_features: Some(false),
        };

        assert!(!settings.debug_mode);
        assert_eq!(settings.log_level, "info");
        assert_eq!(settings.session_timeout, 0);
        assert!(settings.ngrok_auth_token.is_none());
        assert_eq!(settings.ngrok_region, Some("us".to_string()));
        assert!(settings.ngrok_subdomain.is_none());
        assert_eq!(settings.enable_telemetry, Some(false));
        assert_eq!(settings.experimental_features, Some(false));
    }

    #[test]
    fn test_tty_forward_settings() {
        let settings = TTYForwardSettings {
            enabled: false,
            default_port: 8022,
            bind_address: "127.0.0.1".to_string(),
            max_connections: 5,
            buffer_size: 4096,
            keep_alive: true,
            authentication: None,
        };

        assert!(!settings.enabled);
        assert_eq!(settings.default_port, 8022);
        assert_eq!(settings.bind_address, "127.0.0.1");
        assert_eq!(settings.max_connections, 5);
        assert_eq!(settings.buffer_size, 4096);
        assert!(settings.keep_alive);
        assert!(settings.authentication.is_none());
    }

    #[test]
    fn test_monitoring_settings() {
        let settings = MonitoringSettings {
            enabled: true,
            collect_metrics: true,
            metric_interval_seconds: 5,
            max_history_size: 1000,
            alert_on_high_cpu: false,
            alert_on_high_memory: false,
            cpu_threshold_percent: Some(80),
            memory_threshold_percent: Some(80),
        };

        assert!(settings.enabled);
        assert!(settings.collect_metrics);
        assert_eq!(settings.metric_interval_seconds, 5);
        assert_eq!(settings.max_history_size, 1000);
        assert!(!settings.alert_on_high_cpu);
        assert!(!settings.alert_on_high_memory);
        assert_eq!(settings.cpu_threshold_percent, Some(80));
        assert_eq!(settings.memory_threshold_percent, Some(80));
    }

    #[test]
    fn test_network_settings() {
        let settings = NetworkSettings {
            preferred_interface: None,
            enable_ipv6: true,
            dns_servers: None,
            proxy_settings: None,
            connection_timeout_seconds: 30,
            retry_attempts: 3,
        };

        assert!(settings.preferred_interface.is_none());
        assert!(settings.enable_ipv6);
        assert!(settings.dns_servers.is_none());
        assert!(settings.proxy_settings.is_none());
        assert_eq!(settings.connection_timeout_seconds, 30);
        assert_eq!(settings.retry_attempts, 3);
    }

    #[test]
    fn test_proxy_settings() {
        let settings = ProxySettings {
            enabled: true,
            proxy_type: "http".to_string(),
            host: "proxy.example.com".to_string(),
            port: 8080,
            username: Some("user".to_string()),
            password: Some("pass".to_string()),
            bypass_list: Some(vec!["localhost".to_string(), "127.0.0.1".to_string()]),
        };

        assert!(settings.enabled);
        assert_eq!(settings.proxy_type, "http");
        assert_eq!(settings.host, "proxy.example.com");
        assert_eq!(settings.port, 8080);
        assert_eq!(settings.username, Some("user".to_string()));
        assert_eq!(settings.password, Some("pass".to_string()));
        assert_eq!(
            settings.bypass_list,
            Some(vec!["localhost".to_string(), "127.0.0.1".to_string()])
        );
    }

    #[test]
    fn test_port_settings() {
        let settings = PortSettings {
            auto_resolve_conflicts: true,
            preferred_port_range_start: 4000,
            preferred_port_range_end: 5000,
            excluded_ports: Some(vec![4022, 8080]),
            conflict_resolution_strategy: "increment".to_string(),
        };

        assert!(settings.auto_resolve_conflicts);
        assert_eq!(settings.preferred_port_range_start, 4000);
        assert_eq!(settings.preferred_port_range_end, 5000);
        assert_eq!(settings.excluded_ports, Some(vec![4022, 8080]));
        assert_eq!(settings.conflict_resolution_strategy, "increment");
    }

    #[test]
    fn test_notification_settings() {
        let mut notification_types = HashMap::new();
        notification_types.insert("info".to_string(), true);
        notification_types.insert("error".to_string(), false);

        let settings = NotificationSettings {
            enabled: true,
            show_in_system: true,
            play_sound: false,
            notification_types,
            do_not_disturb_enabled: Some(true),
            do_not_disturb_start: Some("22:00".to_string()),
            do_not_disturb_end: Some("08:00".to_string()),
        };

        assert!(settings.enabled);
        assert!(settings.show_in_system);
        assert!(!settings.play_sound);
        assert_eq!(settings.notification_types.get("info"), Some(&true));
        assert_eq!(settings.notification_types.get("error"), Some(&false));
        assert_eq!(settings.do_not_disturb_enabled, Some(true));
        assert_eq!(settings.do_not_disturb_start, Some("22:00".to_string()));
        assert_eq!(settings.do_not_disturb_end, Some("08:00".to_string()));
    }

    #[test]
    fn test_terminal_config() {
        let mut env = HashMap::new();
        env.insert("TERM".to_string(), "xterm-256color".to_string());

        let config = TerminalConfig {
            path: Some("/usr/local/bin/terminal".to_string()),
            args: Some(vec!["--new-session".to_string()]),
            env: Some(env),
            working_directory: Some("/home/user".to_string()),
        };

        assert_eq!(config.path, Some("/usr/local/bin/terminal".to_string()));
        assert_eq!(config.args, Some(vec!["--new-session".to_string()]));
        assert_eq!(
            config.env.as_ref().unwrap().get("TERM"),
            Some(&"xterm-256color".to_string())
        );
        assert_eq!(config.working_directory, Some("/home/user".to_string()));
    }

    #[test]
    fn test_update_settings() {
        let settings = UpdateSettings {
            channel: "stable".to_string(),
            check_frequency: "weekly".to_string(),
            auto_download: false,
            auto_install: false,
            show_release_notes: true,
            include_pre_releases: false,
        };

        assert_eq!(settings.channel, "stable");
        assert_eq!(settings.check_frequency, "weekly");
        assert!(!settings.auto_download);
        assert!(!settings.auto_install);
        assert!(settings.show_release_notes);
        assert!(!settings.include_pre_releases);
    }

    #[test]
    fn test_security_settings() {
        let settings = SecuritySettings {
            enable_encryption: true,
            encryption_algorithm: Some("aes-256-gcm".to_string()),
            require_authentication: true,
            session_token_expiry_hours: Some(24),
            allowed_ip_addresses: Some(vec!["192.168.1.0/24".to_string()]),
            blocked_ip_addresses: Some(vec!["10.0.0.0/8".to_string()]),
            rate_limiting_enabled: true,
            rate_limit_requests_per_minute: Some(60),
        };

        assert!(settings.enable_encryption);
        assert_eq!(
            settings.encryption_algorithm,
            Some("aes-256-gcm".to_string())
        );
        assert!(settings.require_authentication);
        assert_eq!(settings.session_token_expiry_hours, Some(24));
        assert_eq!(
            settings.allowed_ip_addresses,
            Some(vec!["192.168.1.0/24".to_string()])
        );
        assert_eq!(
            settings.blocked_ip_addresses,
            Some(vec!["10.0.0.0/8".to_string()])
        );
        assert!(settings.rate_limiting_enabled);
        assert_eq!(settings.rate_limit_requests_per_minute, Some(60));
    }

    #[test]
    fn test_debug_settings() {
        let settings = DebugSettings {
            enable_debug_menu: true,
            show_performance_stats: true,
            enable_verbose_logging: false,
            log_to_file: true,
            log_file_path: Some("/var/log/vibetunnel.log".to_string()),
            max_log_file_size_mb: Some(100),
            enable_dev_tools: false,
            show_internal_errors: true,
        };

        assert!(settings.enable_debug_menu);
        assert!(settings.show_performance_stats);
        assert!(!settings.enable_verbose_logging);
        assert!(settings.log_to_file);
        assert_eq!(
            settings.log_file_path,
            Some("/var/log/vibetunnel.log".to_string())
        );
        assert_eq!(settings.max_log_file_size_mb, Some(100));
        assert!(!settings.enable_dev_tools);
        assert!(settings.show_internal_errors);
    }

    #[test]
    fn test_settings_default() {
        let settings = Settings::default();

        // Test that all required fields have defaults
        assert_eq!(settings.general.default_terminal, "system");
        assert_eq!(settings.dashboard.server_port, 4022);
        assert_eq!(settings.advanced.log_level, "info");

        // Test that optional fields have sensible defaults
        assert!(settings.tty_forward.is_some());
        assert!(settings.monitoring.is_some());
        assert!(settings.network.is_some());
        assert!(settings.port.is_some());
        assert!(settings.notifications.is_some());
        assert!(settings.terminal_integrations.is_some());
        assert!(settings.updates.is_some());
        assert!(settings.security.is_some());
        assert!(settings.debug.is_some());
    }

    #[test]
    fn test_settings_serialization() {
        let settings = Settings::default();

        // Test that settings can be serialized to TOML
        let toml_result = toml::to_string_pretty(&settings);
        assert!(toml_result.is_ok());

        let toml_str = toml_result.unwrap();
        assert!(toml_str.contains("[general]"));
        assert!(toml_str.contains("[dashboard]"));
        assert!(toml_str.contains("[advanced]"));
    }

    #[test]
    fn test_settings_deserialization() {
        let toml_str = r#"
[general]
launch_at_login = true
show_dock_icon = false
default_terminal = "iTerm2"
default_shell = "/bin/zsh"

[dashboard]
server_port = 8080
enable_password = true
password = ""
access_mode = "network"
auto_cleanup = false

[advanced]
debug_mode = true
log_level = "debug"
session_timeout = 3600
"#;

        let settings_result: Result<Settings, _> = toml::from_str(toml_str);
        assert!(settings_result.is_ok());

        let settings = settings_result.unwrap();
        assert!(settings.general.launch_at_login);
        assert!(!settings.general.show_dock_icon);
        assert_eq!(settings.general.default_terminal, "iTerm2");
        assert_eq!(settings.general.default_shell, "/bin/zsh");
        assert_eq!(settings.dashboard.server_port, 8080);
        assert!(settings.dashboard.enable_password);
        assert_eq!(settings.dashboard.access_mode, "network");
        assert!(!settings.dashboard.auto_cleanup);
        assert!(settings.advanced.debug_mode);
        assert_eq!(settings.advanced.log_level, "debug");
        assert_eq!(settings.advanced.session_timeout, 3600);
    }

    #[test]
    fn test_settings_partial_deserialization() {
        // Test that missing optional fields don't cause deserialization to fail
        let toml_str = r#"
[general]
launch_at_login = false
show_dock_icon = true
default_terminal = "system"
default_shell = "default"

[dashboard]
server_port = 4022
enable_password = false
password = ""
access_mode = "localhost"
auto_cleanup = true

[advanced]
debug_mode = false
log_level = "info"
session_timeout = 0
"#;

        let settings_result: Result<Settings, _> = toml::from_str(toml_str);
        assert!(settings_result.is_ok());

        let settings = settings_result.unwrap();
        // All optional sections should be None
        assert!(settings.tty_forward.is_none());
        assert!(settings.monitoring.is_none());
        assert!(settings.network.is_none());
    }

    #[test]
    fn test_terminal_integration_settings() {
        let mut enabled_terminals = HashMap::new();
        enabled_terminals.insert("Terminal".to_string(), true);
        enabled_terminals.insert("iTerm2".to_string(), false);

        let mut terminal_configs = HashMap::new();
        terminal_configs.insert(
            "Terminal".to_string(),
            TerminalConfig {
                path: Some("/System/Applications/Utilities/Terminal.app".to_string()),
                args: None,
                env: None,
                working_directory: None,
            },
        );

        let settings = TerminalIntegrationSettings {
            enabled_terminals,
            terminal_configs,
            default_terminal_override: Some("Terminal".to_string()),
        };

        assert_eq!(settings.enabled_terminals.get("Terminal"), Some(&true));
        assert_eq!(settings.enabled_terminals.get("iTerm2"), Some(&false));
        assert!(settings.terminal_configs.contains_key("Terminal"));
        assert_eq!(
            settings.default_terminal_override,
            Some("Terminal".to_string())
        );
    }

    #[test]
    fn test_settings_clone() {
        let original = Settings::default();
        let cloned = original.clone();

        // Verify that clone produces identical values
        assert_eq!(
            original.general.launch_at_login,
            cloned.general.launch_at_login
        );
        assert_eq!(original.dashboard.server_port, cloned.dashboard.server_port);
        assert_eq!(original.advanced.log_level, cloned.advanced.log_level);
    }

    #[test]
    fn test_sensitive_data_removal() {
        let mut settings = Settings::default();
        settings.dashboard.password = "secret123".to_string();
        settings.advanced.ngrok_auth_token = Some("token456".to_string());

        let mut settings_to_save = settings.clone();
        // Simulate what happens during save
        settings_to_save.dashboard.password = String::new();
        settings_to_save.advanced.ngrok_auth_token = None;

        assert_eq!(settings_to_save.dashboard.password, "");
        assert!(settings_to_save.advanced.ngrok_auth_token.is_none());
    }
}
