use super::config::ContextConfig;
use std::future::Future;

/// Trait for test context setup structs.
///
/// This trait defines how to start all services in a test context.
/// Implementations typically:
/// 1. Construct the context from configuration
/// 2. Start each service sequentially
/// 3. Wait for each to become healthy before starting the next
/// 4. Return the running context with all services ready
///
/// # Example
///
/// ```rust,ignore
/// impl ContextSetup for MyContextSetup {
///     type Running = MyContextRunning;
///     type Error = ContextError;
///     type Config = MyContextConfig;
///     
///     fn construct(config: Self::Config) -> Self {
///         Self {
///             postgres: SqlxPostgresServiceSetup::construct(config.postgres),
///             redis: FredRedisServiceSetup::construct(config.redis),
///         }
///     }
///     
///     async fn start_all(self, config: &ContextConfig) -> Result<Self::Running, Self::Error> {
///         let postgres = self.postgres.start().await?;
///         wait_until_healthy_with_config(&postgres, config).await?;
///         
///         let redis = self.redis.start().await?;
///         wait_until_healthy_with_config(&redis, config).await?;
///         
///         Ok(MyContextRunning { postgres, redis })
///     }
/// }
/// ```
pub trait ContextSetup: Sized {
    /// The running version of this context (with all services started)
    type Running: ContextRunning;

    /// The error type returned by context operations
    type Error: std::error::Error + Send + Sync + 'static;

    /// Configuration needed to construct this context.
    /// Typically auto-generated by the `context!` macro from service configs.
    type Config;

    /// Construct a context setup from configuration.
    fn construct(config: Self::Config) -> Self;

    /// Start all services in the context sequentially.
    ///
    /// This method should use the provided config for health check parameters.
    fn start_all(
        self,
        config: &ContextConfig,
    ) -> impl Future<Output = Result<Self::Running, Self::Error>> + Send;
}

/// Trait for running test contexts.
///
/// This trait defines how to stop all services in a running context.
pub trait ContextRunning {
    /// The error type returned by context operations
    type Error: std::error::Error + Send + Sync + 'static;

    /// Stop all services in the context.
    ///
    /// This is typically called during test cleanup. Implementations should
    /// use best-effort cleanup: attempt to stop all services even if some
    /// fail, and log errors rather than propagating them.
    ///
    /// Takes `&mut self` to allow cleanup without consuming the context,
    /// enabling use in Drop implementations.
    fn stop_all(&mut self) -> impl Future<Output = Result<(), Self::Error>> + Send;
}
