pub trait MonitoringSystem {}

// 1. Modified AlertReceiver trait:
//    - Removed the problematic `clone` method.
//    - Added `box_clone` which returns a Box<dyn AlertReceiver>.
pub trait AlertReceiver {
    type M: MonitoringSystem;
    fn install(&self, sender: &Self::M) -> Result<(), String>;
    // This method allows concrete types to clone themselves into a Box<dyn AlertReceiver>
    fn box_clone(&self) -> Box<dyn AlertReceiver<M = Self::M>>;
}
#[derive(Clone)]
struct Prometheus{}
impl MonitoringSystem for Prometheus {}

#[derive(Clone)] // Keep derive(Clone) for DiscordWebhook itself
struct DiscordWebhook{}

impl AlertReceiver for DiscordWebhook {
    type M = Prometheus;
    fn install(&self, sender: &Self::M) -> Result<(), String> {
        // Placeholder for actual installation logic
        println!("DiscordWebhook installed for Prometheus monitoring.");
        Ok(())
    }
    // 2. Implement `box_clone` for DiscordWebhook:
    //    This uses the derived `Clone` for DiscordWebhook to create a new boxed instance.
    fn box_clone(&self) -> Box<dyn AlertReceiver<M = Self::M>> {
        Box::new(self.clone())
    }
}

// 3. Implement `std::clone::Clone` for `Box<dyn AlertReceiver<M= M>>`:
//    This allows `Box<dyn AlertReceiver>` to be cloned.
//    The `+ 'static` lifetime bound is often necessary for trait objects stored in collections,
//    ensuring they live long enough.
impl<M: MonitoringSystem + 'static> Clone for Box<dyn AlertReceiver<M= M>> {
    fn clone(&self) -> Self {
        self.box_clone() // Call the custom `box_clone` method
    }
}

// MonitoringConfig can now derive Clone because its `receivers` field
// (Vec<Box<dyn AlertReceiver<M = M>>>) is now cloneable.
#[derive(Clone)]
struct MonitoringConfig <M: MonitoringSystem + 'static>{
    receivers: Vec<Box<dyn AlertReceiver<M = M>>>
}

// Example usage to demonstrate compilation and functionality
fn main() {
    let prometheus_instance = Prometheus{};
    let discord_webhook_instance = DiscordWebhook{};

    let mut config = MonitoringConfig {
        receivers: Vec::new()
    };

    // Create a boxed alert receiver
    let boxed_receiver: Box<dyn AlertReceiver<M = Prometheus>> = Box::new(discord_webhook_instance);
    config.receivers.push(boxed_receiver);

    // Clone the config, which will now correctly clone the boxed receiver
    let cloned_config = config.clone();

    println!("Original config has {} receivers.", config.receivers.len());
    println!("Cloned config has {} receivers.", cloned_config.receivers.len());

    // Example of using the installed receiver
    if let Some(receiver) = config.receivers.get(0) {
        let _ = receiver.install(&prometheus_instance);
    }
}
