//! Common traits used across services
//!
//! This module provides shared traits that define common interfaces
//! for services in the Foxhunt HFT trading system.

use crate::error::CommonResult;
use crate::types::{ServiceStatus, Timestamp};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Trait for configurable components
#[async_trait]
pub trait Configurable {
    /// Configuration type for this component
    type Config: Clone + Send + Sync;

    /// Apply configuration changes
    async fn configure(&mut self, config: Self::Config) -> CommonResult<()>;

    /// Get current configuration
    fn get_config(&self) -> &Self::Config;

    /// Validate configuration before applying
    ///
    /// # Errors
    /// Returns error if the operation fails
    fn validate_config(config: &Self::Config) -> CommonResult<()>;
}

/// Trait for health check capabilities
#[async_trait]
pub trait HealthCheck {
    /// Perform a health check
    async fn health_check(&self) -> CommonResult<HealthStatus>;

    /// Get detailed health information
    async fn detailed_health(&self) -> CommonResult<DetailedHealth>;
}

/// Health status for components
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
    /// Overall health status
    pub status: ServiceStatus,
    /// Timestamp of the health check
    pub timestamp: Timestamp,
    /// Optional message
    pub message: Option<String>,
}

/// Detailed health information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DetailedHealth {
    /// Basic health status
    pub status: HealthStatus,
    /// Component-specific metrics
    pub metrics: HashMap<String, f64>,
    /// Sub-component health statuses
    pub components: HashMap<String, HealthStatus>,
}

/// Trait for metrics collection
pub trait Metrics {
    /// Metrics type for this component
    type Metrics: Clone + Send + Sync + Serialize;

    /// Get current metrics
    fn get_metrics(&self) -> Self::Metrics;

    /// Reset metrics counters
    fn reset_metrics(&mut self);
}

/// Trait for service lifecycle management
#[async_trait]
pub trait Service: Send + Sync {
    /// Start the service
    async fn start(&mut self) -> CommonResult<()>;

    /// Stop the service gracefully
    async fn stop(&mut self) -> CommonResult<()>;

    /// Get current service status
    fn status(&self) -> ServiceStatus;

    /// Get service name
    fn name(&self) -> &str;

    /// Get service version
    fn version(&self) -> &str;
}

/// Trait for components that can be reloaded
#[async_trait]
pub trait Reloadable {
    /// Reload the component (hot reload)
    async fn reload(&mut self) -> CommonResult<()>;

    /// Check if reload is supported
    fn supports_reload(&self) -> bool {
        true
    }
}

/// Trait for components with graceful shutdown
#[async_trait]
pub trait GracefulShutdown {
    /// Initiate graceful shutdown
    async fn shutdown(&mut self) -> CommonResult<()>;

    /// Force shutdown (emergency stop)
    async fn force_shutdown(&mut self) -> CommonResult<()>;

    /// Get shutdown timeout duration in seconds
    fn shutdown_timeout_seconds(&self) -> u64 {
        30 // Default 30 seconds
    }
}

/// Trait for components that support circuit breaking
pub trait CircuitBreaker {
    /// Check if circuit is open
    fn is_circuit_open(&self) -> bool;

    /// Get failure count
    fn failure_count(&self) -> u64;

    /// Reset circuit breaker
    fn reset_circuit(&mut self);
}

/// Trait for rate-limited operations
pub trait RateLimited {
    /// Check if operation is allowed under rate limits
    fn is_allowed(&self) -> bool;

    /// Get current rate limit status
    fn rate_limit_status(&self) -> RateLimitStatus;
}

/// Rate limit status information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimitStatus {
    /// Current request count in the window
    pub current_count: u64,
    /// Maximum requests allowed in the window
    pub max_requests: u64,
    /// Time window in seconds
    pub window_seconds: u64,
    /// Seconds until window resets
    pub reset_in_seconds: u64,
}
