using System;
using System.Collections.Generic;
using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using Xunit;

namespace GitHub.Runner.Common.Tests.Util
{
    public class NodeUtilL0
    {
        // We're testing the logic with feature flags
        [Theory]
        [InlineData(false, false, false, false, "node20", false)] // Phase 1: No env vars
        [InlineData(false, false, false, true, "node20", false)]  // Phase 1: Allow unsecure (redundant)
        [InlineData(false, false, true, false, "node24", false)]  // Phase 1: Force node24
        [InlineData(false, false, true, true, "node20", true)]    // Phase 1: Both flags (use phase default + warning)
        [InlineData(false, true, false, false, "node24", false)]  // Phase 2: No env vars
        [InlineData(false, true, false, true, "node20", false)]   // Phase 2: Allow unsecure
        [InlineData(false, true, true, false, "node24", false)]   // Phase 2: Force node24 (redundant)
        [InlineData(false, true, true, true, "node24", true)]     // Phase 2: Both flags (use phase default + warning)
        [InlineData(true, false, false, false, "node24", false)]  // Phase 3: Always Node 24 regardless of env vars
        [InlineData(true, false, false, true, "node24", false)]   // Phase 3: Always Node 24 regardless of env vars
        [InlineData(true, false, true, false, "node24", false)]   // Phase 3: Always Node 24 regardless of env vars
        [InlineData(true, false, true, true, "node24", false)]     // Phase 3: Always Node 24 regardless of env vars, no warnings in Phase 3
        public void TestNodeVersionLogic(bool requireNode24, bool useNode24ByDefault, bool forceNode24, bool allowUnsecureNode, string expectedVersion, bool expectWarning)
        {
            try
            {
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.ForceNode24Variable, forceNode24 ? "true" : null);
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.AllowUnsecureNodeVersionVariable, allowUnsecureNode ? "true" : null);

                // Call the actual method
                var (actualVersion, warningMessage) = NodeUtil.DetermineActionsNodeVersion(null, useNode24ByDefault, requireNode24);

                // Assert
                Assert.Equal(expectedVersion, actualVersion);

                if (expectWarning)
                {
                    Assert.NotNull(warningMessage);
                    Assert.Contains("Both", warningMessage);
                    Assert.Contains("are set to true", warningMessage);
                }
                else
                {
                    Assert.Null(warningMessage);
                }
            }
            finally
            {
                // Cleanup
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.ForceNode24Variable, null);
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.AllowUnsecureNodeVersionVariable, null);
            }
        }

        [Theory]
        [InlineData(false, false, false, false, false, true, "node20", false)]   // Phase 1: System env: none, Workflow env: allow=true
        [InlineData(false, false, true, false, false, false, "node24", false)]   // Phase 1: System env: force node24, Workflow env: none
        [InlineData(false, true, false, false, true, false, "node24", false)]    // Phase 1: System env: none, Workflow env: force node24
        [InlineData(false, false, false, true, false, true, "node20", false)]    // Phase 1: System env: allow=true, Workflow env: allow=true (workflow takes precedence)
        [InlineData(false, false, true, true, false, false, "node20", true)]    // Phase 1: System env: both true, Workflow env: none (use phase default + warning)
        [InlineData(false, false, false, false, true, true, "node20", true)]     // Phase 1: System env: none, Workflow env: both (use phase default + warning)
        [InlineData(true, false, false, false, false, false, "node24", false)]   // Phase 2: System env: none, Workflow env: none
        [InlineData(true, false, false, true, false, false, "node20", false)]    // Phase 2: System env: allow=true, Workflow env: none
        [InlineData(true, false, false, false, false, true, "node20", false)]    // Phase 2: System env: none, Workflow env: allow unsecure
        [InlineData(true, false, true, false, false, true, "node20", false)]     // Phase 2: System env: force node24, Workflow env: allow unsecure
        [InlineData(true, false, true, true, false, false, "node24", true)]    // Phase 2: System env: both true, Workflow env: none (use phase default + warning)
        [InlineData(true, false, false, false, true, true, "node24", true)]      // Phase 2: System env: none, Workflow env: both (phase default + warning)
        [InlineData(false, true, false, false, false, true, "node24", false)]    // Phase 3: System env: none, Workflow env: allow=true (always Node 24 in Phase 3)
        [InlineData(false, true, true, true, false, false, "node24", false)]     // Phase 3: System env: both true, Workflow env: none (always Node 24 in Phase 3, no warning)
        [InlineData(false, true, false, false, true, true, "node24", false)]      // Phase 3: System env: none, Workflow env: both (always Node 24 in Phase 3, no warning)
        public void TestNodeVersionLogicWithWorkflowEnvironment(bool useNode24ByDefault, bool requireNode24,
            bool systemForceNode24, bool systemAllowUnsecure,
            bool workflowForceNode24, bool workflowAllowUnsecure,
            string expectedVersion, bool expectWarning)
        {
            try
            {
                // Set system environment variables
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.ForceNode24Variable, systemForceNode24 ? "true" : null);
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.AllowUnsecureNodeVersionVariable, systemAllowUnsecure ? "true" : null);

                // Set workflow environment variables
                var workflowEnv = new Dictionary<string, string>();
                if (workflowForceNode24)
                {
                    workflowEnv[Constants.Runner.NodeMigration.ForceNode24Variable] = "true";
                }
                if (workflowAllowUnsecure)
                {
                    workflowEnv[Constants.Runner.NodeMigration.AllowUnsecureNodeVersionVariable] = "true";
                }

                // Call the actual method with our test parameters
                var (actualVersion, warningMessage) = NodeUtil.DetermineActionsNodeVersion(workflowEnv, useNode24ByDefault, requireNode24);

                // Assert
                Assert.Equal(expectedVersion, actualVersion);

                if (expectWarning)
                {
                    Assert.NotNull(warningMessage);
                    Assert.Contains("Both", warningMessage);
                    Assert.Contains("are set to true", warningMessage);
                }
                else
                {
                    Assert.Null(warningMessage);
                }
            }
            finally
            {
                // Cleanup
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.ForceNode24Variable, null);
                Environment.SetEnvironmentVariable(Constants.Runner.NodeMigration.AllowUnsecureNodeVersionVariable, null);
            }
        }
    }
}
