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

namespace NT8.Adapters.NinjaTrader
{
    /// <summary>
    /// Main NT8 adapter implementation that integrates all components
    /// </summary>
    public class NT8Adapter : INT8Adapter
    {
        private readonly object _lock = new object();
        private readonly NT8DataAdapter _dataAdapter;
        private readonly NT8OrderAdapter _orderAdapter;
        private readonly NT8LoggingAdapter _loggingAdapter;
        private readonly List<NT8OrderExecutionRecord> _executionHistory;
        private IRiskManager _riskManager;
        private IPositionSizer _positionSizer;

        /// <summary>
        /// Constructor for NT8Adapter
        /// </summary>
        public NT8Adapter()
        {
            _dataAdapter = new NT8DataAdapter();
            _orderAdapter = new NT8OrderAdapter();
            _loggingAdapter = new NT8LoggingAdapter();
            _executionHistory = new List<NT8OrderExecutionRecord>();
        }

        /// <summary>
        /// Initialize the adapter with required components
        /// </summary>
        public void Initialize(IRiskManager riskManager, IPositionSizer positionSizer)
        {
            _riskManager = riskManager;
            _positionSizer = positionSizer;
            _orderAdapter.Initialize(riskManager, positionSizer);
        }

        /// <summary>
        /// Convert NT8 bar data to SDK format
        /// </summary>
        public BarData ConvertToSdkBar(string symbol, DateTime time, double open, double high, double low, double close, long volume, int barSizeMinutes)
        {
            return _dataAdapter.ConvertToSdkBar(symbol, time, open, high, low, close, volume, barSizeMinutes);
        }

        /// <summary>
        /// Convert NT8 account data to SDK format
        /// </summary>
        public AccountInfo ConvertToSdkAccount(double equity, double buyingPower, double dailyPnL, double maxDrawdown, DateTime lastUpdate)
        {
            return _dataAdapter.ConvertToSdkAccount(equity, buyingPower, dailyPnL, maxDrawdown, lastUpdate);
        }

        /// <summary>
        /// Convert NT8 position data to SDK format
        /// </summary>
        public Position ConvertToSdkPosition(string symbol, int quantity, double averagePrice, double unrealizedPnL, double realizedPnL, DateTime lastUpdate)
        {
            return _dataAdapter.ConvertToSdkPosition(symbol, quantity, averagePrice, unrealizedPnL, realizedPnL, lastUpdate);
        }

        /// <summary>
        /// Execute strategy intent through NT8
        /// </summary>
        public void ExecuteIntent(StrategyIntent intent, SizingResult sizing)
        {
            if (intent == null)
            {
                throw new ArgumentNullException("intent");
            }

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

            // In a full implementation, this would execute the order through NT8
            // For now, we'll just log what would be executed
            _loggingAdapter.LogInformation("Executing intent: {0} {1} contracts at {2} ticks stop",
                intent.Side, sizing.Contracts, intent.StopTicks);

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

        /// <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)
        {
            _orderAdapter.OnOrderUpdate(orderId, limitPrice, stopPrice, quantity, filled, averageFillPrice, orderState, time, errorCode, nativeError);
        }

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

        /// <summary>
        /// Gets execution history captured by the order adapter.
        /// </summary>
        /// <returns>Execution history snapshot.</returns>
        public IList<NT8OrderExecutionRecord> GetExecutionHistory()
        {
            lock (_lock)
            {
                return new List<NT8OrderExecutionRecord>(_executionHistory);
            }
        }
    }
}
