<#
.SYNOPSIS
    A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
    A longer description of the function, its purpose, common use cases, etc.
.NOTES
    $StartTime & $EndTime
        Send local time in parameter as [datetime] object
        Function will convert the date object to UTC, and convert that result to a string via .ToString()
            API properties of start_date and end_date require datetime formatted as string
            (Get-Date -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
.LINK
    Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
    $NewITDServiceNowChangeRequestParams = @{
    TemplateName              = 'NDIT-SPS-Server Add/Chg/Del'
    RequestedByUsername       = 'zmeier';
    Category                  = 'Systems Platforms - Systems';
    Subcategory               = 'Windows';
    Impact                    = 3;
    ShortDescription          = "things and stuff 5";
    Description               = "things and stuff description";
    Justification             = "things are being done to stuff";
    Implementation            = "do things to stuff";
    RiskImpactAnalysis        = "things will have stuff done to them";
    BackoutPlan               = "can't remove things from stuff"
    TestPlan                  = "test stuff first"
    WhoIsImpacted             = "all the things";
    StartTime                 = (Get-Date)
    EndTime                   = (Get-Date).AddHours(1);
    AssignmentGroup           = 'NDIT-Computer Systems Windows';
    ChangeManagerUsername     = 'khellman';
    ChangeCoordinatorUsername = 'gpgolberg';
    AssignedToUsername        = 'zmeier';
    CabRequred                = $false;
}

$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams
#>

function New-ITDServiceNowChangeRequest {
    [CmdletBinding()]
    param (
        [Parameter(ParameterSetName = 'Standard')]
        [string]
        $TemplateName,

        [string]
        $RequestedByUsername,

        [Parameter(Mandatory = $true)]
        [string]
        $Category,

        [string]
        $ConfigurationItemSysId,

        [string]
        $Subcategory,

        [Parameter(Mandatory = $true)]
        [string]
        $ShortDescription,

        [Parameter(Mandatory = $true)]
        [string]
        $Description,

        [ValidateRange(1, 3)]
        [int]
        $Priority,

        [ValidateRange(1, 3)]
        [int]
        $Impact,

        [Parameter(Mandatory = $true)]
        [string]
        $Justification,

        [Parameter(Mandatory = $true)]
        [string]
        $Implementation,

        [Parameter(Mandatory = $true)]
        [string]
        $RiskImpactAnalysis,

        [Parameter(Mandatory = $true)]
        [string]
        $BackoutPlan,

        [Parameter(Mandatory = $true)]
        [string]
        $TestPlan,

        [string]
        $WhoIsImpacted,

        [Parameter(Mandatory = $true)]
        [string]
        $ChangeManagerUsername,

        [string]
        $ChangeCoordinatorUsername,

        [Parameter(Mandatory = $true)]
        [string]
        $AssignmentGroup,

        [string]
        $AssignedToUsername,

        [Parameter(Mandatory = $true)]
        [datetime]
        $StartTime,
        
        [Parameter(Mandatory = $true)]
        [datetime]
        $EndTime

        <#
        [ValidateSet($true,$false)]
        [string]
        $CabRequired = $true
        #>
    )
    
    begin {
        switch ($PSCmdlet.ParameterSetName) {
            'Standard' {
                Write-Verbose -Message "Standard Change Template parameter: $TemplateName"  # Server Add/Chg/Del
                
                # get standard template
                $ChgTemplateStd = Get-ITDServiceNowChangeTemplateStandard -Name $TemplateName
                $ChgTemplateStdSysId = $ChgTemplateStd.sys_id.value
            }
            Default {

            }
        }
    }
    
    process {            
        [PSCustomObject]$NewRecord = @{
            category             = $Category;
            u_subcategory        = $Subcategory
            impact               = $Impact;
            urgency              = $Urgency;
            short_description    = $ShortDescription;
            description          = $Description;
            justification        = $Justification;
            implementation_plan  = $Implementation;
            risk_impact_analysis = $RiskImpactAnalysis;
            backout_plan         = $BackoutPlan;
            test_plan            = $TestPlan
            u_who_is_impacted    = $WhoIsImpacted;
            start_date           = (Get-Date -Date $StartTime -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
            end_date             = (Get-Date -Date $EndTime -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
        }

        If($ConfigurationItemSysId) {
            $NewRecord += @{cmdb_ci = $ConfigurationItemSysId}
        }

        If ($CabRequired){
            $NewRecord += @{cab_required = $true}
        } Else {
            $NewRecord += @{cab_required = $false}
        }

        If ($RequestedByUsername) {
            $ReqBy = Get-ITDServiceNowUser -Username $RequestedByUsername
            If (@($ReqBy).count -gt 1) {
                Write-Error "Multiple requested users found, creation failed." -ErrorAction Stop
            }
            Else {
                $NewRecord += @{requested_by = $ReqBy.sys_id }
            }
        }

        If ($AssignmentGroup) {
            $AssGroup = Get-ITDServiceNowUserGroup -Name $AssignmentGroup
            If (@($AssGroup).count -gt 1) {
                Write-Error "Multiple assignment groups found, creation failed." -ErrorAction Stop
            }
            Else {
                $NewRecord += @{assignment_group = $AssGroup.sys_id }
            }
        }

        $ChgManagerUsername = Get-ITDServiceNowUser -Username $ChangeManagerUsername
        If (@($ChgManagerUsername).count -gt 1) {
            Write-Error "Multiple users found for ChangeManagerUsername, creation failed." -ErrorAction Stop
        }
        Else {
            $NewRecord += @{u_change_manager = $ChgManagerUsername.sys_id }
        }

        $ChgCoordUsername = Get-ITDServiceNowUser -Username $ChangeCoordinatorUsername
        If (@($ChgCoordUsername).count -gt 1) {
            Write-Error "Multiple users found for ChangeCoordinator, creation failed." -ErrorAction Stop
        }
        Else {
            $NewRecord += @{u_change_coordinator = $ChgCoordUsername.sys_id }
        }

        If ($AssignedToUsername) {
            $AssTo = Get-ITDServiceNowUser -Username $AssignedToUsername
            If (@($AssTo).count -gt 1) {
                Write-Error "Multiple assignment users found, incident creation failed." -ErrorAction Step
            }
            Else {
                $NewRecord += @{assigned_to = $AssTo.sys_id }
            }
        }

        Write-Verbose ($NewRecord | ConvertTo-Json)
            
        switch ($PSCmdlet.ParameterSetName) {
            'Standard' {
                $Uri = ($Script:ServiceNowSession.Uri + "/api/sn_chg_rest/change/standard/$ChgTemplateStdSysId" );
            }
            Default {
                Write-Verbose -Message ("Uri = " + $Uri)
                $Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/change_request");
            }
        }

        Write-Verbose -Message "Standard CHG Template SysId = $Uri"
        $InvokeRestMethodParams = @{
            Method      = 'Post';
            Uri         = $Uri;
            Body        = $NewRecord | ConvertTo-Json;
            Headers     = $Script:ServiceNowSession.Headers;
            ContentType = "application/json"
        }

        #Write-Output $InvokeRestMethodParams
        $result = (Invoke-RestMethod @InvokeRestMethodParams).result
    }
    
    end {
        Write-Output $result   
    }
}