//! Position Manager fixes for Price/Decimal conflicts
//! 
//! Key fixes needed:
//! 1. Replace .value() calls on Decimal with direct usage
//! 2. Fix Position field access (avg_cost -> avg_price)  
//! 3. Handle Volume::new() Result return type
//! 4. Add proper type conversions

use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, info, warn};

use crate::trading_operations::ExecutionResult;
use crate::types::prelude::*;
use rust_decimal::Decimal;

/// Position Manager for tracking and managing positions
#[derive(Debug)]
pub struct PositionManager {
    /// Current positions by symbol
    positions: Arc<RwLock<HashMap<String, Position>>>,
}

impl PositionManager {
    /// Create a new position manager
    pub fn new() -> Self {
        Self {
            positions: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Update position based on execution
    pub async fn update_position(&self, execution: &ExecutionResult) -> Result<(), String> {
        let mut positions = self.positions.write().await;

        let position = positions
            .entry(execution.symbol.clone())
            .or_insert_with(|| {
                let now = chrono::Utc::now();
                Position {
                    id: uuid::Uuid::new_v4(),
                    symbol: execution.symbol.clone(),
                    quantity: Decimal::ZERO,
                    avg_price: Decimal::ZERO,
                    avg_cost: Decimal::ZERO,
                    basis: Decimal::ZERO,
                    average_price: Decimal::ZERO,
                    market_value: Decimal::ZERO,
                    unrealized_pnl: Decimal::ZERO,
                    realized_pnl: Decimal::ZERO,
                    created_at: now,
                    updated_at: now,
                    last_updated: now,
                    current_price: None,
                    notional_value: Decimal::ZERO,
                    margin_requirement: Decimal::ZERO,
                }
            });

        // CRITICAL FIX: Don't call .value() on Decimal - use directly
        let is_buy = execution.executed_quantity > Decimal::ZERO;
        let old_quantity = position.quantity;  // Already Decimal
        let old_cost = position.avg_price;     // FIX: Use avg_price not avg_cost

        if is_buy {
            if position.quantity >= Decimal::ZERO {
                // Same direction - calculate new average cost
                let old_qty_decimal = old_quantity;
                let old_cost_decimal = old_cost;  // Already Decimal
                let exec_qty_decimal = execution.executed_quantity;
                let exec_price_decimal = execution.execution_price;

                let total_cost = old_qty_decimal * old_cost_decimal + exec_qty_decimal * exec_price_decimal;
                let new_quantity_decimal = old_qty_decimal + exec_qty_decimal;

                position.quantity = new_quantity_decimal;
                position.avg_price = if new_quantity_decimal > Decimal::ZERO {
                    total_cost / new_quantity_decimal
                } else {
                    Decimal::ZERO
                };
                // Keep other fields in sync
                position.avg_cost = position.avg_price;
                position.average_price = position.avg_price;
            } else {
                // Reducing short position
                let exec_qty_decimal = execution.executed_quantity;
                let exec_price_decimal = execution.execution_price;
                let old_qty_decimal = old_quantity;
                // FIX: old_cost is already Decimal, no conversion needed
                let old_cost_decimal = old_cost;

                let reduction = exec_qty_decimal.min(old_qty_decimal.abs());
                let realized_pnl = reduction * (old_cost_decimal - exec_price_decimal);
                position.realized_pnl = position.realized_pnl + realized_pnl;

                let new_quantity = old_qty_decimal + reduction;
                position.quantity = new_quantity;

                if new_quantity > Decimal::ZERO {
                    position.avg_price = exec_price_decimal;
                    position.avg_cost = exec_price_decimal;
                    position.average_price = exec_price_decimal;
                }
            }
        } else {
            // Decreasing position (sell)
            let exec_qty_decimal = execution.executed_quantity;
            let exec_price_decimal = execution.execution_price;
            // FIX: Don't call .value() on Decimal
            let old_qty_decimal = old_quantity;
            let old_cost_decimal = old_cost;  // Already Decimal

            if old_qty_decimal > Decimal::ZERO {
                // Reducing long position
                let reduction = exec_qty_decimal.min(old_qty_decimal);
                let realized_pnl = reduction * (exec_price_decimal - old_cost_decimal);
                position.realized_pnl = position.realized_pnl + realized_pnl;

                let new_quantity_decimal = old_qty_decimal - reduction;
                position.quantity = new_quantity_decimal;

                if new_quantity_decimal < Decimal::ZERO {
                    position.avg_price = exec_price_decimal;
                    position.avg_cost = exec_price_decimal;
                    position.average_price = exec_price_decimal;
                }
            } else {
                // Increasing short position
                let total_cost = old_qty_decimal.abs() * old_cost_decimal + exec_qty_decimal * exec_price_decimal;
                let new_quantity_decimal = old_qty_decimal - exec_qty_decimal;

                position.quantity = new_quantity_decimal;
                if new_quantity_decimal < Decimal::ZERO {
                    let new_avg_price = total_cost / new_quantity_decimal.abs();
                    position.avg_price = new_avg_price;
                    position.avg_cost = new_avg_price;
                    position.average_price = new_avg_price;
                } else {
                    position.avg_price = Decimal::ZERO;
                    position.avg_cost = Decimal::ZERO; 
                    position.average_price = Decimal::ZERO;
                }
            }
        }
        position.last_updated = chrono::Utc::now();
        position.updated_at = chrono::Utc::now();

        info!(
            "Position updated for {}: {} @ {} (realized P&L: {})",
            execution.symbol, position.quantity, position.avg_price, position.realized_pnl
        );

        Ok(())
    }

    /// Update market values based on current market prices
    pub async fn update_market_values(
        &self,
        market_prices: HashMap<String, Decimal>,
    ) -> Result<(), String> {
        let mut positions = self.positions.write().await;

        for (symbol, market_price) in market_prices {
            if let Some(position) = positions.get_mut(&symbol) {
                let qty_decimal = position.quantity;
                // FIX: avg_cost is already Decimal
                let avg_cost_decimal = position.avg_price;  // Use avg_price

                // Calculate market value
                let market_value_decimal = qty_decimal * market_price;
                position.market_value = market_value_decimal;
                
                // Calculate unrealized P&L
                if qty_decimal != Decimal::ZERO {
                    let unrealized_pnl = if qty_decimal > Decimal::ZERO {
                        // Long position
                        qty_decimal * (market_price - avg_cost_decimal)
                    } else {
                        // Short position
                        qty_decimal.abs() * (avg_cost_decimal - market_price)
                    };
                    position.unrealized_pnl = unrealized_pnl;
                } else {
                    position.unrealized_pnl = Decimal::ZERO;
                }

                position.last_updated = chrono::Utc::now();
                position.updated_at = chrono::Utc::now();

                debug!(
                    "Updated market value for {}: {} (unrealized P&L: {})",
                    symbol, position.market_value, position.unrealized_pnl
                );
            }
        }

        Ok(())
    }

    /// Get total portfolio value
    pub async fn get_total_portfolio_value(&self) -> Decimal {
        let positions = self.positions.read().await;

        positions
            .values()
            .map(|pos| pos.market_value)  // Already Decimal, no conversion needed
            .sum::<Decimal>()
    }

    /// Get positions that exceed risk limits
    pub async fn get_positions_exceeding_limits(
        &self,
        max_position_value: Decimal,
    ) -> Vec<Position> {
        let positions = self.positions.read().await;

        positions
            .values()
            .filter(|pos| pos.market_value.abs() > max_position_value)  // Already Decimal
            .cloned()
            .collect()
    }

    /// Calculate position concentration risk
    pub async fn calculate_concentration_risk(&self) -> HashMap<String, f64> {
        let positions = self.positions.read().await;
        let total_value = positions
            .values()
            .map(|pos| pos.market_value.abs())  // Already Decimal
            .sum::<Decimal>();

        if total_value == Decimal::ZERO {
            return HashMap::new();
        }

        positions
            .iter()
            .map(|(symbol, position)| {
                let concentration = (position.market_value.abs() / total_value)
                    .to_f64()
                    .unwrap_or(0.0)
                    * 100.0;
                (symbol.clone(), concentration)
            })
            .collect()
    }

    // ... rest of methods remain the same
}