using System;
using System.Collections.Generic;
using NT8.Core.Common.Models;
using NT8.Core.Risk;
using NT8.Core.Sizing;

namespace NT8.Adapters.NinjaTrader
{
    /// <summary>
    /// Order adapter for executing trades through NT8
    /// </summary>
    public class NT8OrderAdapter
    {
        private readonly object _lock = new object();
        private IRiskManager _riskManager;
        private IPositionSizer _positionSizer;
        private readonly List<NT8OrderExecutionRecord> _executionHistory;

        /// <summary>
        /// Constructor for NT8OrderAdapter.
        /// </summary>
        public NT8OrderAdapter()
        {
            _executionHistory = new List<NT8OrderExecutionRecord>();
        }

        /// <summary>
        /// Initialize the order adapter with required components
        /// </summary>
        public void Initialize(IRiskManager riskManager, IPositionSizer positionSizer)
        {
            if (riskManager == null)
            {
                throw new ArgumentNullException("riskManager");
            }

            if (positionSizer == null)
            {
                throw new ArgumentNullException("positionSizer");
            }

            try
            {
                _riskManager = riskManager;
                _positionSizer = positionSizer;
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Execute strategy intent through NT8 order management
        /// </summary>
        public void ExecuteIntent(StrategyIntent intent, StrategyContext context, StrategyConfig config)
        {
            if (intent == null)
            {
                throw new ArgumentNullException("intent");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if (_riskManager == null || _positionSizer == null)
            {
                throw new InvalidOperationException("Adapter not initialized. Call Initialize() first.");
            }

            try
            {
                // Validate the intent through risk management
                var riskDecision = _riskManager.ValidateOrder(intent, context, config.RiskSettings);
                if (!riskDecision.Allow)
                {
                    // Risk rejected the order flow.
                    return;
                }

                // Calculate position size
                var sizingResult = _positionSizer.CalculateSize(intent, context, config.SizingSettings);
                if (sizingResult.Contracts <= 0)
                {
                    // No tradable size produced.
                    return;
                }

                // In a real implementation, this would call NT8's order execution methods.
                ExecuteInNT8(intent, sizingResult);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Gets a snapshot of executions submitted through this adapter.
        /// </summary>
        /// <returns>Execution history snapshot.</returns>
        public IList<NT8OrderExecutionRecord> GetExecutionHistory()
        {
            try
            {
                lock (_lock)
                {
                    return new List<NT8OrderExecutionRecord>(_executionHistory);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Execute the order in NT8 (placeholder implementation)
        /// </summary>
        private void ExecuteInNT8(StrategyIntent intent, SizingResult sizing)
        {
            if (intent == null)
            {
                throw new ArgumentNullException("intent");
            }

            if (sizing == null)
            {
                throw new ArgumentNullException("sizing");
            }

            // This is where the actual NT8 order execution would happen
            // In a real implementation, this would call NT8's EnterLong/EnterShort methods
            // along with SetStopLoss, SetProfitTarget, etc.

            lock (_lock)
            {
                _executionHistory.Add(new NT8OrderExecutionRecord(
                    intent.Symbol,
                    intent.Side,
                    intent.EntryType,
                    sizing.Contracts,
                    intent.StopTicks,
                    intent.TargetTicks,
                    DateTime.UtcNow));
            }

            // Example of what this might look like in NT8:
            /*
            if (intent.Side == OrderSide.Buy)
            {
                EnterLong(sizing.Contracts, "SDK_Entry");
                SetStopLoss("SDK_Entry", CalculationMode.Ticks, intent.StopTicks);
                if (intent.TargetTicks.HasValue)
                {
                    SetProfitTarget("SDK_Entry", CalculationMode.Ticks, intent.TargetTicks.Value);
                }
            }
            else if (intent.Side == OrderSide.Sell)
            {
                EnterShort(sizing.Contracts, "SDK_Entry");
                SetStopLoss("SDK_Entry", CalculationMode.Ticks, intent.StopTicks);
                if (intent.TargetTicks.HasValue)
                {
                    SetProfitTarget("SDK_Entry", CalculationMode.Ticks, intent.TargetTicks.Value);
                }
            }
            */
        }

        /// <summary>
        /// Handle order updates from NT8
        /// </summary>
        public void OnOrderUpdate(string orderId, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, string orderState, DateTime time, string errorCode, string nativeError)
        {
            if (string.IsNullOrWhiteSpace(orderId))
            {
                throw new ArgumentException("orderId");
            }

            try
            {
                // Pass order updates to risk manager for tracking.
                if (_riskManager != null)
                {
                    // In a real implementation, convert NT8 order data to SDK models.
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Handle execution updates from NT8
        /// </summary>
        public void OnExecutionUpdate(string executionId, string orderId, double price, int quantity, string marketPosition, DateTime time)
        {
            if (string.IsNullOrWhiteSpace(executionId))
            {
                throw new ArgumentException("executionId");
            }

            if (string.IsNullOrWhiteSpace(orderId))
            {
                throw new ArgumentException("orderId");
            }

            try
            {
                // Pass execution updates to risk manager for P&L tracking.
                if (_riskManager != null)
                {
                    // In a real implementation, convert NT8 execution data to SDK models.
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

    /// <summary>
    /// Execution record captured by NT8OrderAdapter for diagnostics and tests.
    /// </summary>
    public class NT8OrderExecutionRecord
    {
        /// <summary>
        /// Trading symbol.
        /// </summary>
        public string Symbol { get; set; }

        /// <summary>
        /// Order side.
        /// </summary>
        public OrderSide Side { get; set; }

        /// <summary>
        /// Entry order type.
        /// </summary>
        public OrderType EntryType { get; set; }

        /// <summary>
        /// Executed contract quantity.
        /// </summary>
        public int Contracts { get; set; }

        /// <summary>
        /// Stop-loss distance in ticks.
        /// </summary>
        public int StopTicks { get; set; }

        /// <summary>
        /// Profit target distance in ticks.
        /// </summary>
        public int? TargetTicks { get; set; }

        /// <summary>
        /// Timestamp when the execution was recorded.
        /// </summary>
        public DateTime Timestamp { get; set; }

        /// <summary>
        /// Constructor for NT8OrderExecutionRecord.
        /// </summary>
        public NT8OrderExecutionRecord(string symbol, OrderSide side, OrderType entryType, int contracts, int stopTicks, int? targetTicks, DateTime timestamp)
        {
            Symbol = symbol;
            Side = side;
            EntryType = entryType;
            Contracts = contracts;
            StopTicks = stopTicks;
            TargetTicks = targetTicks;
            Timestamp = timestamp;
        }
    }
}
