//! Common broker types and traits for trading system integration.
//!
//! This module provides the foundational types and traits for integrating with
//! various broker and trading platforms. It defines common interfaces for order
//! management, execution reporting, and broker connectivity.
//!
//! # Architecture
//!
//! ```text
//! ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
//! │  BrokerClient   │────│ TradingOrder    │────│ ExecutionReport │
//! │     (trait)     │    │                 │    │                 │
//! └─────────────────┘    └─────────────────┘    └─────────────────┘
//!          │                       │                       │
//!          ▼                       ▼                       ▼
//! ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
//! │ Implementation  │    │ Order Validation│    │ Trade Reporting │
//! │ (IB, ICMarkets) │    │ & Risk Checks   │    │ & Settlement    │
//! └─────────────────┘    └─────────────────┘    └─────────────────┘
//! ```
//!
//! # Usage
//!
//! ```rust
//! use data::brokers::common::{BrokerClient, TradingOrder, BrokerConfig};
//! use async_trait::async_trait;
//!
//! // Implement broker client for a specific platform
//! struct MyBroker {
//!     config: BrokerConfig,
//!     // ... connection state
//! }
//!
//! #[async_trait]
//! impl BrokerClient for MyBroker {
//!     async fn connect(&mut self) -> BrokerResult<()> {
//!         // Platform-specific connection logic
//!         Ok(())
//!     }
//!
//!     async fn submit_order(&self, order: &TradingOrder) -> BrokerResult<String> {
//!         // Platform-specific order submission
//!         Ok("order_123".to_string())
//!     }
//!
//!     // ... implement other required methods
//! }
//! ```

use ::common::{OrderSide, OrderStatus, OrderType, Position, TimeInForce};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use tokio::sync::mpsc;

/// Result type for broker operations with standardized error handling.
///
/// Provides a consistent return type for all broker operations, wrapping
/// success values with `BrokerError` for comprehensive error handling.
/// This enables uniform error propagation across all broker implementations.
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::{BrokerResult, BrokerError};
///
/// async fn connect_to_broker() -> BrokerResult<String> {
///     // Connection logic here
///     Ok("Connected successfully".to_string())
/// }
///
/// // Handle result
/// match connect_to_broker().await {
///     Ok(msg) => println!("Success: {}", msg),
///     Err(e) => eprintln!("Broker error: {}", e),
/// }
/// ```
pub type BrokerResult<T> = Result<T, BrokerError>;

/// Broker connection status enumeration.
///
/// Represents the current state of the connection between the trading system
/// and the broker platform. Used for monitoring connectivity, handling
/// reconnection logic, and ensuring reliable order flow.
///
/// # State Transitions
///
/// ```text
/// Disconnected → Connecting → Connected
///      ↑              ↓           ↓
///      └── Error ←────┴───────────┘
///      └── Reconnecting ←─────────┘
/// ```
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::BrokerConnectionStatus;
///
/// let status = BrokerConnectionStatus::Connected;
/// assert_eq!(status, BrokerConnectionStatus::Connected);
///
/// // Handle error states
/// let error_status = BrokerConnectionStatus::Error("Connection timeout".to_string());
/// match error_status {
///     BrokerConnectionStatus::Error(msg) => println!("Connection failed: {}", msg),
///     _ => {}
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BrokerConnectionStatus {
    /// Successfully connected to broker with active session
    ///
    /// All broker operations are available and the connection is stable.
    /// Orders can be submitted and market data is flowing.
    Connected,

    /// Disconnected from broker with no active session
    ///
    /// No broker operations are possible. This is the initial state
    /// and the state after a clean disconnect.
    Disconnected,

    /// Currently attempting to establish connection
    ///
    /// Connection is in progress. Some operations may be queued
    /// pending successful connection establishment.
    Connecting,

    /// Attempting to reconnect after connection failure
    ///
    /// Connection was lost and the system is trying to restore it.
    /// This includes implementing backoff strategies and retry logic.
    Reconnecting,

    /// Error state with detailed failure description
    ///
    /// Connection failed with a specific error. The error message
    /// provides context for debugging and recovery actions.
    Error(String),
}

impl Default for BrokerConnectionStatus {
    fn default() -> Self {
        Self::Disconnected
    }
}

/// Comprehensive broker error types for trading operations.
///
/// Categorizes all possible errors that can occur during broker interactions,
/// from connection issues to order execution failures. Each error type includes
/// descriptive context to aid in debugging and error handling.
///
/// # Error Categories
///
/// - **Connection**: Network and authentication issues
/// - **Order**: Trade execution and order management errors  
/// - **Market Data**: Data feed and subscription problems
/// - **Configuration**: Setup and parameter validation errors
/// - **Protocol**: Communication and message format issues
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::{BrokerError, BrokerResult};
///
/// fn process_order() -> BrokerResult<String> {
///     // Simulate order processing
///     Err(BrokerError::Order("Insufficient margin".to_string()))
/// }
///
/// match process_order() {
///     Ok(order_id) => println!("Order submitted: {}", order_id),
///     Err(BrokerError::Order(msg)) => eprintln!("Order failed: {}", msg),
///     Err(e) => eprintln!("Other error: {}", e),
/// }
/// ```
#[derive(Debug, thiserror::Error)]
pub enum BrokerError {
    /// General connection-related errors
    ///
    /// Covers network issues, socket errors, and connection state problems
    /// that don't fall into specific categories below.
    #[error("Connection error: {0}")]
    Connection(String),

    /// Connection establishment failures
    ///
    /// Specific to initial connection attempts that fail due to network
    /// issues, firewall blocks, or broker service unavailability.
    #[error("Connection failed: {0}")]
    ConnectionFailed(String),

    /// Authentication and authorization failures
    ///
    /// Invalid credentials, expired tokens, insufficient permissions,
    /// or account access restrictions.
    #[error("Authentication error: {0}")]
    Authentication(String),

    /// Order submission and management errors
    ///
    /// Includes order validation failures, rejection by broker,
    /// insufficient margin, and order lifecycle management issues.
    #[error("Order error: {0}")]
    Order(String),

    /// Market data subscription and feed errors
    ///
    /// Data feed interruptions, subscription failures, symbol resolution
    /// issues, and market data quality problems.
    #[error("Market data error: {0}")]
    MarketData(String),

    /// Configuration and setup errors
    ///
    /// Invalid configuration parameters, missing required settings,
    /// incompatible broker settings, and setup validation failures.
    #[error("Configuration error: {0}")]
    Configuration(String),

    /// Operation timeout errors
    ///
    /// Request timeouts, response delays, heartbeat failures,
    /// and connection keepalive issues.
    #[error("Timeout error: {0}")]
    Timeout(String),

    /// Message protocol and format errors
    ///
    /// Message parsing failures, protocol version mismatches,
    /// and communication format errors specific to broker APIs.
    #[error("Protocol error: {0}")]
    ProtocolError(String),

    /// Broker service unavailability
    ///
    /// Broker platform downtime, maintenance windows,
    /// or service capacity limitations.
    #[error("Broker not available: {0}")]
    BrokerNotAvailable(String),

    /// Method not yet implemented
    ///
    /// The requested functionality is not yet implemented for this broker.
    /// Used for stub implementations that need full integration work.
    #[error("Not implemented: {method} for broker {broker}")]
    NotImplemented {
        /// Name of the unimplemented method
        method: String,
        /// Name of the broker lacking this implementation
        broker: String,
    },

    /// Input/output system errors
    ///
    /// Low-level I/O errors from the operating system,
    /// network stack, or file system operations.
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    /// JSON serialization/deserialization errors
    ///
    /// Message format errors when converting between internal
    /// data structures and broker API JSON formats.
    #[error("Serialization error: {0}")]
    Serialization(#[from] serde_json::Error),
}

/// Enumeration of supported broker and trading platform types.
///
/// Identifies the specific broker platform being used for trade execution
/// and market data. Each broker type has its own implementation of the
/// `BrokerClient` trait with platform-specific connection and API logic.
///
/// # Supported Platforms
///
/// - **Interactive Brokers**: Professional trading platform with TWS API
/// - **ICMarkets**: Forex and CFD broker with `FIX` 4.4 protocol  
/// - **Alpaca**: Commission-free stock trading with REST API
/// - **Mock**: Simulated broker for testing and development
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::BrokerType;
///
/// let broker = BrokerType::InteractiveBrokers;
/// println!("Using broker: {}", broker);
///
/// // Configuration selection
/// let config = match broker {
///     BrokerType::InteractiveBrokers => { /* IB config */ },
///     BrokerType::ICMarkets => { /* ICM config */ },
///     BrokerType::Alpaca => { /* Alpaca config */ },
///     BrokerType::Mock => { /* Mock config */ },
/// };
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BrokerType {
    /// Interactive Brokers TWS (Trader Workstation) API
    ///
    /// Professional trading platform supporting equities, options, futures,
    /// forex, and bonds. Uses proprietary API protocol with real-time
    /// market data and advanced order types.
    InteractiveBrokers,

    /// ICMarkets `FIX` 4.4 protocol integration
    ///
    /// Forex and CFD broker using Financial Information eXchange (`FIX`)
    /// protocol for institutional-grade trading connectivity with
    /// low-latency execution.
    ICMarkets,

    /// Alpaca REST API for commission-free stock trading
    ///
    /// Cloud-based broker with REST API and WebSocket streaming.
    /// Focused on algorithmic trading with modern API design.
    Alpaca,

    /// Mock broker implementation for testing and development
    ///
    /// Simulated broker that mimics real broker behavior without
    /// actual trade execution. Used for backtesting and development.
    Mock,
}

impl Default for BrokerType {
    fn default() -> Self {
        Self::Mock
    }
}

impl std::fmt::Display for BrokerType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            BrokerType::InteractiveBrokers => write!(f, "InteractiveBrokers"),
            BrokerType::ICMarkets => write!(f, "ICMarkets"),
            BrokerType::Alpaca => write!(f, "Alpaca"),
            BrokerType::Mock => write!(f, "Mock"),
        }
    }
}

/// Comprehensive broker configuration container.
///
/// Contains all settings required to establish and maintain a connection
/// with a specific broker platform. Includes connection parameters,
/// trading limits, risk controls, and operational settings.
///
/// # Configuration Sections
///
/// - **Connection**: Network and authentication settings
/// - **Trading**: Order limits and symbol restrictions  
/// - **Risk**: Loss limits and safety controls
/// - **Operational**: Timeouts, retries, and feature flags
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::{BrokerConfig, BrokerType};
///
/// let config = BrokerConfig {
///     broker_type: BrokerType::InteractiveBrokers,
///     enabled: true,
///     ..Default::default()
/// };
///
/// // Validate configuration before use
/// if config.enabled && config.connection.timeout_seconds > 0 {
///     // Configuration is ready for use
/// }
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerConfig {
    /// Type of broker platform to connect to
    ///
    /// Determines which broker implementation will be used and
    /// affects the connection protocol and API calls.
    pub broker_type: BrokerType,

    /// Network connection and authentication configuration
    ///
    /// Contains host, port, credentials, timeouts, and retry settings
    /// needed to establish and maintain the broker connection.
    pub connection: BrokerConnectionConfig,

    /// Trading operational parameters and limits
    ///
    /// Defines order size limits, allowed symbols, timeouts,
    /// and other trading-specific operational constraints.
    pub trading: BrokerTradingConfig,

    /// Risk management and safety control settings
    ///
    /// Contains loss limits, position limits, kill switch settings,
    /// and other risk control parameters.
    pub risk: BrokerRiskConfig,

    /// Whether this broker configuration is active
    ///
    /// When false, this broker will be skipped during initialization.
    /// Useful for temporarily disabling brokers without removing config.
    pub enabled: bool,
}

impl Default for BrokerConfig {
    fn default() -> Self {
        Self {
            broker_type: BrokerType::Mock,
            connection: BrokerConnectionConfig::default(),
            trading: BrokerTradingConfig::default(),
            risk: BrokerRiskConfig::default(),
            enabled: false,
        }
    }
}

/// Network connection and authentication configuration for broker platforms.
///
/// Contains all parameters required to establish and maintain a stable
/// connection with a broker's trading API, including network settings,
/// authentication credentials, and connection management options.
///
/// # Security Considerations
///
/// - Credentials should be stored securely and never logged
/// - Use paper trading mode for development and testing
/// - Configure appropriate timeouts to prevent hanging connections
/// - Implement retry logic with exponential backoff
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::{BrokerConnectionConfig, BrokerCredentials};
/// use std::collections::HashMap;
///
/// let config = BrokerConnectionConfig {
///     host: "api.broker.com".to_string(),
///     port: 7497,
///     client_id: 1001,
///     timeout_seconds: 30,
///     retry_attempts: 3,
///     paper_trading: true, // Safe for testing
///     credentials: Some(BrokerCredentials {
///         api_key: "your_api_key".to_string(),
///         api_secret: Some("your_secret".to_string()),
///         extra: HashMap::new(),
///     }),
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerConnectionConfig {
    /// Hostname or IP address of the broker server
    ///
    /// The network address where the broker's trading API is hosted.
    /// Examples: "127.0.0.1", "api.interactivebrokers.com", "api.alpaca.markets"
    pub host: String,

    /// TCP port number for the broker connection
    ///
    /// Standard ports vary by broker:
    /// - Interactive Brokers: 7497 (paper), 7496 (live)
    /// - ICMarkets `FIX`: 443 (SSL), 4001 (non-SSL)
    /// - Alpaca: 443 (HTTPS/WSS)
    pub port: u16,

    /// Unique client identifier for this connection
    ///
    /// Used by the broker to distinguish between multiple client connections
    /// from the same account. Should be unique per trading session.
    pub client_id: u32,

    /// Maximum time to wait for connection establishment (seconds)
    ///
    /// How long to wait for initial connection before timing out.
    /// Recommended: 30-60 seconds for most brokers.
    pub timeout_seconds: u64,

    /// Number of connection retry attempts on failure
    ///
    /// How many times to retry connection before giving up.
    /// Recommended: 3-5 attempts with exponential backoff.
    pub retry_attempts: u32,

    /// Enable paper trading mode for safe testing
    ///
    /// When true, connects to broker's simulation environment.
    /// All trades are simulated without real money impact.
    /// ALWAYS use true for development and testing.
    pub paper_trading: bool,

    /// Optional authentication credentials
    ///
    /// Required for most brokers. Contains API keys, tokens,
    /// or other authentication information. Should be None
    /// for brokers that use alternative auth methods.
    pub credentials: Option<BrokerCredentials>,
}

impl Default for BrokerConnectionConfig {
    fn default() -> Self {
        Self {
            host: "127.0.0.1".to_owned(),
            port: 7497,
            client_id: 1,
            timeout_seconds: 30,
            retry_attempts: 3,
            paper_trading: true,
            credentials: None,
        }
    }
}

/// Authentication credentials for broker API access.
///
/// Contains sensitive authentication information required to access
/// broker trading APIs. Should be handled securely and never exposed
/// in logs or debug output.
///
/// # Security Best Practices
///
/// - Store credentials in secure configuration management
/// - Use environment variables or encrypted config files
/// - Never commit credentials to version control
/// - Rotate API keys regularly
/// - Use paper trading credentials for development
///
/// # Broker-Specific Usage
///
/// - **Interactive Brokers**: Usually no credentials needed (uses TWS login)
/// - **Alpaca**: api_key = Key ID, api_secret = Secret Key
/// - **ICMarkets**: api_key = Username, api_secret = Password
/// - **Mock**: Credentials ignored
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::BrokerCredentials;
/// use std::collections::HashMap;
///
/// // Alpaca credentials
/// let alpaca_creds = BrokerCredentials {
///     api_key: "PK...".to_string(),
///     api_secret: Some("...".to_string()),
///     extra: HashMap::new(),
/// };
///
/// // ICMarkets with additional `FIX` parameters
/// let mut extra = HashMap::new();
/// extra.insert("SenderCompID".to_string(), "YOUR_SENDER_ID".to_string());
/// let icm_creds = BrokerCredentials {
///     api_key: "username".to_string(),
///     api_secret: Some("password".to_string()),
///     extra,
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerCredentials {
    /// Primary API key, username, or public identifier
    ///
    /// The public part of the authentication credentials.
    /// For API-based brokers, this is typically the API key ID.
    /// For traditional brokers, this may be the username.
    pub api_key: String,

    /// Secret key, password, or private authentication token
    ///
    /// The private part of the authentication credentials.
    /// Should be treated as highly sensitive information.
    /// Optional for brokers that use single-factor auth.
    pub api_secret: Option<String>,

    /// Additional broker-specific authentication parameters
    ///
    /// Extra fields required by specific broker implementations:
    /// - `FIX` protocol: SenderCompID, TargetCompID, etc.
    /// - OAuth: refresh_token, scope, etc.
    /// - Custom: Any broker-specific auth fields
    pub extra: HashMap<String, String>,
}

/// Trading operational limits and constraints configuration.
///
/// Defines operational parameters that control trading behavior,
/// including position limits, order constraints, timeouts, and
/// symbol restrictions. These settings provide safety guardrails
/// and ensure compliance with risk management policies.
///
/// # Risk Management
///
/// - Order size limits prevent accidental large orders
/// - Position limits control overall exposure
/// - Symbol restrictions limit trading universe
/// - Timeouts prevent hanging orders
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::BrokerTradingConfig;
///
/// let config = BrokerTradingConfig {
///     max_order_size: 1000.0,     // Max 1000 shares per order
///     max_position_size: 10000.0, // Max 10000 share position
///     order_timeout_seconds: 30,  // 30 second order timeout
///     min_order_size: 1.0,        // Minimum 1 share orders
///     allowed_symbols: vec![
///         "AAPL".to_string(),
///         "GOOGL".to_string(),
///         "MSFT".to_string(),
///     ],
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerTradingConfig {
    /// Maximum size allowed for any single order
    ///
    /// Prevents accidental submission of excessively large orders.
    /// Units depend on the instrument (shares, contracts, lots).
    /// Should be set based on account size and risk tolerance.
    pub max_order_size: f64,

    /// Maximum total position size for any single symbol
    ///
    /// Limits overall exposure to prevent concentration risk.
    /// Includes both long and short positions (absolute value).
    /// Should align with portfolio risk management strategy.
    pub max_position_size: f64,

    /// Timeout for order acknowledgment from broker (seconds)
    ///
    /// How long to wait for broker confirmation before considering
    /// an order submission failed. Prevents hanging orders that
    /// could cause position tracking issues.
    pub order_timeout_seconds: u64,

    /// Minimum order size to prevent dust orders
    ///
    /// Smallest allowable order size to prevent creation of
    /// economically insignificant positions that may incur
    /// disproportionate fees or cause execution issues.
    pub min_order_size: f64,

    /// Whitelist of symbols permitted for trading
    ///
    /// Restricts trading to a predefined universe of symbols.
    /// Empty list means all symbols are allowed (use with caution).
    /// Helps prevent trading in illiquid or unsuitable instruments.
    pub allowed_symbols: Vec<String>,
}

impl Default for BrokerTradingConfig {
    fn default() -> Self {
        Self {
            max_order_size: 10000.0,
            max_position_size: 50000.0,
            order_timeout_seconds: 30,
            min_order_size: 1.0,
            allowed_symbols: vec![
                "EURUSD".to_owned(),
                "GBPUSD".to_owned(),
                "USDJPY".to_owned(),
            ],
        }
    }
}

/// Risk management and safety control configuration.
///
/// Contains critical risk parameters that protect against excessive
/// losses and ensure safe trading operations. These controls act as
/// circuit breakers to prevent catastrophic losses from algorithm
/// malfunctions or market anomalies.
///
/// # Risk Controls
///
/// - **Loss Limits**: Daily loss thresholds that trigger shutdown
/// - **Volume Limits**: Maximum daily trading volume constraints
/// - **Kill Switch**: Emergency stop mechanism for all trading
/// - **Timeouts**: Risk check performance requirements
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::BrokerRiskConfig;
///
/// let config = BrokerRiskConfig {
///     max_daily_loss: 5000.0,        // Stop at $5k daily loss
///     max_daily_volume: 1000000.0,   // Max $1M daily volume
///     kill_switch_enabled: true,     // Enable emergency stop
///     risk_check_timeout_ms: 100,    // 100ms risk check limit
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrokerRiskConfig {
    /// Maximum allowable daily loss before trading halt
    ///
    /// When daily P&L drops below this threshold (negative value),
    /// all trading activity will be automatically suspended.
    /// Should be set to a loss level the account can absorb.
    pub max_daily_loss: f64,

    /// Maximum daily trading volume limit
    ///
    /// Total dollar volume of trades allowed per day across all symbols.
    /// Prevents excessive turnover and helps control transaction costs.
    /// Trading halts when this limit is exceeded.
    pub max_daily_volume: f64,

    /// Enable emergency kill switch functionality
    ///
    /// When true, allows immediate shutdown of all trading operations
    /// via emergency stop commands. Critical safety feature that
    /// should typically remain enabled in production.
    pub kill_switch_enabled: bool,

    /// Maximum time allowed for risk checks (milliseconds)
    ///
    /// Risk validation must complete within this timeframe or
    /// the operation will be rejected. Prevents slow risk checks
    /// from affecting trading latency.
    pub risk_check_timeout_ms: u64,
}

impl Default for BrokerRiskConfig {
    fn default() -> Self {
        Self {
            max_daily_loss: 5000.0,
            max_daily_volume: 1000000.0,
            kill_switch_enabled: true,
            risk_check_timeout_ms: 100,
        }
    }
}

/// Execution report containing trade confirmation details from broker.
///
/// Comprehensive record of a completed trade execution, including all
/// relevant details such as fill price, quantity, timing, fees, and
/// order status. Used for trade reconciliation, P&L calculation,
/// and regulatory reporting.
///
/// # Contents
///
/// - **Identification**: Order ID, symbol, broker reference
/// - **Execution Details**: Price, quantity, side, timestamp
/// - **Costs**: Commission, fees, and other charges
/// - **Status**: Current order status after execution
///
/// # Usage
///
/// ```rust
/// use data::brokers::common::ExecutionReport;
/// use common::{OrderSide, OrderStatus};
///
/// let execution = ExecutionReport {
///     order_id: "ORD_123456".to_string(),
///     symbol: "AAPL".to_string(),
///     side: OrderSide::Buy,
///     executed_price: 150.25,
///     executed_quantity: 100.0,
///     timestamp_ns: 1640995200000000000, // Unix timestamp in nanoseconds
///     broker_id: "IB_REF_789".to_string(),
///     commission: 1.00,
///     fee: 0.02,
///     status: OrderStatus::Filled,
/// };
///
/// // Calculate total execution cost
/// let gross_value = execution.executed_price * execution.executed_quantity;
/// let total_cost = gross_value + execution.commission + execution.fee;
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionReport {
    /// Internal order identifier from trading system
    ///
    /// The order ID assigned by our trading system when the order
    /// was originally submitted. Used to match executions with orders.
    pub order_id: String,

    /// Symbol of the executed security
    ///
    /// Standard symbol identifier for the instrument that was traded.
    pub symbol: String,

    /// Side of the executed trade (Buy/Sell)
    ///
    /// Indicates whether this was a buy or sell execution.
    pub side: OrderSide,

    /// Price at which the trade was executed
    ///
    /// The actual fill price achieved by the broker, which may differ
    /// from the order's limit price due to market conditions.
    pub executed_price: f64,

    /// Quantity of shares/contracts executed
    ///
    /// The number of units that were actually filled. May be partial
    /// if the order was only partially executed.
    pub executed_quantity: f64,

    /// Execution timestamp in nanoseconds since Unix epoch
    ///
    /// High-precision timestamp of when the trade occurred at the exchange.
    /// Used for accurate latency measurement and trade sequencing.
    pub timestamp_ns: u64,

    /// Broker's internal reference identifier
    ///
    /// The broker's own identifier for this execution, used for
    /// reconciliation with broker statements and support requests.
    pub broker_id: String,

    /// Commission charged by the broker
    ///
    /// The broker's commission fee for this execution.
    /// Typically charged per share or as a percentage of trade value.
    pub commission: f64,

    /// Additional trading fees and charges
    ///
    /// Other fees such as exchange fees, clearing fees, regulatory fees,
    /// or other charges associated with this execution.
    pub fee: f64,

    /// Current status of the order after this execution
    ///
    /// Updated order status (Filled, PartiallyFilled, etc.) reflecting
    /// the state of the order after this execution event.
    pub status: OrderStatus,
}

/// Trading order structure for submission to broker platforms.
///
/// Standardized order representation that contains all necessary
/// information for trade execution across different broker platforms.
/// Supports various order types, time-in-force options, and
/// platform-specific parameters.
///
/// # Order Types Supported
///
/// - **Market**: Execute immediately at best available price
/// - **Limit**: Execute only at specified price or better
/// - **Stop**: Trigger market order when stop price is reached
/// - **StopLimit**: Trigger limit order when stop price is reached
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::TradingOrder;
/// use common::{OrderSide, OrderType, TimeInForce};
///
/// // Market buy order
/// let market_order = TradingOrder {
///     order_id: "ORD_001".to_string(),
///     symbol: "AAPL".to_string(),
///     side: OrderSide::Buy,
///     order_type: OrderType::Market,
///     quantity: 100.0,
///     price: None,
///     stop_price: None,
///     time_in_force: TimeInForce::Day,
///     client_order_id: Some("CLIENT_001".to_string()),
/// };
///
/// // Limit sell order
/// let limit_order = TradingOrder {
///     order_id: "ORD_002".to_string(),
///     symbol: "GOOGL".to_string(),
///     side: OrderSide::Sell,
///     order_type: OrderType::Limit,
///     quantity: 50.0,
///     price: Some(2500.00),
///     stop_price: None,
///     time_in_force: TimeInForce::GoodTillCancel,
///     client_order_id: None,
/// };
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradingOrder {
    /// Unique identifier for this order
    ///
    /// Internal order ID assigned by the trading system.
    /// Used to track order lifecycle and match with executions.
    pub order_id: String,

    /// Symbol of the security to trade
    ///
    /// Standard symbol identifier for the target instrument.
    pub symbol: String,

    /// Side of the order (Buy/Sell)
    ///
    /// Specifies whether this is a buy or sell order.
    pub side: OrderSide,

    /// Type of order execution logic
    ///
    /// Determines how the order should be executed (Market, Limit, Stop, etc.).
    pub order_type: OrderType,

    /// Number of shares/contracts to trade
    ///
    /// The quantity of the security to buy or sell.
    pub quantity: f64,

    /// Limit price for limit and stop-limit orders
    ///
    /// For limit orders: maximum buy price or minimum sell price.
    /// For stop-limit orders: limit price after stop is triggered.
    /// Not used for market or stop orders.
    pub price: Option<f64>,

    /// Stop trigger price for stop and stop-limit orders
    ///
    /// Price that triggers the order execution.
    /// For stop orders: triggers market order.
    /// For stop-limit orders: triggers limit order.
    /// Not used for market or limit orders.
    pub stop_price: Option<f64>,

    /// Order duration and cancellation policy
    ///
    /// Specifies how long the order remains active:
    /// - Day: Cancel at end of trading day
    /// - GTC: Good Till Canceled (manual cancellation required)
    /// - IOC: Immediate Or Cancel
    /// - FOK: Fill Or Kill
    pub time_in_force: TimeInForce,

    /// Optional client-assigned order identifier
    ///
    /// Custom identifier that can be used by the client for
    /// order tracking and reconciliation purposes.
    pub client_order_id: Option<String>,
}

impl TradingOrder {
    /// Convert from common::Order to TradingOrder
    pub fn from_common_order(order: &::common::Order) -> Result<Self, BrokerError> {
        Ok(TradingOrder {
            order_id: uuid::Uuid::new_v4().to_string(),
            symbol: order.symbol.to_string(),
            side: order.side,
            order_type: order.order_type,
            quantity: order.quantity.to_f64(),
            price: order.price.as_ref().map(|p| p.to_f64()),
            stop_price: order.stop_price.as_ref().map(|p| p.to_f64()),
            time_in_force: order.time_in_force,
            client_order_id: None,
        })
    }
}

/// Common interface for all broker client implementations.
///
/// Defines the standard operations that all broker clients must support,
/// providing a uniform API for order management, account information,
/// and connection handling across different broker platforms.
///
/// # Implementation Requirements
///
/// All broker clients must implement:
/// - **Connection Management**: Connect, disconnect, status monitoring
/// - **Order Operations**: Submit, cancel, modify orders
/// - **Account Access**: Get account info, positions, balances
/// - **Execution Reporting**: Subscribe to trade confirmations
/// - **Health Monitoring**: Heartbeat, reconnection, status checks
///
/// # Thread Safety
///
/// All implementations must be thread-safe (Send + Sync) to support
/// concurrent access from multiple trading strategies and monitoring systems.
///
/// # Error Handling
///
/// All methods return `BrokerResult<T>` for consistent error handling
/// across all broker implementations.
///
/// # Examples
///
/// ```rust
/// use data::brokers::common::{BrokerClient, TradingOrder, BrokerResult};
/// use async_trait::async_trait;
///
/// struct MyBrokerClient {
///     // Implementation-specific fields
/// }
///
/// #[async_trait]
/// impl BrokerClient for MyBrokerClient {
///     async fn connect(&mut self) -> BrokerResult<()> {
///         // Establish connection to broker
///         Ok(())
///     }
///
///     async fn submit_order(&self, order: &TradingOrder) -> BrokerResult<String> {
///         // Submit order to broker
///         Ok("broker_order_id".to_string())
///     }
///
///     // ... implement other required methods
/// }
/// ```
#[async_trait]
pub trait BrokerClient: Send + Sync {
    /// Establish connection to the broker platform.
    ///
    /// Initiates the connection process including authentication,
    /// session establishment, and any required initialization.
    /// Must be called before any trading operations.
    ///
    /// # Returns
    ///
    /// - `Ok(())` if connection is successfully established
    /// - `Err(BrokerError)` if connection fails with details
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(mut client: impl BrokerClient) -> BrokerResult<()> {
    /// client.connect().await?;
    /// assert!(client.is_connected());
    /// # Ok(())
    /// # }
    /// ```
    async fn connect(&mut self) -> BrokerResult<()>;

    /// Gracefully disconnect from the broker platform.
    ///
    /// Cleanly closes the connection, cancels any pending orders
    /// if required by the broker, and releases resources.
    /// Should be called before shutting down the trading system.
    ///
    /// # Returns
    ///
    /// - `Ok(())` if disconnection is successful
    /// - `Err(BrokerError)` if disconnection encounters issues
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(mut client: impl BrokerClient) -> BrokerResult<()> {
    /// client.disconnect().await?;
    /// assert!(!client.is_connected());
    /// # Ok(())
    /// # }
    /// ```
    async fn disconnect(&mut self) -> BrokerResult<()>;

    /// Check current connection status to the broker.
    ///
    /// Returns whether the client is currently connected and
    /// able to perform trading operations. Does not perform
    /// a network check, only returns cached connection state.
    ///
    /// # Returns
    ///
    /// `true` if connected and ready for operations, `false` otherwise.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::BrokerClient;
    /// # fn example(client: &impl BrokerClient) {
    /// if client.is_connected() {
    ///     // Safe to submit orders
    /// } else {
    ///     // Need to connect first
    /// }
    /// # }
    /// ```
    fn is_connected(&self) -> bool;

    /// Get the human-readable name of this broker platform.
    ///
    /// Returns a static string identifying the broker type,
    /// useful for logging, monitoring, and user interfaces.
    ///
    /// # Returns
    ///
    /// String slice with broker name (e.g., "InteractiveBrokers", "Alpaca").
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::BrokerClient;
    /// # fn example(client: &impl BrokerClient) {
    /// println!("Using broker: {}", client.broker_name());
    /// # }
    /// ```
    fn broker_name(&self) -> &str;

    /// Get detailed connection status information.
    ///
    /// Returns the current connection state with additional context
    /// such as error messages for failed connections or reconnection
    /// status during recovery attempts.
    ///
    /// # Returns
    ///
    /// `BrokerConnectionStatus` enum with current state details.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerConnectionStatus};
    /// # fn example(client: &impl BrokerClient) {
    /// match client.connection_status() {
    ///     BrokerConnectionStatus::Connected => {
    ///         // Ready for trading
    ///     },
    ///     BrokerConnectionStatus::Error(msg) => {
    ///         eprintln!("Connection error: {}", msg);
    ///     },
    ///     _ => {
    ///         // Handle other states
    ///     }
    /// }
    /// # }
    /// ```
    fn connection_status(&self) -> BrokerConnectionStatus;

    /// Submit a trading order to the broker for execution.
    ///
    /// Validates the order parameters, performs risk checks,
    /// and submits the order to the broker platform for execution.
    /// Returns the broker's order ID for tracking purposes.
    ///
    /// # Parameters
    ///
    /// * `order` - The trading order to submit
    ///
    /// # Returns
    ///
    /// - `Ok(String)` with broker's order ID if submission succeeds
    /// - `Err(BrokerError)` if validation fails or submission is rejected
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, TradingOrder, BrokerResult};
    /// # use common::{OrderSide, OrderType, TimeInForce};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// let order = TradingOrder {
    ///     order_id: "ORD_001".to_string(),
    ///     symbol: "AAPL".to_string(),
    ///     side: OrderSide::Buy,
    ///     order_type: OrderType::Market,
    ///     quantity: 100.0,
    ///     // ... other fields
    /// #   price: None,
    /// #   stop_price: None,
    /// #   time_in_force: TimeInForce::Day,
    /// #   client_order_id: None,
    /// };
    ///
    /// let broker_order_id = client.submit_order(&order).await?;
    /// println!("Order submitted with ID: {}", broker_order_id);
    /// # Ok(())
    /// # }
    /// ```
    async fn submit_order(&self, order: &TradingOrder) -> BrokerResult<String>;

    /// Cancel an existing order.
    ///
    /// Attempts to cancel an order that was previously submitted.
    /// Success depends on the order's current state and broker capabilities.
    /// Orders that are already filled cannot be canceled.
    ///
    /// # Parameters
    ///
    /// * `order_id` - The order ID to cancel (from submit_order)
    ///
    /// # Returns
    ///
    /// - `Ok(())` if cancellation request is accepted
    /// - `Err(BrokerError)` if cancellation fails or order not found
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// let order_id = "broker_order_123";
    /// client.cancel_order(order_id).await?;
    /// println!("Order {} canceled", order_id);
    /// # Ok(())
    /// # }
    /// ```
    async fn cancel_order(&self, order_id: &str) -> BrokerResult<()>;

    /// Modify parameters of an existing order.
    ///
    /// Updates order parameters such as quantity, price, or time-in-force
    /// for an order that has not yet been filled. Not all brokers support
    /// order modification; some require cancel-and-replace.
    ///
    /// # Parameters
    ///
    /// * `order_id` - The order ID to modify
    /// * `new_order` - New order parameters to apply
    ///
    /// # Returns
    ///
    /// - `Ok(())` if modification is accepted
    /// - `Err(BrokerError)` if modification fails or is not supported
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, TradingOrder, BrokerResult};
    /// # async fn example(client: &impl BrokerClient, order_id: &str, new_order: TradingOrder) -> BrokerResult<()> {
    /// client.modify_order(order_id, &new_order).await?;
    /// println!("Order {} modified", order_id);
    /// # Ok(())
    /// # }
    /// ```
    async fn modify_order(&self, order_id: &str, new_order: &TradingOrder) -> BrokerResult<()>;

    /// Query the current status of an order.
    ///
    /// Retrieves the latest status information for an order,
    /// including fill status, remaining quantity, and any
    /// rejection reasons.
    ///
    /// # Parameters
    ///
    /// * `order_id` - The order ID to query
    ///
    /// # Returns
    ///
    /// - `Ok(OrderStatus)` with current order state
    /// - `Err(BrokerError)` if query fails or order not found
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # use common::OrderStatus;
    /// # async fn example(client: &impl BrokerClient, order_id: &str) -> BrokerResult<()> {
    /// let status = client.get_order_status(order_id).await?;
    /// match status {
    ///     OrderStatus::Filled => println!("Order completed"),
    ///     OrderStatus::PartiallyFilled => println!("Order partially filled"),
    ///     OrderStatus::Rejected => println!("Order was rejected"),
    ///     _ => println!("Order status: {:?}", status),
    /// }
    /// # Ok(())
    /// # }
    /// ```
    async fn get_order_status(&self, order_id: &str) -> BrokerResult<OrderStatus>;

    /// Retrieve current account information and balances.
    ///
    /// Fetches account-level information including cash balances,
    /// buying power, margin requirements, and other account metrics.
    /// The returned data format may vary by broker.
    ///
    /// # Returns
    ///
    /// - `Ok(HashMap)` with account information key-value pairs
    /// - `Err(BrokerError)` if account query fails
    ///
    /// # Common Keys
    ///
    /// - "cash_balance": Available cash
    /// - "buying_power": Available buying power
    /// - "total_equity": Net liquidation value
    /// - "margin_requirements": Current margin requirements
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// let account_info = client.get_account_info().await?;
    /// if let Some(cash) = account_info.get("cash_balance") {
    ///     println!("Available cash: {}", cash);
    /// }
    /// # Ok(())
    /// # }
    /// ```
    async fn get_account_info(&self) -> BrokerResult<HashMap<String, String>>;

    /// Retrieve current positions for the account.
    ///
    /// Returns a list of all open positions, optionally filtered
    /// by symbol. Includes position size, average cost, market value,
    /// and unrealized P&L for each position.
    ///
    /// # Parameters
    ///
    /// * `symbol` - Optional symbol filter; if None, returns all positions
    ///
    /// # Returns
    ///
    /// - `Ok(Vec<Position>)` with current positions
    /// - `Err(BrokerError)` if position query fails
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// // Get all positions
    /// let all_positions = client.get_positions(None).await?;
    /// println!("Total positions: {}", all_positions.len());
    ///
    /// // Get positions for specific symbol
    /// let aapl_positions = client.get_positions(Some("AAPL")).await?;
    /// for position in aapl_positions {
    ///     println!("AAPL position: {} shares", position.size);
    /// }
    /// # Ok(())
    /// # }
    /// ```
    async fn get_positions(&self, symbol: Option<&str>) -> BrokerResult<Vec<Position>>;

    /// Subscribe to real-time execution reports.
    ///
    /// Establishes a stream of execution reports that will receive
    /// notifications for all trade executions on this account.
    /// Essential for real-time position tracking and P&L calculation.
    ///
    /// # Returns
    ///
    /// - `Ok(Receiver<ExecutionReport>)` for receiving execution reports
    /// - `Err(BrokerError)` if subscription setup fails
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// let mut execution_stream = client.subscribe_to_executions().await?;
    ///
    /// tokio::spawn(async move {
    ///     while let Some(execution) = execution_stream.recv().await {
    ///         println!("Trade executed: {} {} @ {}",
    ///                  execution.symbol,
    ///                  execution.executed_quantity,
    ///                  execution.executed_price);
    ///     }
    /// });
    /// # Ok(())
    /// # }
    /// ```
    async fn subscribe_to_executions(&self) -> BrokerResult<mpsc::Receiver<ExecutionReport>>;

    /// Subscribe to executions (alias for compatibility).
    ///
    /// Convenience method that calls `subscribe_to_executions()`.
    /// Provided for backward compatibility with existing code.
    ///
    /// # Returns
    ///
    /// Same as `subscribe_to_executions()`.
    async fn subscribe_executions(&self) -> BrokerResult<mpsc::Receiver<ExecutionReport>> {
        self.subscribe_to_executions().await
    }

    /// Send heartbeat message to maintain connection.
    ///
    /// Sends a keepalive message to the broker to prevent
    /// connection timeouts during periods of low activity.
    /// Should be called periodically (typically every 30-60 seconds).
    ///
    /// # Returns
    ///
    /// - `Ok(())` if heartbeat is successfully sent
    /// - `Err(BrokerError)` if heartbeat fails (may indicate connection issues)
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// // Send periodic heartbeat
    /// tokio::spawn(async move {
    ///     let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(30));
    ///     loop {
    ///         interval.tick().await;
    ///         if let Err(e) = client.send_heartbeat().await {
    ///             eprintln!("Heartbeat failed: {}", e);
    ///             break;
    ///         }
    ///     }
    /// });
    /// # Ok(())
    /// # }
    /// ```
    async fn send_heartbeat(&self) -> BrokerResult<()>;

    /// Attempt to reconnect to the broker after connection loss.
    ///
    /// Initiates reconnection logic including cleanup of stale state,
    /// re-authentication, and restoration of subscriptions.
    /// Should be called when connection monitoring detects a failure.
    ///
    /// # Returns
    ///
    /// - `Ok(())` if reconnection succeeds
    /// - `Err(BrokerError)` if reconnection fails
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use data::brokers::common::{BrokerClient, BrokerResult};
    /// # async fn example(client: &impl BrokerClient) -> BrokerResult<()> {
    /// // Reconnection with retry logic
    /// for attempt in 1..=3 {
    ///     match client.reconnect().await {
    ///         Ok(()) => {
    ///             println!("Reconnected successfully");
    ///             break;
    ///         },
    ///         Err(e) => {
    ///             eprintln!("Reconnection attempt {} failed: {}", attempt, e);
    ///             if attempt < 3 {
    ///                 tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
    ///             }
    ///         }
    ///     }
    /// }
    /// # Ok(())
    /// # }
    /// ```
    async fn reconnect(&self) -> BrokerResult<()>;
}

// Order struct is now imported from common::types
// Note: Order is imported from ::common but not re-exported to avoid conflicts
