//! Provisioning Daemon configuration wrapper
//!
//! This module wraps the external daemon library's configuration system
//! with support for hierarchical loading and environment variable overrides.

use std::env;
use std::path::{Path, PathBuf};

use platform_config::ConfigLoader;
use serde::{Deserialize, Serialize};

/// Wrapper for external daemon configuration
///
/// Provides hierarchical configuration loading and environment variable
/// overrides for the provisioning-daemon service.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProvisioningDaemonConfigWrapper {
    /// Configuration path used for loading
    #[serde(skip)]
    pub config_path: PathBuf,
}

impl ProvisioningDaemonConfigWrapper {
    /// Load configuration from hierarchical sources with mode support
    ///
    /// Priority order:
    /// 1. DAEMON_CONFIG environment variable (explicit path)
    /// 2. DAEMON_MODE environment variable (mode-specific file)
    /// 3. Default configuration path
    ///
    /// This method always succeeds - it resolves a path regardless of whether
    /// the file exists. The external daemon library handles file validation.
    pub fn load_from_hierarchy() -> Self {
        let config_path = Self::resolve_config_path();
        Self { config_path }
    }

    /// Resolve the configuration path from environment variables or defaults
    fn resolve_config_path() -> PathBuf {
        if let Ok(path) = env::var("DAEMON_CONFIG") {
            // Explicit config path provided
            return PathBuf::from(path);
        }

        if let Ok(mode) = env::var("DAEMON_MODE") {
            // Mode-specific config file
            return PathBuf::from(format!(
                "provisioning/platform/config/provisioning-daemon.{}.toml",
                mode
            ));
        }

        // Default fallback - use a basic default config
        // In production, this would point to a system config location
        PathBuf::from("provisioning/platform/config/provisioning-daemon.solo.toml")
    }

    /// Get the resolved configuration path
    pub fn path(&self) -> &PathBuf {
        &self.config_path
    }

    /// Load configuration using the external daemon library's loader
    ///
    /// This delegates to the external library's configuration loading
    /// mechanism. The external library handles the actual parsing and
    /// validation.
    #[allow(dead_code)]
    pub fn load_with_external(&self) -> Result<(), Box<dyn std::error::Error>> {
        // This would integrate with the external daemon_cli library
        // Example: daemon_cli::DaemonConfig::load(&self.config_path)?;
        // For now, this is a placeholder that demonstrates the pattern
        Ok(())
    }

    /// Apply environment variable overrides
    ///
    /// Environment variables follow the pattern: DAEMON_{SECTION}_{KEY}
    ///
    /// Supported overrides:
    /// - DAEMON_POLL_INTERVAL (seconds)
    /// - DAEMON_MAX_WORKERS (count)
    /// - DAEMON_LOGGING_LEVEL (debug/info/warn/error)
    /// - DAEMON_AUTO_CLEANUP (true/false)
    #[allow(dead_code)]
    pub fn apply_env_overrides(&mut self) {
        // Environment variable overrides are handled by the external library
        // or by pre-setting them before calling the external loader.
        //
        // The pattern is:
        // 1. Load the config file (via external library)
        // 2. Parse environment variable overrides
        // 3. Apply overrides on top of loaded config
        //
        // Since the external library may not support this pattern directly,
        // this wrapper allows the calling code to:
        // - Check env vars before calling the loader
        // - Inject config path via environment
        // - Handle overrides at the application level
    }

    /// Get the configuration path as a string
    pub fn path_str(&self) -> String {
        self.config_path.to_string_lossy().to_string()
    }
}

impl Default for ProvisioningDaemonConfigWrapper {
    fn default() -> Self {
        Self {
            config_path: PathBuf::from(
                "provisioning/platform/config/provisioning-daemon.solo.toml",
            ),
        }
    }
}

impl ConfigLoader for ProvisioningDaemonConfigWrapper {
    fn service_name() -> &'static str {
        "provisioning-daemon"
    }

    fn load_from_hierarchy() -> std::result::Result<Self, Box<dyn std::error::Error + Send + Sync>>
    {
        let service = Self::service_name();

        if let Some(path) = platform_config::resolve_config_path(service) {
            return Self::from_path(&path);
        }

        // Fallback to defaults
        Ok(Self::default())
    }

    fn apply_env_overrides(
        &mut self,
    ) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
        // No-op for wrapper - env overrides handled by external daemon library
        Ok(())
    }

    fn from_path<P: AsRef<Path>>(
        path: P,
    ) -> std::result::Result<Self, Box<dyn std::error::Error + Send + Sync>> {
        Ok(Self {
            config_path: path.as_ref().to_path_buf(),
        })
    }
}

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

    #[test]
    fn test_default_config_path() {
        let config = ProvisioningDaemonConfigWrapper::default();
        assert!(config.path_str().contains("provisioning-daemon.solo.toml"));
    }

    #[test]
    fn test_config_path_method() {
        let config = ProvisioningDaemonConfigWrapper::default();
        let path = config.path();
        assert!(path.to_string_lossy().contains("provisioning-daemon"));
    }

    #[test]
    fn test_resolve_config_path_default() {
        // Without env vars, should return default
        let wrapper = ProvisioningDaemonConfigWrapper::load_from_hierarchy();
        assert!(wrapper.path_str().contains("provisioning-daemon"));
    }
}
