// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

use bollard::container::{ListContainersOptions, RemoveContainerOptions};
use std::collections::HashMap;

use bollard::network::ListNetworksOptions;
use bollard::Docker;

use crate::constants::{LABEL, LABEL_FILTER};
use crate::TestError;

/// Struct to manage the cleanup.
pub struct Cleanup {
    docker: Docker,
}

impl Cleanup {
    /// Create a new cleanup instance.
    pub fn new(docker: Docker) -> Self {
        Self { docker }
    }

    /// Purge the containers and networks.
    pub async fn purge(&self) -> Result<(), TestError> {
        self.purge_containers().await?;
        self.purge_networks().await
    }

    async fn purge_containers(&self) -> Result<(), TestError> {
        let containers = self
            .docker
            .list_containers(Some(ListContainersOptions {
                all: true,
                limit: None,
                size: false,
                filters: HashMap::from([(LABEL, vec![LABEL_FILTER])]),
            }))
            .await?;

        for id in containers.into_iter().filter_map(|cont| cont.id) {
            self.docker
                .remove_container(
                    &id,
                    Some(RemoveContainerOptions {
                        v: true,
                        force: true,
                        link: false,
                    }),
                )
                .await?;
        }

        Ok(())
    }

    async fn purge_networks(&self) -> Result<(), TestError> {
        let networks = self
            .docker
            .list_networks(Some(ListNetworksOptions {
                filters: HashMap::from([(LABEL, vec![LABEL_FILTER])]),
            }))
            .await?;

        for id in networks.into_iter().filter_map(|net| net.id) {
            self.docker.remove_network(&id).await?;
        }

        Ok(())
    }
}
