using Microsoft.VisualStudio.TestTools.UnitTesting;
using NT8.Adapters.NinjaTrader;
using System;
using System.IO;

namespace NT8.Integration.Tests
{
    /// <summary>
    /// Integration tests for NT8 logging adapter output formatting.
    /// </summary>
    [TestClass]
    public class NT8LoggingAdapterIntegrationTests
    {
        [TestMethod]
        public void LogDebug_WritesDebugPrefixAndFormattedMessage()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogDebug("Order {0} created", "A1"));

            // Assert
            Assert.IsTrue(output.Contains("[DEBUG]"));
            Assert.IsTrue(output.Contains("Order A1 created"));
        }

        [TestMethod]
        public void LogInformation_WritesInfoPrefixAndFormattedMessage()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogInformation("Risk {0:F2}", 125.5));

            // Assert
            Assert.IsTrue(output.Contains("[INFO]"));
            Assert.IsTrue(output.Contains("Risk 125.50"));
        }

        [TestMethod]
        public void LogWarning_WritesWarningPrefixAndMessage()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogWarning("Max positions reached"));

            // Assert
            Assert.IsTrue(output.Contains("[WARN]"));
            Assert.IsTrue(output.Contains("Max positions reached"));
        }

        [TestMethod]
        public void LogError_WritesErrorPrefixAndMessage()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogError("Order {0} rejected", "B2"));

            // Assert
            Assert.IsTrue(output.Contains("[ERROR]"));
            Assert.IsTrue(output.Contains("Order B2 rejected"));
        }

        [TestMethod]
        public void LogCritical_WritesCriticalPrefixAndMessage()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogCritical("Emergency flatten executed"));

            // Assert
            Assert.IsTrue(output.Contains("[CRITICAL]"));
            Assert.IsTrue(output.Contains("Emergency flatten executed"));
        }

        [TestMethod]
        public void LogMethods_InvalidFormat_ReturnOriginalMessageWithoutThrowing()
        {
            // Arrange
            var adapter = new NT8LoggingAdapter();

            // Act
            var output = CaptureConsoleOutput(() => adapter.LogInformation("Bad format {0} {1}", "onlyOneArg"));

            // Assert
            Assert.IsTrue(output.Contains("[INFO]"));
            Assert.IsTrue(output.Contains("Bad format {0} {1}"));
        }

        private static string CaptureConsoleOutput(Action action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            var originalOut = Console.Out;
            var writer = new StringWriter();

            try
            {
                Console.SetOut(writer);
                action();
                Console.Out.Flush();
                return writer.ToString();
            }
            finally
            {
                Console.SetOut(originalOut);
                writer.Dispose();
            }
        }
    }
}
