// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers;
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Resources;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using VSTestAttachmentSet = Microsoft.VisualStudio.TestPlatform.ObjectModel.AttachmentSet;
using VSTestTestCase = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestCase;
using VSTestTestResult = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResult;
using VSTestTestResultMessage = Microsoft.VisualStudio.TestPlatform.ObjectModel.TestResultMessage;
using VSTestUriDataAttachment = Microsoft.VisualStudio.TestPlatform.ObjectModel.UriDataAttachment;

namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Extensions;

/// <summary>
/// Extension methods for TestResult.
/// </summary>
internal static class TestResultExtensions
{
    /// <summary>
    /// Convert parameter unitTestResult to testResult.
    /// </summary>
    /// <param name="frameworkTestResult"> The framework result to be converted to VSTest test result.</param>
    /// <param name="testCase"> The test Case. </param>
    /// <param name="startTime"> The start Time. </param>
    /// <param name="endTime"> The end Time. </param>
    /// <param name="computerName">The computer name.</param>
    /// <param name="currentSettings">Current MSTest settings.</param>
    internal static VSTestTestResult ToTestResult(this TestResult frameworkTestResult, VSTestTestCase testCase, DateTimeOffset startTime, DateTimeOffset endTime, string computerName, MSTestSettings currentSettings)
    {
        DebugEx.Assert(testCase != null, "testCase");
        if (frameworkTestResult.AssociatedUnitTestElement is UnitTestElement unitTestElement)
        {
            testCase = unitTestElement.ToTestCase();
        }

        var testResult = new VSTestTestResult(testCase)
        {
            DisplayName = frameworkTestResult.DisplayName,
            Duration = frameworkTestResult.Duration,
            ErrorMessage = frameworkTestResult.ExceptionMessage ?? frameworkTestResult.IgnoreReason,
            ErrorStackTrace = frameworkTestResult.ExceptionStackTrace,
            Outcome = UnitTestOutcomeHelper.ToTestOutcome(frameworkTestResult.Outcome, currentSettings),
            StartTime = startTime,
            EndTime = endTime,
            ComputerName = computerName,
        };

        testResult.SetPropertyValue(AdapterTestProperties.ExecutionIdProperty, frameworkTestResult.ExecutionId);
        testResult.SetPropertyValue(AdapterTestProperties.ParentExecIdProperty, frameworkTestResult.ParentExecId);

        if (!StringEx.IsNullOrEmpty(frameworkTestResult.LogOutput))
        {
            VSTestTestResultMessage message = new(VSTestTestResultMessage.StandardOutCategory, frameworkTestResult.LogOutput);
            testResult.Messages.Add(message);
        }

        if (!StringEx.IsNullOrEmpty(frameworkTestResult.LogError))
        {
            VSTestTestResultMessage message = new(VSTestTestResultMessage.StandardErrorCategory, frameworkTestResult.LogError);
            testResult.Messages.Add(message);
        }

        if (!StringEx.IsNullOrEmpty(frameworkTestResult.DebugTrace))
        {
            string debugTraceMessagesInStdOut =
                $"""


                 {Resource.DebugTraceBanner}
                 {frameworkTestResult.DebugTrace}
                 """;
            VSTestTestResultMessage debugTraceMessage = new(VSTestTestResultMessage.StandardOutCategory, debugTraceMessagesInStdOut);
            testResult.Messages.Add(debugTraceMessage);
        }

        if (!StringEx.IsNullOrEmpty(frameworkTestResult.TestContextMessages))
        {
            string testContextMessagesInStdOut =
                $"""


                 {Resource.TestContextMessageBanner}
                 {frameworkTestResult.TestContextMessages}
                 """;
            VSTestTestResultMessage testContextMessage = new(VSTestTestResultMessage.StandardOutCategory, testContextMessagesInStdOut);
            testResult.Messages.Add(testContextMessage);
        }

        if (frameworkTestResult.ResultFiles is { Count: > 0 })
        {
            VSTestAttachmentSet attachmentSet = new(EngineConstants.ExecutorUri, Resource.AttachmentSetDisplayName);
            foreach (string resultFile in frameworkTestResult.ResultFiles)
            {
                string pathToResultFile = PlatformServiceProvider.Instance.FileOperations.GetFullFilePath(resultFile);
                VSTestUriDataAttachment attachment = new(new Uri(pathToResultFile), resultFile);
                attachmentSet.Attachments.Add(attachment);
            }

            testResult.Attachments.Add(attachmentSet);
        }

        return testResult;
    }
}
