using C4IT.Logging;
using System;
using System.Activities;
using System.ComponentModel;
using System.Reflection;
using static C4IT.Logging.cLogManager;
using Matrix42.Contracts.Platform.Data;
using Matrix42.ServiceRepository.Contracts.Components;
using Matrix42.Workflows.Contracts;
using System.Linq;
using Matrix42.Contracts.Platform.General;
using System.Json;
using Newtonsoft.Json;
using System.Collections.Generic;
using Matrix42.Workflows.Activities.Common.Data;
using System.Activities.Validation;
using System.Threading.Tasks;
using LiamWorkflowActivities;
using System.Runtime.CompilerServices;
using System.Security.Principal;
using static LiamAD.ADServiceGroupCreator;
using C4IT.LIAM;
using C4IT_IAM_Engine;

namespace C4IT.LIAM.Activities
{
    public class C4ITLIAMInitializeProviderActivity : cLIAMM42BaseActivity
    {
        [RequiredArgument]
        [Category("Input")]
        [DisplayName("Config Id")]
        public InArgument<Guid> ConfigID { get; set; }

        [RequiredArgument]
        [Category("Credentials")]
        public InArgument<SecureData> Password { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Message")]
        public OutArgument<string> Message { get; set; }

        [Category("Output")]
        [DisplayName("Error Code")]
        public OutArgument<string> ErrorCode { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {ConfigID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);
                ErrorCode.Set(context, string.Empty);
                Message.Set(context, string.Empty);

                SecureData secureData = Password.Get(context);
                var configEOID = ConfigID.Get(context);

                var dataMain = dataProvider.GetDataList(constFragmentNameConfigProviderMain,
                    "ID, [Expression-ObjectId] as EOID, GCCDomain, GCCTarget, GCCMaxDepth, " +
                    "GCCgroupLDAPFilter, GCCgroupOUPath, GCCPermissionGroupStrategy, GCCtargetType",
                    $"[Expression-ObjectId] = '{configEOID}'");

                Guid ConfigClassId = (Guid)dataMain.First()["ID"];
                var dataBase = dataProvider.GetDataList(constFragmentNameConfigProviderBase, "Account",
                    $"[Expression-ObjectID] = '{configEOID}'");
                var dataAdditional = dataProvider.GetDataList(constFragmentNameConfigProviderAdditionalAttributes, "Name, Value",
                    $"[Expression-ObjectID] = '{configEOID}'");
                var dataCustomTag = dataProvider.GetDataList(constFragmentNameCustomTagBase, "Key, Name",
                    $"[Expression-ObjectID] = '{configEOID}'");
                var dataNamingConvention = dataProvider.GetDataList(constFragmentNameConfigNamingConvention,
                    "ID, Usage, NamingConvention.Description as Description, NamingConvention.DescriptionTemplate as DescriptionTemplate, " +
                    "NamingConvention.Name as Name, NamingConvention.NamingTemplate as NamingTemplate, NamingConvention.Wildcard as Wildcard",
                    $"[Expression-ObjectID] = '{configEOID}'");

                var DataProvider = createProvider(dataMain.First(), dataBase.First(), dataAdditional, dataNamingConvention, dataCustomTag, secureData);

                var validLogon = DataProvider.LogonAsync().GetAwaiter().GetResult();
                if (validLogon)
                {
                    AddCache(ConfigClassId, configEOID, DataProvider);
                }
                else
                {
                    Message.Set(context, DataProvider.GetLastErrorMessage());
                    if (DataProvider is cLiamProviderExchange exProvider)
                        ErrorCode.Set(context, exProvider.GetLastErrorCode());
                    else
                        ErrorCode.Set(context, "WF_PROVIDER_LOGON_FAILED");
                }

                Success.Set(context, validLogon);
            }
            catch (Exception E)
            {
                LogException(E);
                Success.Set(context, false);
                ErrorCode.Set(context, "WF_ACTIVITY_EXCEPTION");
                Message.Set(context, E.Message);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMGetDataAreasFromProviderActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Output")]
        [DisplayName("DataAreas")]
        public OutArgument<JsonArray> DataAreas { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Error Code")]
        public OutArgument<string> ErrorCode { get; set; }

        [Category("Output")]
        [DisplayName("Error Message")]
        public OutArgument<string> ErrorMessage { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {ConfigID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);
                Success.Set(context, false);
                ErrorCode.Set(context, string.Empty);
                ErrorMessage.Set(context, string.Empty);

                var dataAreas = getDataAreasFromProvider(ConfigID.Get(context)).GetAwaiter().GetResult() ?? Enumerable.Empty<DataAreaEntry>();
                var dataAreaJson = dataAreas.Select(da => JsonValue.Parse(JsonConvert.SerializeObject(da)));
                DataAreas.Set(context, new JsonArray(dataAreaJson));
                Success.Set(context, true);

                if (!string.IsNullOrWhiteSpace(LastOperationErrorCode))
                {
                    Success.Set(context, false);
                    ErrorCode.Set(context, LastOperationErrorCode);
                    ErrorMessage.Set(context, LastOperationErrorMessage);
                }
            }
            catch (Exception E)
            {
                LogException(E);
                Success.Set(context, false);
                ErrorCode.Set(context, "WF_ACTIVITY_EXCEPTION");
                ErrorMessage.Set(context, E.Message);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMGetSecurityGroupsFromProviderActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Output")]
        [DisplayName("SecurityGroups")]
        public OutArgument<JsonArray> SecurityGroups { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Error Code")]
        public OutArgument<string> ErrorCode { get; set; }

        [Category("Output")]
        [DisplayName("Error Message")]
        public OutArgument<string> ErrorMessage { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {ConfigID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);
                Success.Set(context, false);
                ErrorCode.Set(context, string.Empty);
                ErrorMessage.Set(context, string.Empty);

                var securityGroups = getSecurityGroupsFromProvider(ConfigID.Get(context)).GetAwaiter().GetResult() ?? Enumerable.Empty<SecurityGroupEntry>();
                var securityGroupJson = securityGroups.Select(sg => JsonValue.Parse(JsonConvert.SerializeObject(sg)));
                SecurityGroups.Set(context, new JsonArray(securityGroupJson));
                Success.Set(context, true);

                if (!string.IsNullOrWhiteSpace(LastOperationErrorCode))
                {
                    Success.Set(context, false);
                    ErrorCode.Set(context, LastOperationErrorCode);
                    ErrorMessage.Set(context, LastOperationErrorMessage);
                }
            }
            catch (Exception E)
            {
                LogException(E);
                Success.Set(context, false);
                ErrorCode.Set(context, "WF_ACTIVITY_EXCEPTION");
                ErrorMessage.Set(context, E.Message);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMGetOwnersFromDataAreaActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("DataArea Id")]
        [RequiredArgument]
        public InArgument<Guid> DataAreaID { get; set; }

        [Category("Output")]
        [DisplayName("Owner User IDs")]
        public OutArgument<JsonArray> OwnerUserIDs { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {DataAreaID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);

                var ownersInfo = getOwnerInfosFromDataArea(DataAreaID.Get(context)).GetAwaiter().GetResult() ?? new List<cLiamUserInfo>();
                var owners = getPersonsFromUsers(ownersInfo) ?? new List<Guid>();
                var ownerJson = owners.Select(user => JsonValue.Parse(JsonConvert.SerializeObject(user)));
                OwnerUserIDs.Set(context, new JsonArray(ownerJson));
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMGrantPermissionActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("DataArea Id")]
        [RequiredArgument]
        public InArgument<Guid> DataAreaID { get; set; }

        [Category("Input")]
        [DisplayName("User Id")]
        [RequiredArgument]
        public InArgument<Guid> UserID { get; set; }

        [Category("Input")]
        [DisplayName("AccessType")]
        [RequiredArgument]
        public InArgument<Int32> AccessType { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {DataAreaID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);

                var result = grantPermission(DataAreaID.Get(context), UserID.Get(context), AccessType.Get(context), Guid.Empty).GetAwaiter().GetResult();
                Success.Set(context, result.Valid);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }
        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }
    public class C4ITLIAMCloneTeamActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Input")]
        [DisplayName("Team Id")]
        [RequiredArgument]
        public InArgument<string> TeamId { get; set; }

        [Category("Input")]
        [DisplayName("Name")]
        [RequiredArgument]
        public InArgument<string> Name { get; set; }

        [Category("Input")]
        [DisplayName("Description")]
        [RequiredArgument]
        public InArgument<string> Description { get; set; }

        [Category("Input")]
        [DisplayName("Visibility")]
        [RequiredArgument]
        public InArgument<Int32> Visibility { get; set; }

        [Category("Input")]
        [DisplayName("Parts to Clone")]
        [RequiredArgument]
        public InArgument<Int32> PartsToClone { get; set; }

        [Category("Input")]
        [DisplayName("Additional Members")]
        [RequiredArgument]
        public InArgument<string> AdditionalMembers { get; set; }

        [Category("Input")]
        [DisplayName("Additional Owners")]
        [RequiredArgument]
        public InArgument<string> AdditionalOwners { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("CreatedTeamId")]
        public OutArgument<Guid> CreatedTeamId { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {TeamId.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);

                var providerEntry = getDataProvider(ConfigID.Get(context));
                var result = LiamWorkflowRuntime.CloneTeamAsync(
                    providerEntry?.Provider,
                    TeamId.Get(context),
                    Name.Get(context),
                    Description.Get(context),
                    Visibility.Get(context),
                    PartsToClone.Get(context),
                    AdditionalMembers.Get(context),
                    AdditionalOwners.Get(context)).GetAwaiter().GetResult();
                Success.Set(context, result != null && result.Success);
                CreatedTeamId.Set(context, result?.CreatedTeamId ?? Guid.Empty);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMRevokePermissionActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("DataArea Id")]
        [RequiredArgument]
        public InArgument<Guid> DataAreaID { get; set; }

        [Category("Input")]
        [DisplayName("User Id")]
        [RequiredArgument]
        public InArgument<Guid> UserID { get; set; }

        [Category("Input")]
        [DisplayName("AccessType")]
        [RequiredArgument]
        public InArgument<Int32> AccessType { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}':", LogLevels.Info);
                LogEntry($"  Local server name: {Environment.MachineName}", LogLevels.Info);
                LogEntry($"  Activity input string: {DataAreaID.Get(context)}", LogLevels.Info);

                EnsureDataProviders(context);

                var result = revokePermission(DataAreaID.Get(context), UserID.Get(context), AccessType.Get(context), Guid.Empty).GetAwaiter().GetResult();
                Success.Set(context, result);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMCreateDistributionGroupActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Input")]
        [DisplayName("Name")]
        [RequiredArgument]
        public InArgument<string> Name { get; set; }

        [Category("Input")]
        [DisplayName("Alias")]
        [RequiredArgument]
        public InArgument<string> Alias { get; set; }

        [Category("Input")]
        [DisplayName("Distribution List Display Name")]
        public InArgument<string> DistributionListDisplayName { get; set; }

        [Category("Input")]
        [DisplayName("Primary SMTP Address")]
        public InArgument<string> PrimarySmtpAddress { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Object GUID")]
        public OutArgument<Guid> ObjectGuid { get; set; }

        [Category("Output")]
        [DisplayName("Created Groups")]
        public OutArgument<List<Tuple<string, string, string, string>>> CreatedGroups { get; set; }

        [Category("Output")]
        [DisplayName("Error Code")]
        public OutArgument<string> ErrorCode { get; set; }

        [Category("Output")]
        [DisplayName("Error Message")]
        public OutArgument<string> ErrorMessage { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}'", LogLevels.Info);

                EnsureDataProviders(context);
                ErrorCode.Set(context, string.Empty);
                ErrorMessage.Set(context, string.Empty);

                var entry = getDataProvider(ConfigID.Get(context));
                var result = LiamWorkflowRuntime.CreateDistributionGroup(
                    entry?.Provider,
                    Name.Get(context),
                    Alias.Get(context),
                    DistributionListDisplayName.Get(context),
                    PrimarySmtpAddress.Get(context));
                Success.Set(context, result.Success);
                ObjectGuid.Set(context, result.ObjectGuid);
                CreatedGroups.Set(context, result.CreatedGroups);
                ErrorCode.Set(context, result.ErrorCode);
                ErrorMessage.Set(context, result.ErrorMessage);
            }
            catch (Exception e)
            {
                LogException(e);
                Success.Set(context, false);
                ErrorCode.Set(context, "WF_ACTIVITY_EXCEPTION");
                ErrorMessage.Set(context, e.Message);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMCreateSharedMailboxActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Input")]
        [DisplayName("Name")]
        [RequiredArgument]
        public InArgument<string> Name { get; set; }

        [Category("Input")]
        [DisplayName("Alias")]
        [RequiredArgument]
        public InArgument<string> Alias { get; set; }

        [Category("Input")]
        [DisplayName("Shared Mailbox Display Name")]
        public InArgument<string> MailboxDisplayName { get; set; }

        [Category("Input")]
        [DisplayName("Primary SMTP Address")]
        public InArgument<string> PrimarySmtpAddress { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Object GUID")]
        public OutArgument<Guid> ObjectGuid { get; set; }

        [Category("Output")]
        [DisplayName("Created Groups")]
        public OutArgument<List<Tuple<string, string, string, string>>> CreatedGroups { get; set; }

        [Category("Output")]
        [DisplayName("Error Code")]
        public OutArgument<string> ErrorCode { get; set; }

        [Category("Output")]
        [DisplayName("Error Message")]
        public OutArgument<string> ErrorMessage { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}'", LogLevels.Info);

                EnsureDataProviders(context);
                ErrorCode.Set(context, string.Empty);
                ErrorMessage.Set(context, string.Empty);

                var entry = getDataProvider(ConfigID.Get(context));
                var result = LiamWorkflowRuntime.CreateSharedMailbox(
                    entry?.Provider,
                    Name.Get(context),
                    Alias.Get(context),
                    MailboxDisplayName.Get(context),
                    PrimarySmtpAddress.Get(context));
                Success.Set(context, result.Success);
                ObjectGuid.Set(context, result.ObjectGuid);
                CreatedGroups.Set(context, result.CreatedGroups);
                ErrorCode.Set(context, result.ErrorCode);
                ErrorMessage.Set(context, result.ErrorMessage);
            }
            catch (Exception e)
            {
                LogException(e);
                Success.Set(context, false);
                ErrorCode.Set(context, "WF_ACTIVITY_EXCEPTION");
                ErrorMessage.Set(context, e.Message);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMCreateADServiceGroupActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Input")]
        [DisplayName("Service Name")]
        [RequiredArgument]
        public InArgument<string> ServiceName { get; set; }

        [Category("Input")]
        [DisplayName("Description")]
        public InArgument<string> Description { get; set; }

        // Neu: Integer statt Enum
        [Category("Input")]
        [DisplayName("Group Scope (2=Global, 4=Local, 8=Universal)")]
        public InArgument<int> GroupScope { get; set; }

        [Category("Input")]
        [DisplayName("Group Type (1=Distribution Group, 0=Security/General)")]
        public InArgument<int> GroupType { get; set; }

        [Category("Input")]
        [DisplayName("Owner SIDs (optional)")]
        public InArgument<IEnumerable<string>> OwnerSids { get; set; }

        [Category("Input")]
        [DisplayName("Member SIDs (optional)")]
        public InArgument<IEnumerable<string>> MemberSids { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Created Groups")]
        public OutArgument<List<Tuple<string, string, string, string>>> CreatedGroups { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            if (!IsInitialized) Initialize(context);
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                LogEntry($"Executing activity '{GetType().Name}'", LogLevels.Info);
                EnsureDataProviders(context);

                var entry = getDataProvider(ConfigID.Get(context));
                if (entry?.Provider is cLiamProviderAD adProv)
                {
                    var svcName = ServiceName.Get(context);
                    var desc = Description.Get(context);

                    // 1) Scope-Bit auslesen oder Default (8 = Universal)
                    int scopeBit = GroupScope.Expression != null
                        ? GroupScope.Get(context)
                        : 8;
                    eLiamAccessRoleScopes scopeEnum;
                    switch (scopeBit)
                    {
                        case 2:
                            scopeEnum = eLiamAccessRoleScopes.Global;
                            break;
                        case 4:
                            scopeEnum = eLiamAccessRoleScopes.DomainLocal;
                            break;
                        case 8:
                            scopeEnum = eLiamAccessRoleScopes.Universal;
                            break;
                        default:
                            throw new ArgumentOutOfRangeException(
                                nameof(scopeBit), $"Ungültiger Gruppenbereich: {scopeBit}");
                    }

                    // 2) Type-Bit auslesen oder Default (1 = Distribution)
                    int typeBit = GroupType.Expression != null
                        ? GroupType.Get(context)
                        : 1;
                    ADGroupType typeEnum;
                    switch (typeBit)
                    {
                        case 1:
                            typeEnum = ADGroupType.Distribution;
                            break;
                        case 0:
                            typeEnum = ADGroupType.Security;
                            break;
                        default:
                            throw new ArgumentOutOfRangeException(
                                nameof(typeBit), $"Ungültiger Gruppentyp: {typeBit}");
                    }

                    var ownerList = OwnerSids.Expression != null ? OwnerSids.Get(context) : null;
                    var memberList = MemberSids.Expression != null ? MemberSids.Get(context) : null;

                    var result = LiamWorkflowRuntime.CreateAdServiceGroups(
                        adProv,
                        svcName,
                        desc,
                        scopeEnum,
                        typeEnum,
                        ownerList,
                        memberList);
                    Success.Set(context, result.Success);
                    CreatedGroups.Set(context, result.CreatedGroups);
                }
                else
                {
                    Success.Set(context, false);
                }
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }
        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }

    public class C4ITLIAMCreateDataAreaActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }
        [RequiredArgument] public InArgument<string> NewFolderPath { get; set; }
        [RequiredArgument] public InArgument<string> ParentFolderPath { get; set; }
        [Category("Output")][DisplayName("Result")] public OutArgument<JsonValue> ResultToken { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            EnsureDataProviders(context);
            var cfgId = ConfigID.Get(context);
            var provider = getDataProvider(cfgId)?.Provider;
            var result = LiamWorkflowRuntime.CreateDataAreaAsync(
                provider,
                NewFolderPath.Get(context),
                ParentFolderPath.Get(context),
                /*customTags*/null,
                /*ownerSids*/null,
                /*readerSids*/null,
                /*writerSids*/null
            ).GetAwaiter().GetResult();
            ResultToken.Set(context, JsonValue.Parse(JsonConvert.SerializeObject(result.ResultToken)));
        }
        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }

    }

    public class C4ITLIAMEnsureNtfsPermissionGroupsActivity : cLIAMM42BaseActivity
    {
        [Category("Input")]
        [DisplayName("Config Id")]
        [RequiredArgument]
        public InArgument<Guid> ConfigID { get; set; }

        [Category("Input")]
        [DisplayName("Path")]
        [RequiredArgument]
        public InArgument<string> FolderPath { get; set; }

        [Category("Input")]
        [DisplayName("Owner SIDs")]
        public InArgument<IEnumerable<string>> OwnerSids { get; set; }

        [Category("Input")]
        [DisplayName("Reader SIDs")]
        public InArgument<IEnumerable<string>> ReaderSids { get; set; }

        [Category("Input")]
        [DisplayName("Writer SIDs")]
        public InArgument<IEnumerable<string>> WriterSids { get; set; }

        [Category("Input")]
        [DisplayName("Ensure Traverse")]
        public InArgument<bool> EnsureTraverse { get; set; }

        [Category("Output")]
        [DisplayName("Success")]
        public OutArgument<bool> Success { get; set; }

        [Category("Output")]
        [DisplayName("Result")]
        public OutArgument<JsonValue> ResultToken { get; set; }

        protected override void Execute(NativeActivityContext context)
        {
            EnsureDataProviders(context);

            var cfgId = ConfigID.Get(context);
            var ownerSids = OwnerSids.Expression != null ? OwnerSids.Get(context) : null;
            var readerSids = ReaderSids.Expression != null ? ReaderSids.Get(context) : null;
            var writerSids = WriterSids.Expression != null ? WriterSids.Get(context) : null;

            var providerEntry = getDataProvider(cfgId);
            var result = LiamWorkflowRuntime.EnsureNtfsPermissionGroupsAsync(
                providerEntry?.Provider,
                FolderPath.Get(context),
                null,
                ownerSids,
                readerSids,
                writerSids,
                EnsureTraverse.Get(context)).GetAwaiter().GetResult();

            Success.Set(context, result.Success);
            ResultToken.Set(context, JsonValue.Parse(JsonConvert.SerializeObject(result.ResultToken)));
        }

        private void EnsureDataProviders(NativeActivityContext context)
        {
            if (executor == null)
                executor = context.GetExtension<IExtensionExecutor>();
            if (schemaReader == null)
                schemaReader = executor.Get<ISchemaReaderProvider>();
            if (dataProvider == null)
                dataProvider = executor.Get<IDataReaderProvider>();
        }
    }
}

