﻿using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure;
using Microsoft.Azure.Management.Resources;
using Microsoft.Azure.Management.Resources.Models;
using Microsoft.Deployment.Common.ActionModel;
using Microsoft.Deployment.Common.Actions;
using Microsoft.Deployment.Common.Enums;
using Microsoft.Deployment.Common.ErrorCode;
using Microsoft.Deployment.Common.Helpers;
using Microsoft.Deployment.Common.Model;
using Newtonsoft.Json.Linq;

namespace Microsoft.Deployment.Actions.AzureCustom.HCL
{
    [Export(typeof(IAction))]
    public class CreateAzureMLWorkspace : BaseAction
    {
        public override async Task<ActionResponse> ExecuteActionAsync(ActionRequest request)
        {
            var azureToken = request.DataStore.GetJson("AzureToken")["access_token"].ToString();
            var subscription = request.DataStore.GetJson("SelectedSubscription")["SubscriptionId"].ToString();
            var resourceGroup = request.DataStore.GetValue("SelectedResourceGroup");
            var location = request.DataStore.GetJson("SelectedLocation")["Name"].ToString();
            var deploymentName = request.DataStore.GetValue("DeploymentName");

            var mlWorkspaceName = request.DataStore.GetValue("mlWorkspaceName");
            //var storageAccountName = request.DataStore.GetValue("storageAccountName");            
            var tagName_mlWorkspaceName = request.DataStore.GetValue("tagName_mlWorkspaceName");

            var storageAccountName = request.DataStore.GetValue("storageAccountName");
            var storageAccountType = request.DataStore.GetValue("storageAccountType");
            var encryptionEnabled = request.DataStore.GetValue("storageAccountEncryptionEnabled");
            var tagName_storageAccountName = request.DataStore.GetValue("tagName_storageAccountName");

            foreach (var item in ListDeployedItems)
            {
                if (item.ToString() == deploymentName)
                    return new ActionResponse(ActionStatus.Success);
            }

            SubscriptionCloudCredentials creds = new TokenCloudCredentials(subscription, azureToken);
            ResourceManagementClient client = new ResourceManagementClient(creds);

            var param = new AzureArmParameterGenerator();
            param.AddStringParam("mlWorkspaceName", mlWorkspaceName);
            param.AddStringParam("storageAccountName", storageAccountName);
            param.AddStringParam("subscription", subscription);
            param.AddStringParam("resourceGroup", resourceGroup);
            param.AddStringParam("encryptionEnabled", encryptionEnabled);
            param.AddStringParam("location", location);
            param.AddStringParam("storageAccountType", storageAccountType);

            var armTemplate = JsonUtility.GetJObjectFromJsonString(System.IO.File.ReadAllText(Path.Combine(request.Info.App.AppFilePath, "Service/AzureML/MLWorkspace.json")));
            var armParamTemplate = JsonUtility.GetJObjectFromObject(param.GetDynamicObject());

            armTemplate.Remove("parameters");
            armTemplate.Add("parameters", armParamTemplate["parameters"]);



            var deployment = new Azure.Management.Resources.Models.Deployment()
            {
                Properties = new DeploymentPropertiesExtended()
                {
                    Template = armTemplate.ToString(),
                    Parameters = JsonUtility.GetEmptyJObject().ToString()
                }
            };

            var validate = await client.Deployments.ValidateAsync(resourceGroup, deploymentName, deployment, new CancellationToken());
            if (!validate.IsValid)
            {
                return new ActionResponse(ActionStatus.Failure, JsonUtility.GetJObjectFromObject(validate), null,
                     DefaultErrorCodes.DefaultErrorCode, $"Azure:{validate.Error.Message} Details:{validate.Error.Details}");
            }

            var deploymentItem = await client.Deployments.CreateOrUpdateAsync(resourceGroup, deploymentName, deployment, new CancellationToken());

            request.DataStore.AddToDataStore(tagName_mlWorkspaceName, mlWorkspaceName);
            request.DataStore.AddToDataStore(tagName_storageAccountName, storageAccountName);
            ListDeployedItems.Add(deploymentName);
            return new ActionResponse(ActionStatus.Success, deploymentItem);
        }
    }
}
