//! Configuration module for the terminal UI
//!
//! Supports configuration via:
//! 1. Environment variables (TUI_*, API_*)
//! 2. Configuration file (.tui/config.toml or custom path)
//! 3. Hardcoded defaults

use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// TUI configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TuiConfig {
    /// Application settings
    pub app: AppConfig,
    /// API server settings
    pub api: ApiConfig,
    /// Features
    #[serde(default)]
    pub features: FeaturesConfig,
    /// UI settings
    #[serde(default)]
    pub ui: UiConfig,
}

/// Application configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    /// Theme name (default, dark, light, minimal, professional)
    #[serde(default = "default_theme")]
    pub theme: String,
    /// Refresh interval in milliseconds
    #[serde(default = "default_refresh_interval")]
    pub refresh_interval_ms: u64,
    /// Enable plugin system
    #[serde(default)]
    pub enable_plugins: bool,
}

/// API server configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiConfig {
    /// API base URL
    #[serde(default = "default_api_base")]
    pub base_url: String,
    /// WebSocket URL for real-time updates
    #[serde(default = "default_ws_url")]
    pub ws_url: String,
    /// API request timeout in seconds
    #[serde(default = "default_api_timeout")]
    pub timeout_secs: u64,
    /// Enable automatic sync with server
    #[serde(default = "default_enable_sync")]
    pub enable_sync: bool,
    /// Sync interval in seconds
    #[serde(default = "default_sync_interval")]
    pub sync_interval_secs: u64,
}

/// Features configuration
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct FeaturesConfig {
    /// Enable real-time sync via WebSocket
    #[serde(default)]
    pub realtime_sync: bool,
    /// Enable caching
    #[serde(default)]
    pub caching: bool,
    /// Enable mouse support
    #[serde(default)]
    pub mouse_support: bool,
    /// Enable offline mode
    #[serde(default)]
    pub offline_mode: bool,
}

/// UI configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UiConfig {
    /// Delete confirmation mode: "modal", "inline", or "prompt"
    #[serde(default = "default_delete_mode")]
    pub delete_confirmation_mode: String,
}

/// Layout configuration for persistent preferences
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LayoutConfig {
    /// Task detail width as percentage (0-100)
    #[serde(default = "default_detail_width")]
    pub task_detail_width_percent: u16,
    /// Window width in characters
    #[serde(default)]
    pub window_width: u16,
    /// Window height in rows
    #[serde(default)]
    pub window_height: u16,
    /// Restore layout on startup
    #[serde(default = "default_restore_layout")]
    pub restore_on_startup: bool,
}

fn default_delete_mode() -> String {
    "modal".to_string()
}

fn default_detail_width() -> u16 {
    50
}

fn default_restore_layout() -> bool {
    true
}

impl Default for UiConfig {
    fn default() -> Self {
        Self {
            delete_confirmation_mode: default_delete_mode(),
        }
    }
}

impl Default for LayoutConfig {
    fn default() -> Self {
        Self {
            task_detail_width_percent: default_detail_width(),
            window_width: 0,
            window_height: 0,
            restore_on_startup: default_restore_layout(),
        }
    }
}

// Default values
fn default_theme() -> String {
    "default".to_string()
}

fn default_refresh_interval() -> u64 {
    250
}

fn default_api_base() -> String {
    "http://localhost:3000/api".to_string()
}

fn default_ws_url() -> String {
    "ws://localhost:3000/ws".to_string()
}

fn default_api_timeout() -> u64 {
    30
}

fn default_enable_sync() -> bool {
    true
}

fn default_sync_interval() -> u64 {
    5
}

impl Default for TuiConfig {
    fn default() -> Self {
        Self {
            app: AppConfig {
                theme: default_theme(),
                refresh_interval_ms: default_refresh_interval(),
                enable_plugins: false,
            },
            api: ApiConfig {
                base_url: default_api_base(),
                ws_url: default_ws_url(),
                timeout_secs: default_api_timeout(),
                enable_sync: default_enable_sync(),
                sync_interval_secs: default_sync_interval(),
            },
            features: FeaturesConfig::default(),
            ui: UiConfig::default(),
        }
    }
}

impl LayoutConfig {
    /// Load layout configuration from file
    pub fn load() -> Result<Self, Box<dyn std::error::Error>> {
        let config_path = std::path::PathBuf::from(".tui/layout.toml");
        if !config_path.exists() {
            return Ok(Self::default());
        }

        let content = std::fs::read_to_string(&config_path)?;
        let config: LayoutConfig = toml::from_str(&content)?;
        Ok(config)
    }

    /// Save layout configuration to file
    #[allow(dead_code)]
    pub fn save(&self) -> Result<(), Box<dyn std::error::Error>> {
        let config_dir = std::path::PathBuf::from(".tui");
        std::fs::create_dir_all(&config_dir)?;

        let config_path = config_dir.join("layout.toml");
        let content = toml::to_string_pretty(self)?;
        std::fs::write(config_path, content)?;
        Ok(())
    }
}

impl TuiConfig {
    /// Load configuration from file or environment
    pub fn load() -> Self {
        // Try to load from config file first
        if let Ok(config) = Self::load_from_file() {
            return config;
        }

        // Load from environment variables
        Self::load_from_env()
    }

    /// Load configuration from TOML file
    fn load_from_file() -> Result<Self, Box<dyn std::error::Error>> {
        let config_path = PathBuf::from(".tui/config.toml");
        if !config_path.exists() {
            return Err("Config file not found".into());
        }

        let content = std::fs::read_to_string(&config_path)?;
        let config: TuiConfig = toml::from_str(&content)?;
        tracing::info!("TUI config loaded from {}", config_path.display());
        Ok(config)
    }

    /// Load configuration from environment variables
    fn load_from_env() -> Self {
        let mut config = Self::default();

        // Override from environment variables
        if let Ok(theme) = std::env::var("TUI_THEME") {
            config.app.theme = theme;
        }
        if let Ok(refresh) = std::env::var("TUI_REFRESH_INTERVAL_MS") {
            if let Ok(r) = refresh.parse() {
                config.app.refresh_interval_ms = r;
            }
        }
        if let Ok(plugins) = std::env::var("TUI_ENABLE_PLUGINS") {
            config.app.enable_plugins = plugins.to_lowercase() == "true";
        }

        if let Ok(base_url) = std::env::var("API_BASE_URL") {
            config.api.base_url = base_url;
        }
        if let Ok(ws_url) = std::env::var("API_WS_URL") {
            config.api.ws_url = ws_url;
        }
        if let Ok(timeout) = std::env::var("API_TIMEOUT_SECS") {
            if let Ok(t) = timeout.parse() {
                config.api.timeout_secs = t;
            }
        }
        if let Ok(enable_sync) = std::env::var("ENABLE_SYNC") {
            config.api.enable_sync = enable_sync.to_lowercase() == "true";
        }

        tracing::info!("TUI config loaded from environment");
        config
    }

    /// Log configuration (mask sensitive values)
    pub fn log_config(&self) {
        tracing::info!("=== TUI Configuration ===");
        tracing::info!("Theme: {}", self.app.theme);
        tracing::info!("Refresh Interval: {}ms", self.app.refresh_interval_ms);
        tracing::info!("Plugins Enabled: {}", self.app.enable_plugins);
        tracing::info!("API Base URL: {}", self.api.base_url);
        tracing::info!(
            "WebSocket URL: {}",
            if self.api.ws_url.is_empty() {
                "(disabled)"
            } else {
                &self.api.ws_url
            }
        );
        tracing::info!("API Timeout: {}s", self.api.timeout_secs);
        tracing::info!("Real-time Sync: {}", self.api.enable_sync);
        if self.api.enable_sync {
            tracing::info!("Sync Interval: {}s", self.api.sync_interval_secs);
        }
        tracing::info!("Features: {:?}", self.features);
    }
}

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

    #[test]
    fn test_default_config() {
        let config = TuiConfig::default();
        assert_eq!(config.app.theme, "default");
        assert_eq!(config.api.base_url, "http://localhost:3000/api");
        assert!(config.api.enable_sync);
    }

    #[test]
    fn test_config_from_env() {
        std::env::set_var("TUI_THEME", "dark");
        std::env::set_var("API_BASE_URL", "http://localhost:3001/api");

        let config = TuiConfig::load_from_env();
        assert_eq!(config.app.theme, "dark");
        assert_eq!(config.api.base_url, "http://localhost:3001/api");
    }
}
