private static async Task <PnPContext> VerifySiteStatusAsync(PnPContext context, string urlOrGroupToCheck, SiteCreationModel siteCreationModel, int maxStatusChecks, int waitAfterStatusCheck)
        {
            var siteCreated        = false;
            var siteUrl            = string.Empty;
            var statusCheckAttempt = 1;
            int lastSiteStatus     = -1;

            string apiCall;

            if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate)
            {
                apiCall = $"_api/SPSiteManager/status?url='{HttpUtility.UrlEncode(urlOrGroupToCheck)}'";
            }
            else
            {
                apiCall = $"_api/groupsitemanager/GetSiteStatus('{urlOrGroupToCheck}')";
            }

            do
            {
                if (statusCheckAttempt > 1)
                {
                    await context.WaitAsync(TimeSpan.FromSeconds(statusCheckAttempt *waitAfterStatusCheck)).ConfigureAwait(false);
                }

                try
                {
                    var result       = await(context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest), HttpMethod.Get).ConfigureAwait(false);
                    var responseJson = JsonSerializer.Deserialize <JsonElement>(result.Json);

                    #region Json response

                    /*
                     * {
                     *  "d": {
                     *      "Status": {
                     *          "__metadata": {
                     *              "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse"
                     *          },
                     *          "SiteId": "b1ec46e2-c26a-423f-ab01-3aeb951c1c82",
                     *          "SiteStatus": 2,
                     *          "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1"
                     *      }
                     *  }
                     * }
                     */
                    #endregion

                    int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32();
                    lastSiteStatus = siteStatus;
                    if (siteStatus == 2)
                    {
                        siteCreated = true;
                        siteUrl     = responseJson.GetProperty("SiteUrl").GetString();
                    }
                }
                catch (Exception ex)
                {
                    // Log and eat exception here
                    context.Logger.LogWarning(PnPCoreAdminResources.Log_Warning_ExceptionWhileGettingSiteStatus, urlOrGroupToCheck, ex.ToString());
                }

                statusCheckAttempt++;
            }while (!siteCreated && statusCheckAttempt <= maxStatusChecks);

            if (siteCreated)
            {
                return(await context.CloneAsync(new Uri(siteUrl)).ConfigureAwait(false));
            }
            else
            {
                throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreationStatusCheck, siteUrl, lastSiteStatus));
            }
        }
        private static async Task <PnPContext> CreateSiteUsingSpoRestImplementationAsync(PnPContext context, SiteCreationModel siteCreationModel, Dictionary <string, object> payload, SiteCreationOptions creationOptions)
        {
            string apiCall;
            string body;

            if (siteCreationModel == SiteCreationModel.SPSiteManagerCreate)
            {
                apiCall = $"_api/SPSiteManager/Create";
                var json = new { request = payload }.AsExpando();
                body = JsonSerializer.Serialize(json, typeof(ExpandoObject));
            }
            else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupEx)
            {
                apiCall = $"_api/GroupSiteManager/CreateGroupEx";
                body    = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase);
            }
            else if (siteCreationModel == SiteCreationModel.GroupSiteManagerCreateGroupForSite)
            {
                apiCall = $"_api/GroupSiteManager/CreateGroupForSite";
                body    = JsonSerializer.Serialize(payload, PnPConstants.JsonSerializer_IgnoreNullValues_CamelCase);
            }
            else
            {
                throw new ClientException(ErrorType.Unsupported, "The requested site creation model does not exist");
            }

            var result = await(context.Web as Web).RawRequestAsync(new ApiCall(apiCall, ApiType.SPORest, body), HttpMethod.Post).ConfigureAwait(false);

            var responseJson = JsonSerializer.Deserialize <JsonElement>(result.Json);

            #region Json Response

            /*
             * Success => SiteStatus = 2
             * Provisioning => SiteStatus = 1
             * Error => all other values
             *
             * {
             *  "d": {
             *      "Create": {
             *          "__metadata": {
             *              "type": "Microsoft.SharePoint.Portal.SPSiteCreationResponse"
             *          },
             *          "SiteId": "12befc2b-4c17-46a4-985e-530e6745cf35",
             *          "SiteStatus": 2,
             *          "SiteUrl": "https://bertonline.sharepoint.com/sites/pnpcoresdktestcommsite1"
             *      }
             *  }
             * }
             *
             */
            #endregion

            int siteStatus = responseJson.GetProperty("SiteStatus").GetInt32();

            PnPContext responseContext;
            if (siteStatus == 2)
            {
                // Site creation succeeded
                responseContext = await context.CloneAsync(new Uri(responseJson.GetProperty("SiteUrl").ToString())).ConfigureAwait(false);
            }
            else if (siteStatus == 1)
            {
                Guid groupId = Guid.Empty;
                if (siteCreationModel != SiteCreationModel.SPSiteManagerCreate)
                {
                    groupId = responseJson.GetProperty("GroupId").GetGuid();
                }

                // Site creation in progress, let's wait for it to finish
                responseContext = await VerifySiteStatusAsync(context, siteCreationModel != SiteCreationModel.SPSiteManagerCreate?groupId.ToString() : payload["Url"].ToString(),
                                                                  siteCreationModel, creationOptions.MaxStatusChecks.Value, creationOptions.WaitAfterStatusCheck.Value).ConfigureAwait(false);
            }
            else
            {
                // Something went wrong
                throw new ClientException(ErrorType.SharePointRestServiceError, string.Format(PnPCoreAdminResources.Exception_SiteCreation, payload["Url"].ToString(), siteStatus));
            }

            // Apply our "wait" strategy
            if (creationOptions.WaitAfterCreation.HasValue && creationOptions.WaitAfterCreation.Value > 0)
            {
                await responseContext.WaitAsync(TimeSpan.FromSeconds(creationOptions.WaitAfterCreation.Value)).ConfigureAwait(false);
            }
            else
            {
                if (creationOptions.WaitForAsyncProvisioning.HasValue && creationOptions.WaitForAsyncProvisioning.Value)
                {
                    // Let's wait for the async provisioning of features, site scripts and content types to be done before we allow API's to further update the created site
                    await WaitForProvisioningToCompleteAsync(responseContext, creationOptions).ConfigureAwait(false);
                }
            }

            return(responseContext);
        }