[CmdletBinding()]
param
(
    [Parameter(Mandatory = $false)]
    [object] $WebhookData
)

function Get-ITDVMwareSharePointSnapshotRequestList {
    [CmdletBinding()]
    Param
    (
        [PSCredential]
        $Credential
    )

    begin {
        $InvokeWebRequestParams = @{ }
        If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
        Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }

        $URL = "https://testshare.nd.gov/itd/Computer-Systems/Distributed-Systems/VMWare/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,Status,NotifyEmail&$expand=Author/Id'
        $InvokeWebRequestParams += @{
            Uri     = $URL
            Method  = "Get"
            Headers = @{ "Accept" = "application/json;odata=verbose" }
        }
    
        $List = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json  
    }

    process {
    
    }

    end {
        $List.d.results
    }
}

If ($WebhookData) {
    If ($WebhookData.RequestHeader.ITD -eq 'HAKpueFYU4L3NMXTKqtHssnNGBrew3gVRLEq2Yi7yzWW8fpKNCPB5gUcnHfr9sdhXC53y7gWf5BDtxXkr3mZA3NV7DszpR3kjiLgi3FpRPgUWus9ZxCWy63znqPGh3AJ2bn43uP7GjzfLcgqYLQRkir') {
        Write-Verbose "Header has required data"
    }
    Else {
        Write-Error "Header missing required data"
        exit;
    }

    $InputParams = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)
    $vCenterCredential = Get-AutomationPSCredential -Name 'VMware Auto' 
    $SharePointCredential = Get-AutomationPSCredential -Name 'SharePoint IaaS ReadWrite'

    Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -ParticipateInCeip $false -Confirm:$false

    $UrlContextInfo = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/contextinfo"
    $InvokeWebRequestParams = @{
        Uri             = $UrlContextInfo;
        Method          = "Post";
        UseBasicParsing = $true;
        Credential      = $SharePointCredential;
    }
    $RequestDigest = Invoke-RestMethod @InvokeWebRequestParams
    $RequestDigest = $RequestDigest.GetContextWebInformation.FormDigestValue
    
    $UrlList = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')"
    $InvokeWebRequestParams = @{
        Uri             = $UrlList;
        UseBasicParsing = $true;
        Credential      = $SharePointCredential;
    }
    $List2 = Invoke-RestMethod @InvokeWebRequestParams
    $ListItemEntityTypeFullName = $list.entry.content.properties.ListItemEntityTypeFullName

    $UrlListItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items" + '?$top=10000' + '&$select=ID,Title,DateTime,Duration,Author/Name,Author/Title,Author/EMail,NotifyEmail&$expand=Author/Id'
    $InvokeWebRequestParams = @{
        Uri             = $UrlListItem;
        Method          = "Get";
        UseBasicParsing = $true;
        Headers         = @{ "Accept" = "application/json;odata=verbose" };
        Credential      = $SharePointCredential
    }
    $ListItems = ((Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json).d.results
    
    $header = @{
        "accept"          = "application/json;odata=verbose"
        "X-RequestDigest" = $RequestDigest
        "IF-MATCH"        = '*'
        "X-HTTP-Method"   = "MERGE"
    }

    $SPListItem = $ListItems | Where-object Id -eq $InputParams.Id
    If ($SPListItem.Title -ne $InputParams.HostName) {
        Write-Error ("Web request JSON does not match SharePoint Record for SPListItem.Hostname " + $SPListItem.HostName + " and InputParams.Hostname " + $InputParams.Hostname)
        Exit
    }

    $VMName = $InputParams.HostName
    $SnapTime = ([DateTime]$SPListItem.DateTime).AddMinutes($Duration * 3)
    
    $NotifyEmail = $SPListItem.Author.Email
    If ($SPListItem.NotifyEmail) { $NotifyEmail = $NotifyEmail + ',' + $SPListItem.NotifyEmail }

    $tryCount = 0
#    while ($tryCount -lt 5) {
        try {
            $tryCount++
            Write-Warning ("SharePoint: " + $SnapTime)
            If ($SnapTime -lt (Get-Date)) {
                $SnapTime = (Get-Date).AddSeconds(30)
            }
            Write-Warning ("PowerShell: " + $SnapTime)

            $SnapName = "AutoSnap_" + $SPListItem.ID
            $SnapExpireDateTime = $SnapTime.AddMinutes($SPListItem.Duration * 3)
            $SnapDeleteDateTime = $SnapExpireDateTime.AddMinutes(30)
    
            $SnapDescription = "AutoSnap_" + $InputParams.ID + "`r" + "AutoExpire_$SnapExpireDateTime" + "`r" + "AutoDelete_$SnapDeleteDateTime"
            $snapMemory = $false
            $snapQuiesce = $false

            Connect-VIServer -Server itdvmvc1.nd.gov, itdvmvc2.nd.gov -Credential $vCenterCredential

            $VM = Get-VM -Name $VMName | where-object { $_.ExtensionData.summary.config.ManagedBy.Type -ne "placeholderVm" }
            If (@($VM).count -eq 2) { $VM = Get-VM -Name $VMName -Server ($global:DefaultVIServers | Sort-Object Name | Select-Object -First 1).Name }

            $VIServer = $VM.Uid.split('@')[1].split(':')[0]
                    
            $si = Get-View ServiceInstance -Server $VIServer
            $scheduledTaskManager = Get-View $si.Content.ScheduledTaskManager -Server $VIServer

            $spec = New-Object VMware.Vim.ScheduledTaskSpec
            $spec.Name = $SnapName, $VMname -join '_'
            $spec.Description = "$SnapDescription"
            $spec.Enabled = $true
            $spec.Notification = $NotifyEmail
    
            $spec.Scheduler = New-Object VMware.Vim.OnceTaskScheduler
            $spec.Scheduler.runat = $SnapTime
    
            $spec.Action = New-Object VMware.Vim.MethodAction
            $spec.Action.Name = "CreateSnapshot_Task"

            @($SnapName, $SnapDescription, $SnapMemory, $SnapQuiesce) | ForEach-Object {
                $arg = New-Object VMware.Vim.MethodActionArgument
                $arg.Value = $_
                $spec.Action.Argument += $arg
            }

            # prep for update SharePoint record status
            $RecordToModify = $ListItems | Where-Object Id -eq $InputParams.Id
            If (@($RecordToModify).count -gt 1) { Write-Error "More than one result, stopping"; Exit }
            $IDtoModify = $RecordToModify.ID

            $UrlItem = "https://testshare.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VMware-Snapshots')/items($IDtoModify)"
            $InvokeWebRequestParams = @{
                Uri             = $UrlItem;
                Method          = "Get";
                Headers         = @{ "Accept" = "application/json;odata=verbose" }
                UseBasicParsing = $true;
                Credential      = $SharePointCredential
            }
            If ($Credential) { $InvokeWebRequestParams += @{Credential = $SharePointCredential } }
            Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }

            # Create vCenter scheduled task
            $scheduledTaskManager.CreateObjectScheduledTask($vm.ExtensionData.MoRef, $spec)  
            Start-Sleep -Seconds 3  
        }
        catch [System.Management.Automation.MethodInvocationException] {
            If ($tryCount -lt 4) {
                If ($Error[1].Exception -like "*You have attempted to schedule the scheduler at a time*in the past*") {
                    Write-Warning ((Get-Date))# + ": Attempted schedule in past @ $SnapTime, trying again")
                }
                write-warning $trycount
            }
            Else {
                write-error "vCenter Snapshot Scheduled Task Creation failed"
                write-error $error[1]
                Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
                $Status = "Errored"
                exit
            }
        }
        catch {
            write-error "vCenter Snapshot Scheduled Task Creation failed default message"
            write-error $error[1]
            Send-MailMessage -From "vmware@nd.gov" -To "zmeier@nd.gov" -Subject "VMware-Snapshot Schedule Failed Default Message - $SnapName" -Body "$SnapName`n$SnapDescription" -SmtpServer apprelay1.nd.gov
            $Status = "Errored"
            exit
        }
    #}

    # update SharePoint record status
    If ($Status -ne "Errored") { $Status = "Scheduled" }
    [PSCustomObject]$SetRecord = @{
        "__metadata" = @{type = $ListItemEntityTypeFullName };
        Status       = $Status;
    }
    $body = $SetRecord | ConvertTo-Json
    $InvokeWebRequestParams = @{
        
        Uri             = $UrlItem;
        Method          = "Post";
        Body            = $body;
        ContentType     = "application/json;odata=verbose";
        Headers         = $header;
        UseBasicParsing = $true;
        Credential      = $SharePointCredential
    }
    Invoke-RestMethod @InvokeWebRequestParams

    Disconnect-VIServer -Server * -Confirm:$false
}
Else {
    Write-Error "Runbook must be started from webhook"
}