// --------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// --------------------------------------------------------------------------------------------

using System.Collections.Generic;
using System.IO;
using Microsoft.Oryx.BuildScriptGenerator.Common;
using Microsoft.Oryx.Tests.Common;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Oryx.BuildImage.Tests
{
    public class CondaTests : PythonSampleAppsTestBase
    {
        public DockerVolume CreateCondaSampleAppVolume(string sampleAppName) =>
            DockerVolume.CreateMirror(Path.Combine(_hostSamplesDir, "python", "conda-samples", sampleAppName));

        public CondaTests(ITestOutputHelper output) : base(output)
        {
        }

        [Fact, Trait("category", "githubactions")]
        public void CanBuildPythonAppWhichHasJupiterNotebookFile()
        {
            // Arrange
            var appName = "requirements";
            var volume = CreateCondaSampleAppVolume(appName);
            var appDir = volume.ContainerDir;
            var appOutputDir = "/tmp/app-output";
            var script = new ShellScriptBuilder()
                .AddBuildCommand($"{appDir} -o {appOutputDir} -p virtualenv_name=venv")
                .AddDirectoryExistsCheck($"{appOutputDir}/venv")
                .ToString();

            // Act
            var result = _dockerCli.Run(new DockerRunArguments
            {
                ImageId = _imageHelper.GetGitHubActionsBuildImage(),
                EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
                Volumes = new List<DockerVolume> { volume },
                CommandToExecuteOnRun = "/bin/bash",
                CommandArguments = new[] { "-c", script }
            });

            // Assert
            RunAsserts(
                () =>
                {
                    Assert.True(result.IsSuccess);
                },
                result.GetDebugInfo());
        }

        // Temporarily commenting out the following test to prevent it blocking pipelines
        // Test run extremely long and times out
        // Workitem: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1896307
        /*
        [Fact, Trait("category", "vso-focal")]
        public void CanBuildAppWhichHasCondaEnvironmentYmlFile()
        {
            // Arrange
            var appName = "conda";
            var volume = CreateCondaSampleAppVolume(appName);
            var appDir = volume.ContainerDir;
            var appOutputDir = "/tmp/app-output";
            var script = new ShellScriptBuilder()
                .AddBuildCommand($"{appDir} -o {appOutputDir}")
                .AddDirectoryExistsCheck($"{appOutputDir}/venv")
                // Following command makes sure that this package 'matplotlib' is present
                .AddCommand("source /opt/conda/etc/profile.d/conda.sh")
                .AddCommand($"conda activate {appOutputDir}/venv")
                .AddCommand("pip show matplotlib")
                .ToString();

            // Act
            var result = _dockerCli.Run(new DockerRunArguments
            {
                ImageId = _imageHelper.GetVsoBuildImage(ImageTestHelperConstants.VsoFocal),
                EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
                Volumes = new List<DockerVolume> { volume },
                CommandToExecuteOnRun = "/bin/bash",
                CommandArguments = new[] { "-c", script }
            });

            // Assert
            RunAsserts(
                () =>
                {
                    Assert.True(result.IsSuccess);
                },
                result.GetDebugInfo());
        }
        */

        [Fact, Trait("category", "githubactions")]
        public void CanBuildPython2AppHavingRequirementsTxtFile()
        {
            // Arrange
            var appName = "python2_runtime";
            var volume = CreateCondaSampleAppVolume(appName);
            var appDir = volume.ContainerDir;
            var appOutputDir = "/tmp/app-output";
            var script = new ShellScriptBuilder()
                .AddBuildCommand($"{appDir} -o {appOutputDir} -p virtualenv_name=venv")
                .AddDirectoryExistsCheck($"{appOutputDir}/venv")
                .ToString();

            // Act
            var result = _dockerCli.Run(new DockerRunArguments
            {
                ImageId = _imageHelper.GetGitHubActionsBuildImage(),
                EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
                Volumes = new List<DockerVolume> { volume },
                CommandToExecuteOnRun = "/bin/bash",
                CommandArguments = new[] { "-c", script }
            });

            // Assert
            RunAsserts(
                () =>
                {
                    Assert.True(result.IsSuccess);
                },
                result.GetDebugInfo());
        }

        // [Fact, Trait("category", "githubactions")]
        // public void CanBuildAppWithCondaEnviornmentYmlFileHavingPipPackages()
        // {
        //     // Arrange
        //     var appName = "python-conda_pip";
        //     var volume = CreateCondaSampleAppVolume(appName);
        //     var appDir = volume.ContainerDir;
        //     var appOutputDir = "/tmp/app-output";
        //     var script = new ShellScriptBuilder()
        //         .AddBuildCommand($"{appDir} -o {appOutputDir} -p virtualenv_name=venv")
        //         .AddDirectoryExistsCheck($"{appOutputDir}/venv")
        //         // Following command makes sure that this package 'matplotlib' is present
        //         .AddCommand("source /opt/conda/etc/profile.d/conda.sh")
        //         .AddCommand($"conda activate {appOutputDir}/venv")
        //         .AddCommand("pip show matplotlib")
        //         .ToString();

        //     // Act
        //     var result = _dockerCli.Run(new DockerRunArguments
        //     {
        //         ImageId = _imageHelper.GetGitHubActionsBuildImage(),
        //         EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
        //         Volumes = new List<DockerVolume> { volume },
        //         CommandToExecuteOnRun = "/bin/bash",
        //         CommandArguments = new[] { "-c", script }
        //     });

        //     // Assert
        //     RunAsserts(
        //         () =>
        //         {
        //             Assert.True(result.IsSuccess);
        //         },
        //         result.GetDebugInfo());
        // }

        // [Fact, Trait("category", "githubactions")]
        // public void CanBuildJuliaPythonSampleApp()
        // {
        //     // Arrange
        //     var appName = "julia-python";
        //     var volume = CreateCondaSampleAppVolume(appName);
        //     var appDir = volume.ContainerDir;
        //     var appOutputDir = "/tmp/app-output";
        //     var script = new ShellScriptBuilder()
        //         .AddBuildCommand($"{appDir} -o {appOutputDir} -p virtualenv_name=venv")
        //         .AddDirectoryExistsCheck($"{appOutputDir}/venv")
        //         // Following command makes sure that this package 'matplotlib' is present
        //         .AddCommand("source /opt/conda/etc/profile.d/conda.sh")
        //         .AddCommand($"conda activate {appOutputDir}/venv")
        //         .AddCommand("pip show julia")
        //         .ToString();

        //     // Act
        //     var result = _dockerCli.Run(new DockerRunArguments
        //     {
        //         ImageId = _imageHelper.GetGitHubActionsBuildImage(),
        //         EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
        //         Volumes = new List<DockerVolume> { volume },
        //         CommandToExecuteOnRun = "/bin/bash",
        //         CommandArguments = new[] { "-c", script }
        //     });

        //     // Assert
        //     RunAsserts(
        //         () =>
        //         {
        //             Assert.True(result.IsSuccess);
        //         },
        //         result.GetDebugInfo());
        // }

        [Fact(Skip = "Skipping test temporarily"), Trait("category", "vso-focal")]
        public void CanBuildJupiterRiseApp()
        {
            // Arrange
            var appName = "jupyter-rise";
            var volume = CreateCondaSampleAppVolume(appName);
            var appDir = volume.ContainerDir;
            var appOutputDir = "/tmp/app-output";
            var script = new ShellScriptBuilder()
                .AddBuildCommand($"{appDir} -o {appOutputDir}")
                .AddDirectoryExistsCheck($"{appOutputDir}/venv")
                // Following command makes sure that this package 'matplotlib' is present
                .AddCommand("source /opt/conda/etc/profile.d/conda.sh")
                .AddCommand($"conda activate {appOutputDir}/venv")
                .AddCommand("pip show matplotlib")
                .ToString();

            // Act
            var result = _dockerCli.Run(new DockerRunArguments
            {
                ImageId = _imageHelper.GetVsoBuildImage(ImageTestHelperConstants.VsoFocal),
                EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
                Volumes = new List<DockerVolume> { volume },
                CommandToExecuteOnRun = "/bin/bash",
                CommandArguments = new[] { "-c", script }
            });

            // Assert
            RunAsserts(
                () =>
                {
                    Assert.True(result.IsSuccess);
                },
                result.GetDebugInfo());
        }

        [Theory(Skip = "Skipping test temporarily"), Trait("category", "vso-focal")]
        [InlineData("jupyter-rise")]
        public void BuildJupiterCondaApps_Prints_BuildCommands_In_File(string appName)
        {
            // Arrange
            var volume = CreateCondaSampleAppVolume(appName);
            var appDir = volume.ContainerDir;
            var appOutputDir = "/tmp/app1-output";
            var commandListFile = $"{appOutputDir}/{FilePaths.BuildCommandsFileName}";
            var script = new ShellScriptBuilder()
                .AddBuildCommand($"{appDir} -o {appOutputDir}")
                .AddFileExistsCheck($"{commandListFile}")
                .AddStringExistsInFileCheck("PlatformWithVersion=", $"{commandListFile}")
                .AddStringExistsInFileCheck("BuildCommands=", $"{commandListFile}")
                .ToString();

            // Act
            var result = _dockerCli.Run(new DockerRunArguments
            {
                ImageId = _imageHelper.GetVsoBuildImage(ImageTestHelperConstants.VsoFocal),
                EnvironmentVariables = new List<EnvironmentVariable> { CreateAppNameEnvVar(appName) },
                Volumes = new List<DockerVolume> { volume },
                CommandToExecuteOnRun = "/bin/bash",
                CommandArguments = new[] { "-c", script }
            });

            // Assert
            RunAsserts(
                () =>
                {
                    Assert.True(result.IsSuccess);
                },
                result.GetDebugInfo());
        }
    }
}
