using System;
using System.Collections.Generic;
using System.Linq;
using BO.AppServer.Metadata.Enums;
using BO.Console.Commands.Base;
using BO.Console.Commands.Enums;
using Quadarax.Foundation.Core.QConsole;
using Quadarax.Foundation.Core.QConsole.Argument;
using Quadarax.Foundation.Core.QConsole.Attributes;
using Quadarax.Foundation.Core.QConsole.Value;
using Quadarax.Foundation.Core.Value;
using Quadarax.Foundation.Core.Value.Extensions;
// ReSharper disable InconsistentNaming

namespace BO.Console.Commands.User
{
    [CommandDefinition]
    internal class UserGetAPIKeyCommand : AbstractGetCommand
    {
        #region *** Constants ***
        private const string CS_CMD_USERGET_NAME = "user_getapikey";
        private const string CS_CMD_USERGET_DESCR = "Get default single user workspace api-key or api-password and process result. Should be run as Administrator.";

        private const string CS_ARG_NAME_TYPE = "outt";
        private const string CS_ARG_HINT_TYPE = "<output_target>";
        private const string CS_ARG_DESC_TYPE = "Defines output target (no - none, clp - clipboard,var - env. variable). Default is no.";



        private const string CS_ARG_NAME_VALUE = "vt";
        private const string CS_ARG_HINT_VALUE = "<value_type>";
        private const string CS_ARG_DESC_VALUE = "Defines value type to return (apikey,apipwd,apiboth). Default is apiboth.";

        private const string CS_ENV_VAR_VALUE_KEY = "bo_apikey";
        private const string CS_ENV_VAR_VALUE_PWD = "bo_apipwd";
        #endregion

        #region *** Properties ***

        public override string Name => CS_CMD_USERGET_NAME;
        public override string Description => CS_CMD_USERGET_DESCR;

        private OutputTargetEnum Target { get; set; }
        private ValueTypeApiKeyEnum ValueType { get; set; }
        #endregion

        #region *** Constructor ***
        public UserGetAPIKeyCommand(Engine engine) : base(engine)
        {
        }
        #endregion

        #region *** EXECUTE ***
        protected override Result OnExecute()
        {
            var user = Client.GetUserAsync(IdentificationType, IdentificationValue).Result;
            WriteInfo($"User '{user.Name}' [{user.Id}] validated (Created:{user.Created.ToFileShortDateTimeString()}, Logged:{user.LastLogged?.ToFileShortDateTimeString()})  ");
            var workspaces = Client.GetWorkspacesAsync(WorkspaceScopeEnums.MyDefault, user.Name).Result;
            if (!workspaces.Any())
                throw new Exception($"No default workspace for user '{user.Name}' set.");
            var workspace = workspaces.First();
            WriteInfo($"User has default workspace named '{workspace.Name}' [{workspace.Id}] (Created:{workspace.Audit.Created.ToFileShortDateTimeString()}, Changed:{workspace.Audit.Changed?.ToFileShortDateTimeString()})");
            WriteCaption($"APIKey: {workspace.ApiKeyNormalized}");
            WriteInfo($"APIPassword: {workspace.Apipassword}");
            var value = ValueType == ValueTypeApiKeyEnum.ApiKey
                ? workspace.ApiKeyNormalized
                : ValueType == ValueTypeApiKeyEnum.ApiPwd ? workspace.Apipassword : workspace.ApiKeyNormalized + ";" + workspace.Apipassword;
            switch (Target)
            {
                case OutputTargetEnum.No:
                    WriteCaption("No output target set.");
                    break;
                case OutputTargetEnum.Clp:
                    TextCopy.ClipboardService.SetText(value);
                    WriteCaption($"Value '{value}' was set to clipboard.");
                    break;
                case OutputTargetEnum.Var:
                    WriteWarning("This feature must run in Administration mode (as Administrator).");

                    if (ValueType == ValueTypeApiKeyEnum.ApiKey || ValueType == ValueTypeApiKeyEnum.ApiBoth)
                    {
                        Environment.SetEnvironmentVariable(CS_ENV_VAR_VALUE_KEY, workspace.ApiKeyNormalized, EnvironmentVariableTarget.Process);
                        WriteCaption($"Value '{workspace.ApiKeyNormalized}' was set to environment value '{CS_ENV_VAR_VALUE_KEY}' in scope current process.");
                    }

                    if (ValueType == ValueTypeApiKeyEnum.ApiPwd || ValueType == ValueTypeApiKeyEnum.ApiBoth)
                    {

                        Environment.SetEnvironmentVariable(CS_ENV_VAR_VALUE_PWD, workspace.Apipassword, EnvironmentVariableTarget.Process);
                        WriteCaption($"Value '{workspace.Apipassword}' was set to environment value '{CS_ENV_VAR_VALUE_PWD}' in scope current process.");
                    }

                    WriteInfo($"To use environment value: use %{CS_ENV_VAR_VALUE_KEY}% and/or %{CS_ENV_VAR_VALUE_PWD}%");
                    break;
            }
            return new Result();
        }
        #endregion

        #region *** Private Overrides ***
        protected override void OnValidateArguments()
        {
            base.OnValidateArguments();
            ValidateArgumentValueEnum<OutputTargetEnum>(CS_ARG_NAME_TYPE);
            ValidateArgumentValueEnum<ValueTypeApiKeyEnum>(CS_ARG_NAME_VALUE);

            Target = GetArgumentValueOrDefault<OutputTargetEnum>(CS_ARG_NAME_TYPE);
            ValueType = GetArgumentValueOrDefault<ValueTypeApiKeyEnum>(CS_ARG_NAME_VALUE);
        }

        protected override IEnumerable<AbstractArgument> OnSetupArguments()
        {
            var args = base.OnSetupArguments().ToList();
            args.Add(new NamedArgument(CS_ARG_NAME_TYPE, CS_ARG_DESC_TYPE, CS_ARG_HINT_TYPE, TypeValuesEnum.String, "no", false));
            args.Add(new NamedArgument(CS_ARG_NAME_VALUE, CS_ARG_DESC_VALUE, CS_ARG_HINT_VALUE, TypeValuesEnum.String, "apiboth", false));
            return args;
        }

        #endregion

        #region *** Private operations ***
        #endregion
    }
}
