//! Repository interfaces for Trading Service
//!
//! This module defines the repository pattern interfaces that eliminate direct database
//! coupling from business logic. All database operations are abstracted through these
//! repository traits, enabling proper dependency injection and clean architecture.

use crate::error::TradingServiceResult;
use async_trait::async_trait;
// Import canonical MarketDataEvent from data crate
use common::MarketDataEvent;
// Import canonical types from trading_engine
use common::OrderSide;
use common::OrderStatus;
use common::OrderType;
use common::PriceLevel;

/// Trading repository for order and execution data persistence
#[async_trait]
pub trait TradingRepository: Send + Sync {
    /// Store a new order in the trading repository
    async fn store_order(&self, order: &TradingOrder) -> TradingServiceResult<String>;

    /// Update an existing order status
    async fn update_order_status(
        &self,
        order_id: &str,
        status: OrderStatus,
    ) -> TradingServiceResult<()>;

    /// Retrieve an order by ID
    async fn get_order(&self, order_id: &str) -> TradingServiceResult<Option<TradingOrder>>;

    /// Get all orders for an account
    async fn get_orders_for_account(
        &self,
        account_id: &str,
    ) -> TradingServiceResult<Vec<TradingOrder>>;

    /// Store execution data
    async fn store_execution(&self, execution: &ExecutionEvent) -> TradingServiceResult<()>;

    /// Get execution history
    async fn get_execution_history(
        &self,
        request: &GetExecutionHistoryRequest,
    ) -> TradingServiceResult<Vec<ExecutionEvent>>;

    /// Store position update
    async fn store_position(&self, position: &TradingPosition) -> TradingServiceResult<()>;

    /// Get positions for account and symbol
    async fn get_positions(
        &self,
        account_id: Option<&str>,
        symbol: Option<&str>,
    ) -> TradingServiceResult<Vec<TradingPosition>>;

    /// Get portfolio summary
    async fn get_portfolio_summary(
        &self,
        account_id: &str,
    ) -> TradingServiceResult<PortfolioSummary>;

    /// Get realized PnL for account and optional symbol
    async fn get_realized_pnl(
        &self,
        account_id: &str,
        symbol: Option<&str>,
    ) -> TradingServiceResult<f64>;

    /// Get day PnL for account (today's realized PnL)
    async fn get_day_pnl(&self, account_id: &str) -> TradingServiceResult<f64>;
}

/// Market data repository for prices, order books, and market information
#[async_trait]
pub trait MarketDataRepository: Send + Sync {
    /// Store market data tick
    async fn store_market_tick(&self, tick: &MarketTick) -> TradingServiceResult<()>;

    /// Get current order book for a symbol
    async fn get_order_book(&self, symbol: &str, depth: i32) -> TradingServiceResult<OrderBook>;

    /// Store order book update
    async fn store_order_book(
        &self,
        symbol: &str,
        order_book: &OrderBook,
    ) -> TradingServiceResult<()>;

    /// Get latest market data for symbols
    async fn get_latest_prices(&self, symbols: &[String]) -> TradingServiceResult<Vec<MarketTick>>;

    /// Store market data event
    async fn store_market_event(&self, event: &MarketDataEvent) -> TradingServiceResult<()>;

    /// Get historical market data
    async fn get_historical_data(
        &self,
        symbol: &str,
        from: i64,
        to: i64,
    ) -> TradingServiceResult<Vec<MarketTick>>;

    /// Get order count for a specific order book level
    async fn get_order_book_level_count(
        &self,
        symbol: &str,
        price: f64,
        side: OrderSide,
    ) -> TradingServiceResult<i32>;
}

/// Risk repository for risk calculations, limits, and compliance data
#[async_trait]
pub trait RiskRepository: Send + Sync {
    /// Store VaR calculation result
    async fn store_var_calculation(&self, calculation: &VarCalculation)
        -> TradingServiceResult<()>;

    /// Get current risk limits for account
    async fn get_risk_limits(&self, account_id: &str) -> TradingServiceResult<RiskLimits>;

    /// Update risk limits for account
    async fn update_risk_limits(
        &self,
        account_id: &str,
        limits: &RiskLimits,
    ) -> TradingServiceResult<()>;

    /// Store risk alert
    async fn store_risk_alert(&self, alert: &RiskAlert) -> TradingServiceResult<()>;

    /// Get risk metrics for portfolio
    async fn get_risk_metrics(&self, account_id: &str) -> TradingServiceResult<RiskMetrics>;

    /// Store position risk calculation
    async fn store_position_risk(
        &self,
        account_id: &str,
        symbol: &str,
        risk: &PositionRisk,
    ) -> TradingServiceResult<()>;

    /// Check if order violates risk limits
    async fn validate_order_risk(
        &self,
        account_id: &str,
        order: &OrderRequest,
    ) -> TradingServiceResult<bool>;

    /// Calculate total margin used for account
    async fn calculate_margin_used(&self, account_id: &str) -> TradingServiceResult<f64>;
}

/// Configuration repository for dynamic configuration management
#[async_trait]
pub trait ConfigRepository: Send + Sync {
    /// Get f64 configuration value by category and key
    async fn get_config_f64(&self, category: &str, key: &str) -> TradingServiceResult<Option<f64>>;

    /// Get u64 configuration value by category and key
    async fn get_config_u64(&self, category: &str, key: &str) -> TradingServiceResult<Option<u64>>;

    /// Get string configuration value by category and key
    async fn get_config_string(
        &self,
        category: &str,
        key: &str,
    ) -> TradingServiceResult<Option<String>>;

    /// Set configuration value by category and key
    async fn set_config<T>(&self, category: &str, key: &str, value: &T) -> TradingServiceResult<()>
    where
        T: serde::Serialize + Send + Sync + 'static;

    /// Get secret from secure storage
    async fn get_secret(&self, key: &str) -> TradingServiceResult<Option<String>>;

    /// Set secret in secure storage
    async fn set_secret(&self, key: &str, value: &str) -> TradingServiceResult<()>;

    /// Subscribe to configuration changes
    async fn subscribe_to_changes(&self) -> TradingServiceResult<ConfigChangeReceiver>;
}

// Supporting types for repository interfaces
use crate::proto::trading::*;

// Use proto Order type for database operations
#[derive(Debug, Clone)]
pub struct TradingOrder {
    pub id: String,
    pub account_id: String,
    pub symbol: String,
    pub side: OrderSide,
    pub order_type: OrderType,
    pub quantity: f64,
    pub filled_quantity: f64,
    pub price: f64,
    pub stop_price: Option<f64>,
    pub status: OrderStatus,
    pub timestamp: i64,
}

/// Trading position for database operations
#[derive(Debug, Clone)]
pub struct TradingPosition {
    pub account_id: String,
    pub symbol: String,
    pub quantity: f64,
    pub average_price: f64,
    pub market_value: f64,
    pub unrealized_pnl: f64,
    pub timestamp: i64,
}

/// Execution event
#[derive(Debug, Clone)]
pub struct ExecutionEvent {
    pub id: String,
    pub order_id: String,
    pub account_id: String,
    pub symbol: String,
    pub side: OrderSide,
    pub quantity: f64,
    pub price: f64,
    pub timestamp: i64,
}

// Position type is already imported from common above

/// Portfolio summary
#[derive(Debug, Clone)]
pub struct PortfolioSummary {
    pub account_id: String,
    pub total_value: f64,
    pub cash_balance: f64,
    pub positions_value: f64,
    pub unrealized_pnl: f64,
    pub realized_pnl: f64,
}

/// Market tick data
#[derive(Debug, Clone)]
pub struct MarketTick {
    pub symbol: String,
    pub price: f64,
    pub quantity: f64,
    pub timestamp: i64,
    pub side: Option<OrderSide>,
}

/// `Order` book representation
#[derive(Debug, Clone)]
pub struct OrderBook {
    pub symbol: String,
    pub bids: Vec<PriceLevel>,
    pub asks: Vec<PriceLevel>,
    pub timestamp: i64,
}

// PriceLevel moved to canonical source in common::types
// Note: Original used f64 and 'quantity' field - code may need conversion

// MarketDataEvent removed - using canonical version from data crate

/// VaR calculation result
#[derive(Debug, Clone)]
pub struct VarCalculation {
    pub account_id: String,
    pub var_value: f64,
    pub confidence: f64,
    pub time_horizon_days: i32,
    pub timestamp: i64,
}

/// Risk limits for account
#[derive(Debug, Clone)]
pub struct RiskLimits {
    pub account_id: String,
    pub max_order_size: f64,
    pub max_position_limit: f64,
    pub max_drawdown_limit: f64,
    pub daily_loss_limit: Option<f64>,
}

/// Risk alert
#[derive(Debug, Clone)]
pub struct RiskAlert {
    pub account_id: String,
    pub alert_type: String,
    pub message: String,
    pub severity: String,
    pub timestamp: i64,
}

/// Risk metrics for portfolio
#[derive(Debug, Clone)]
pub struct RiskMetrics {
    pub account_id: String,
    pub current_var: f64,
    pub current_drawdown: f64,
    pub position_concentration: f64,
    pub leverage_ratio: f64,
}

/// Position-specific risk
#[derive(Debug, Clone)]
pub struct PositionRisk {
    pub symbol: String,
    pub position_var: f64,
    pub concentration_risk: f64,
    pub liquidity_risk: f64,
}

/// `Order` request for validation
#[derive(Debug, Clone)]
pub struct OrderRequest {
    pub symbol: String,
    pub side: OrderSide,
    pub order_type: OrderType,
    pub quantity: f64,
    pub price: Option<f64>,
}

/// Configuration change receiver
pub type ConfigChangeReceiver = tokio::sync::broadcast::Receiver<(String, String)>;
