using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NT8.Core.Execution;
using NT8.Core.Tests.Mocks;

namespace NT8.Core.Tests.Execution
{
    [TestClass]
    public class MultiLevelTargetManagerTests
    {
        private MultiLevelTargetManager _manager;

        [TestInitialize]
        public void Setup()
        {
            _manager = new MultiLevelTargetManager(new MockLogger<MultiLevelTargetManager>());
        }

        [TestMethod]
        public void Constructor_NullLogger_ThrowsArgumentNullException()
        {
            Assert.ThrowsException<ArgumentNullException>(delegate
            {
                new MultiLevelTargetManager(null);
            });
        }

        [TestMethod]
        public void SetTargets_ValidInput_SetsStatusActive()
        {
            var targets = new MultiLevelTargets(8, 2, 16, 2, 32, 1);
            _manager.SetTargets("ORD-ML-1", targets);

            var status = _manager.GetTargetStatus("ORD-ML-1");
            Assert.IsTrue(status.Active);
            Assert.AreEqual(3, status.TotalTargets);
        }

        [TestMethod]
        public void SetTargets_NullOrderId_ThrowsArgumentNullException()
        {
            var targets = new MultiLevelTargets(8, 1);
            Assert.ThrowsException<ArgumentNullException>(delegate
            {
                _manager.SetTargets(null, targets);
            });
        }

        [TestMethod]
        public void SetTargets_NullTargets_ThrowsArgumentNullException()
        {
            Assert.ThrowsException<ArgumentNullException>(delegate
            {
                _manager.SetTargets("ORD-ML-2", null);
            });
        }

        [TestMethod]
        public void OnTargetHit_Tp1_ReturnsPartialClose()
        {
            _manager.SetTargets("ORD-ML-3", new MultiLevelTargets(8, 2, 16, 2, 32, 1));

            var result = _manager.OnTargetHit("ORD-ML-3", 1, 5002m);

            Assert.AreEqual(TargetAction.PartialClose, result.Action);
            Assert.AreEqual(2, result.ContractsToClose);
        }

        [TestMethod]
        public void OnTargetHit_Tp2NotConfigured_ReturnsNoAction()
        {
            _manager.SetTargets("ORD-ML-4", new MultiLevelTargets(8, 1));

            var result = _manager.OnTargetHit("ORD-ML-4", 2, 5003m);

            Assert.AreEqual(TargetAction.NoAction, result.Action);
        }

        [TestMethod]
        public void OnTargetHit_AllConfiguredTargetsHit_ReturnsClosePosition()
        {
            _manager.SetTargets("ORD-ML-5", new MultiLevelTargets(8, 1, 16, 1));

            var r1 = _manager.OnTargetHit("ORD-ML-5", 1, 5002m);
            var r2 = _manager.OnTargetHit("ORD-ML-5", 2, 5004m);

            Assert.AreEqual(TargetAction.PartialClose, r1.Action);
            Assert.AreEqual(TargetAction.ClosePosition, r2.Action);
        }

        [TestMethod]
        public void OnTargetHit_DuplicateLevel_ReturnsNoAction()
        {
            _manager.SetTargets("ORD-ML-6", new MultiLevelTargets(8, 1, 16, 1));

            var first = _manager.OnTargetHit("ORD-ML-6", 1, 5002m);
            var second = _manager.OnTargetHit("ORD-ML-6", 1, 5003m);

            Assert.AreEqual(TargetAction.PartialClose, first.Action);
            Assert.AreEqual(TargetAction.NoAction, second.Action);
        }

        [TestMethod]
        public void OnTargetHit_UnknownOrder_ReturnsNoAction()
        {
            var result = _manager.OnTargetHit("ORD-UNKNOWN", 1, 100m);
            Assert.AreEqual(TargetAction.NoAction, result.Action);
        }

        [TestMethod]
        public void ShouldAdvanceStop_Tp1AndTp2_True_Tp3False()
        {
            Assert.IsTrue(_manager.ShouldAdvanceStop(1));
            Assert.IsTrue(_manager.ShouldAdvanceStop(2));
            Assert.IsFalse(_manager.ShouldAdvanceStop(3));
        }

        [TestMethod]
        public void GetTargetStatus_UnknownOrder_ReturnsInactive()
        {
            var status = _manager.GetTargetStatus("ORD-NONE");
            Assert.IsFalse(status.Active);
            Assert.AreEqual(0, status.TotalTargets);
        }

        [TestMethod]
        public void DeactivateTargets_SetsInactive()
        {
            _manager.SetTargets("ORD-ML-7", new MultiLevelTargets(8, 1));
            _manager.DeactivateTargets("ORD-ML-7");

            var status = _manager.GetTargetStatus("ORD-ML-7");
            Assert.IsFalse(status.Active);
        }

        [TestMethod]
        public void RemoveTargets_DeletesState()
        {
            _manager.SetTargets("ORD-ML-8", new MultiLevelTargets(8, 1, 16, 1, 32, 1));
            _manager.RemoveTargets("ORD-ML-8");

            var status = _manager.GetTargetStatus("ORD-ML-8");
            Assert.IsFalse(status.Active);
            Assert.AreEqual(0, status.TotalTargets);
        }
    }
}
