use crate::common::status::{StatusInfo, generate_status_info};
use crate::compression_engine::CompressionType;
use crate::config::Settings;
use crate::meta_plugin::MetaPluginType;
use crate::services::filter_service::get_available_filter_plugins;
use clap::Command;
use std::path::PathBuf;
use std::str::FromStr;

/// Service for generating system status information.
///
/// This service collects and formats status data about the application's
/// configuration, storage paths, compression engines, metadata plugins,
/// and filter plugins. It provides a unified interface for status reporting
/// used by both CLI and server modes.
///
/// # Examples
///
/// ```ignore
/// let service = StatusService::new();
/// let status = service.generate_status(&mut cmd, &settings, data_path, db_path);
/// ```
pub struct StatusService;

impl StatusService {
    /// Creates a new `StatusService` instance.
    ///
    /// No specific initialization is needed; it's a stateless service.
    ///
    /// # Returns
    ///
    /// * `StatusService` - A new instance.
    ///
    /// # Examples
    ///
    /// ```
    /// # use keep::services::StatusService;
    /// let service = StatusService::new();
    /// ```
    pub fn new() -> Self {
        Self
    }

    /// Generates comprehensive status information for the application.
    ///
    /// Collects data about paths, compression engines, available and configured
    /// meta plugins, and filter plugins. Uses the provided settings to determine
    /// enabled components. Handles error reporting via Clap if needed.
    ///
    /// # Arguments
    ///
    /// * `cmd` - Mutable reference to the Clap command for error reporting (e.g., invalid plugins).
    /// * `settings` - Application settings containing configuration details like enabled plugins.
    /// * `data_path` - Path to the data storage directory for item files.
    /// * `db_path` - Path to the SQLite database file.
    ///
    /// # Returns
    ///
    /// * `StatusInfo` - A structured object containing all status details, including paths, plugins, and config.
    ///
    /// # Errors
    ///
    /// Exits via Clap error if invalid meta plugin types are configured in settings.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// let status = service.generate_status(&mut cmd, &settings, data_path, db_path);
    /// assert!(!status.filter_plugins.is_empty());
    /// ```
    pub fn generate_status(
        &self,
        cmd: &mut Command,
        settings: &Settings,
        data_path: PathBuf,
        db_path: PathBuf,
    ) -> anyhow::Result<StatusInfo> {
        // Get meta plugins directly from config
        let meta_plugin_types: Vec<MetaPluginType> =
            crate::modes::common::settings_meta_plugin_types(cmd, settings);

        // Determine which compression type would be enabled for a save operation
        let enabled_compression_type = if let Some(compression_name) = &settings.compression() {
            CompressionType::from_str(compression_name).ok()
        } else {
            Some(crate::compression_engine::default_compression_type())
        };

        let mut status_info = generate_status_info(
            data_path,
            db_path,
            &meta_plugin_types,
            enabled_compression_type,
        )?;

        // Add detailed filter plugins information
        let filter_plugins_map = get_available_filter_plugins()?;
        let mut filter_plugins_info = Vec::new();

        for (name, creator) in filter_plugins_map {
            let plugin = creator();
            let options = plugin.options();
            // For now, use a default description
            let description = "Filter plugin".to_string();

            filter_plugins_info.push(crate::common::status::FilterPluginInfo {
                name,
                options,
                description,
            });
        }
        status_info.filter_plugins = filter_plugins_info;

        // Add configured meta plugins information
        status_info.configured_meta_plugins = settings.meta_plugins.clone();

        Ok(status_info)
    }
}

impl Default for StatusService {
    /// Returns the default `StatusService` instance.
    ///
    /// Delegates to `new()` for consistency.
    ///
    /// # Returns
    ///
    /// * `StatusService` - A new instance.
    fn default() -> Self {
        Self::new()
    }
}
