using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Logging;
using NT8.Core.Orders;
using NT8.Core.Risk;
using NT8.Core.Sizing;
using NT8.Core.Common.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace NT8.Core.Tests.Orders
{
    [TestClass]
    public class OrderManagerTests
    {
        private TestRiskManager _testRiskManager;
        private TestPositionSizer _testPositionSizer;
        private TestLogger _testLogger;
        private OrderManager _orderManager;

        [TestInitialize]
        public void TestInitialize()
        {
            _testRiskManager = new TestRiskManager();
            _testPositionSizer = new TestPositionSizer();
            _testLogger = new TestLogger();

            _orderManager = new OrderManager(
                _testRiskManager,
                _testPositionSizer,
                _testLogger);
        }

        [TestMethod]
        public async Task SubmitOrderAsync_WithValidRequest_ReturnsSuccess()
        {
            // Arrange
            var algorithmParameters = new Dictionary<string, object>();
            var request = new OrderRequest(
                "ES",
                NT8.Core.Orders.OrderSide.Buy,
                NT8.Core.Orders.OrderType.Market,
                1,
                null,
                null,
                NT8.Core.Orders.TimeInForce.Day,
                null,
                algorithmParameters
            );

            var customData = new Dictionary<string, object>();
            var context = new StrategyContext(
                "ES",
                DateTime.UtcNow,
                new Position("ES", 0, 0, 0, 0, DateTime.UtcNow),
                new AccountInfo(10000, 100, 0, 0, DateTime.UtcNow),
                new MarketSession(DateTime.UtcNow, DateTime.UtcNow.AddHours(8), true, "RTH"),
                customData
            );

            // Act
            var result = await _orderManager.SubmitOrderAsync(request, context);

            // Assert
            Assert.IsTrue(result.Success);
            Assert.IsNotNull(result.OrderId);
            Assert.AreEqual("Order submitted successfully", result.Message);
        }

        [TestMethod]
        public async Task GetRoutingConfig_ReturnsConfig()
        {
            // Act
            var config = _orderManager.GetRoutingConfig();

            // Assert
            Assert.IsNotNull(config);
            Assert.IsTrue(config.SmartRoutingEnabled);
            Assert.AreEqual("Primary", config.DefaultVenue);
        }

        [TestMethod]
        public void UpdateRoutingConfig_WithValidConfig_UpdatesConfig()
        {
            // Arrange
            var venuePreferences = new Dictionary<string, double>();
            venuePreferences.Add("TestVenue", 1.0);

            var newConfig = new RoutingConfig(
                false,  // SmartRoutingEnabled
                "TestVenue",  // DefaultVenue
                venuePreferences,
                1.0, // MaxSlippagePercent
                TimeSpan.FromSeconds(60),  // MaxRoutingTime
                false,  // RouteByCost
                false,  // RouteBySpeed
                false   // RouteByReliability
            );

            // Act
            _orderManager.UpdateRoutingConfig(newConfig);
            var config = _orderManager.GetRoutingConfig();

            // Assert
            Assert.IsNotNull(config);
            Assert.IsFalse(config.SmartRoutingEnabled);
            Assert.AreEqual("TestVenue", config.DefaultVenue);
            Assert.AreEqual(1.0, config.MaxSlippagePercent);
        }

        #region Test Implementations

        /// <summary>
        /// Test implementation of IRiskManager
        /// </summary>
        private class TestRiskManager : IRiskManager
        {
            public RiskDecision ValidateOrder(StrategyIntent intent, StrategyContext context, RiskConfig config)
            {
                // Always approve for testing
                var metrics = new Dictionary<string, object>();
                return new RiskDecision(true, null, null, RiskLevel.Low, metrics);
            }

            public void OnFill(OrderFill fill)
            {
                // No-op for testing
            }

            public void OnPnLUpdate(double netPnL, double dayPnL)
            {
                // No-op for testing
            }

            public async Task<bool> EmergencyFlatten(string reason)
            {
                // Always succeed for testing
                return true;
            }

            public RiskStatus GetRiskStatus()
            {
                var alerts = new List<string>();
                return new RiskStatus(true, 0, 1000, 0, 0, DateTime.UtcNow, alerts);
            }
        }

        /// <summary>
        /// Test implementation of IPositionSizer
        /// </summary>
        private class TestPositionSizer : IPositionSizer
        {
            public SizingResult CalculateSize(StrategyIntent intent, StrategyContext context, SizingConfig config)
            {
                // Return fixed size for testing
                var calculations = new Dictionary<string, object>();
                return new SizingResult(1, 100, SizingMethod.FixedContracts, calculations);
            }

            public SizingMetadata GetMetadata()
            {
                var requiredParameters = new List<string>();
                return new SizingMetadata("TestSizer", "Test position sizer", requiredParameters);
            }
        }

        /// <summary>
        /// Test implementation of ILogger
        /// </summary>
        private class TestLogger : ILogger<OrderManager>
        {
            public IDisposable BeginScope<TState>(TState state)
            {
                return null;
            }

            public bool IsEnabled(LogLevel logLevel)
            {
                return true;
            }

            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
            {
                // No-op for testing
            }
        }

        #endregion
    }
}
