// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Win32;

namespace Microsoft.CmdPal.UI.Helpers;

internal enum GpoRuleConfiguredValue
{
    WrongValue = -3,
    Unavailable = -2,
    NotConfigured = -1,
    Disabled = 0,
    Enabled = 1,
}

/*
 * Contains methods extracted from PowerToys gpo.h
 * The idea is to keep CmdPal codebase take as little dependences on the PowerToys codebase as possible.
 * Having this class to check GPO being contained in CmdPal means we don't need to depend on GPOWrapper.
 */
internal static class GpoValueChecker
{
    private const string PoliciesPath = @"SOFTWARE\Policies\PowerToys";
    private static readonly RegistryKey PoliciesScopeMachine = Registry.LocalMachine;
    private static readonly RegistryKey PoliciesScopeUser = Registry.CurrentUser;
    private const string PolicyConfigureEnabledCmdPal = @"ConfigureEnabledUtilityCmdPal";
    private const string PolicyConfigureEnabledGlobalAllUtilities = @"ConfigureGlobalUtilityEnabledState";

    private static GpoRuleConfiguredValue GetConfiguredValue(string registryValueName)
    {
        // For GPO policies, machine scope should take precedence over user scope
        var value = ReadRegistryValue(PoliciesScopeMachine, PoliciesPath, registryValueName);

        if (!value.HasValue)
        {
            // If not found in machine scope, check user scope
            value = ReadRegistryValue(PoliciesScopeUser, PoliciesPath, registryValueName);
            if (!value.HasValue)
            {
                return GpoRuleConfiguredValue.NotConfigured;
            }
        }

        return value switch
        {
            0 => GpoRuleConfiguredValue.Disabled,
            1 => GpoRuleConfiguredValue.Enabled,
            _ => GpoRuleConfiguredValue.WrongValue,
        };
    }

    // Reads an integer registry value if it exists.
    private static int? ReadRegistryValue(RegistryKey rootKey, string subKeyPath, string valueName)
    {
        using (RegistryKey? key = rootKey.OpenSubKey(subKeyPath, false))
        {
            if (key is null)
            {
                return null;
            }

            var value = key.GetValue(valueName);
            if (value is int intValue)
            {
                return intValue;
            }

            return null;
        }
    }

    private static GpoRuleConfiguredValue GetUtilityEnabledValue(string utilityName)
    {
        var individualValue = GetConfiguredValue(utilityName);

        if (individualValue == GpoRuleConfiguredValue.Disabled || individualValue == GpoRuleConfiguredValue.Enabled)
        {
            return individualValue;
        }
        else
        {
            // If the individual utility value is not set, check the global all utilities policy value.
            return GetConfiguredValue(PolicyConfigureEnabledGlobalAllUtilities);
        }
    }

    internal static GpoRuleConfiguredValue GetConfiguredCmdPalEnabledValue()
    {
        return GetUtilityEnabledValue(PolicyConfigureEnabledCmdPal);
    }
}
