commands.ps1


<#
    .SYNOPSIS
        A universal function to interact with Azure DevOps REST API endpoints.
         
    .DESCRIPTION
        The `Invoke-ADOApiRequest` function allows interaction with any Azure DevOps REST API endpoint.
        It requires the organization, a valid authentication token, and the specific API URI.
        The project is optional and will only be included in the URL if specified.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        The name of the Azure DevOps project (optional).
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ApiUri
        The specific Azure DevOps REST API URI to interact with (relative to the organization or project URL).
         
    .PARAMETER Method
        The HTTP method to use for the request (e.g., GET, POST, PUT, DELETE). Default is "GET".
         
    .PARAMETER Body
        The body content to include in the HTTP request (for POST/PUT requests).
         
    .PARAMETER Headers
        Additional headers to include in the request.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .PARAMETER OnlyFirstPage
        If enabled, the function will return only the first page of results and stop if a continuation token is present.
         
    .EXAMPLE
        Invoke-ADOApiRequest -Organization "my-org" -ApiUri "_apis/testplan/Plans/123/suites" -Token "my-token"
         
        This example retrieves test suites from the test plan with ID 123 in the specified organization.
         
    .EXAMPLE
        Invoke-ADOApiRequest -Organization "my-org" -ApiUri "_apis/projects" -Token "my-token" -OnlyFirstPage
         
        This example retrieves only the first page of projects in the specified organization.
         
    .NOTES
            - The function uses the Azure DevOps REST API.
            - An authentication token is required.
            - Handles pagination through continuation tokens.
        Author: Oleksandr Nikolaiev
#>


function Invoke-ADOApiRequest {
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter()]
        [string]$Project = $null,

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

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

        [Parameter()]
        [ValidateSet("GET", "POST", "PUT", "DELETE", "PATCH")]
        [string]$Method = "GET",

        [Parameter()]
        [string]$Body = $null,

        [Parameter()]
        [Hashtable]$Headers = @{}, 

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion,

        [Parameter()]
        [switch]$OnlyFirstPage
    )
    begin {
        Invoke-TimeSignal -Start
        if (-not $Token) {
            Write-PSFMessage -Level Error -Message "Token is required"
            return
        }
        if (-not $ApiUri) {
            Write-PSFMessage -Level Error -Message "ApiUri is required"
            return
        }
        if (-not $Organization) {
            Write-PSFMessage -Level Error -Message "Organization is required"
            return
        }
        if ($Organization.StartsWith("https://dev.azure.com") -eq $false) {
            $Organization = "https://dev.azure.com/$Organization"
        }

        # Prepare Authorization Header
        if ($Token.StartsWith("Bearer")) {
            $authHeader = @{ Authorization = "$Token"}
        } else {
            $authHeader = @{ Authorization = "Bearer $Token" }
        }

        # Merge additional headers
        $headers = $authHeader + $Headers

        $allResults = @()
        $continuationToken = $null
        $requestUrl = ""
    }
    process {       

        try {
            $statusCode = $null

            do {
                # Construct the full URL with API version and continuation token
                $baseUrl = if ($Project) { "$Organization/$Project" } else { $Organization }
                $baseUrl = $baseUrl.TrimEnd('/')
                $ApiUri = $ApiUri.TrimStart('/').TrimEnd('/')                
                $requestUrl = "$baseUrl/$ApiUri"   
                
                if ($continuationToken) {
                    $requestUrl += "&continuationToken=$continuationToken"
                }
                
                $requestUrl = if ($requestUrl.Contains("?")) 
                { [System.Uri]::EscapeUriString("$requestUrl" + "&api-version=$ApiVersion") } 
                else 
                { [System.Uri]::EscapeUriString("$requestUrl" + "?api-version=$ApiVersion") }

                Write-PSFMessage -Level Verbose -Message "Request URL: $Method $requestUrl"

                if ($PSVersionTable.PSVersion.Major -ge 7) {
                    $response = Invoke-RestMethod -Uri $requestUrl -Headers $headers -Method $Method.ToLower() -Body $Body -ResponseHeadersVariable responseHeaders -StatusCodeVariable statusCode
                    $continuationToken = $responseHeaders['x-ms-continuationtoken']
                } else {
                    $response = Invoke-WebRequest -Uri $requestUrl -Headers $headers -Method $Method.ToLower() -Body $Body -UseBasicParsing
                    $continuationToken = $response.Headers['x-ms-continuationtoken']
                    $statusCode = $response.StatusCode
                    $response = $response.Content | ConvertFrom-Json
                }
                
                if ($statusCode -in @(200, 201, 202, 204 )) {
                    if ($response.value) {
                        $allResults += $response.value
                    } else {
                        $allResults += $response
                    }

                    # If OnlyFirstPage is enabled, stop after the first response
                    if ($OnlyFirstPage -and $continuationToken) {
                        break
                    }
                } else {
                    Write-PSFMessage -Level Error -Message "The request failed with status code: $($statusCode)"
                }

            } while ($continuationToken)

            return @{
                Results = $allResults
                Count = $allResults.Count
            }
        } catch {
            Write-PSFMessage -Level Error -Message "Something went wrong during request to ADO: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }
    end {
        Invoke-TimeSignal -End        
    }
}


<#
    .SYNOPSIS
        Handle time measurement
         
    .DESCRIPTION
        Handle time measurement from when a cmdlet / function starts and ends
         
        Will write the output to the verbose stream (Write-PSFMessage -Level Verbose)
         
    .PARAMETER Start
        Switch to instruct the cmdlet that a start time registration needs to take place
         
    .PARAMETER End
        Switch to instruct the cmdlet that a time registration has come to its end and it needs to do the calculation
         
    .EXAMPLE
        PS C:\> Invoke-TimeSignal -Start
         
        This will start the time measurement for any given cmdlet / function
         
    .EXAMPLE
        PS C:\> Invoke-TimeSignal -End
         
        This will end the time measurement for any given cmdlet / function.
        The output will go into the verbose stream.
         
    .NOTES
        This is refactored function from d365fo.tools
         
        Original Author: Mötz Jensen (@Splaxi)
        Author: Oleksandr Nikolaiev (@onikolaiev)
         
#>

function Invoke-TimeSignal {
    [CmdletBinding(DefaultParameterSetName = 'Start')]
    param (
        [Parameter(Mandatory = $true, ParameterSetName = 'Start', Position = 1 )]
        [switch] $Start,
        
        [Parameter(Mandatory = $True, ParameterSetName = 'End', Position = 2 )]
        [switch] $End
    )

    $Time = (Get-Date)

    $Command = (Get-PSCallStack)[1].Command

    if ($Start) {
        if ($Script:TimeSignals.ContainsKey($Command)) {
            Write-PSFMessage -Level Verbose -Message "The command '$Command' was already taking part in time measurement. The entry has been update with current date and time."
            $Script:TimeSignals[$Command] = $Time
        }
        else {
            $Script:TimeSignals.Add($Command, $Time)
        }
    }
    else {
        if ($Script:TimeSignals.ContainsKey($Command)) {
            $TimeSpan = New-TimeSpan -End $Time -Start (($Script:TimeSignals)[$Command])

            Write-PSFMessage -Level Verbose -Message "Total time spent inside the function was $TimeSpan" -Target $TimeSpan -FunctionName $Command -Tag "TimeSignal"
            $null = $Script:TimeSignals.Remove($Command)
        }
        else {
            Write-PSFMessage -Level Verbose -Message "The command '$Command' was never started to take part in time measurement."
        }
    }
}


<#
    .SYNOPSIS
        Creates a picklist.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new picklist in the specified organization.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Body
        The JSON string containing the properties for the picklist to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "id": null,
            "name": "picklist_aef2c045-0d2d-4f92-9d09-56eea553e1ef",
            "type": "String",
            "url": null,
            "items": [
            "Blue",
            "Green",
            "Red"
            ],
            "isSuggested": false
        }
        "@
         
        Add-ADOPickList -Organization "fabrikam" -Token "my-token" -Body $body
         
        Creates a new picklist in the specified organization.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOPickList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a new picklist for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/lists"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a new picklist for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.PickListObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create picklist: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a new picklist for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a new process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new process in the specified organization.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Body
        The JSON string containing the properties for the process to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "MyNewAgileProcess",
            "parentProcessTypeId": "adcc42ab-9882-485e-a3ed-7678f01f66bc",
            "referenceName": "fabrikam.MyNewAgileProcess",
            "description": "My new process"
        }
        "@
         
        Add-ADOProcess -Organization "fabrikam" -Token "my-token" -Body $body
         
        Creates a new process in the specified organization.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOProcess {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a new process for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a new process for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create process: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a new process for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a behavior in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new behavior for a specified process.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER Body
        The JSON string containing the properties for the behavior to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "NewCustomBehavior",
            "color": "009CDD",
            "inherits": "System.PortfolioBacklogBehavior"
        }
        "@
         
        Add-ADOProcessBehavior -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -Body $body
         
        Creates a new behavior for the specified process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOProcessBehavior {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a behavior for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/behaviors"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a behavior for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessBehaviorObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create a behavior: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a behavior for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Queues a project to be created.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and queue a new project creation in the specified organization.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Body
        The JSON string containing the properties for the project to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "FabrikamTravel",
            "description": "Fabrikam travel app for Windows Phone",
            "capabilities": {
                "versioncontrol": {
                    "sourceControlType": "Git"
                },
                "processTemplate": {
                    "templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
                }
            }
        }
        "@
         
        Add-ADOProject -Organization "fabrikam" -Token "my-token" -Body $body
         
        Queues a new project creation in the specified organization.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOProject {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a new project for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/projects"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully queued project creation for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProjectObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to queue project creation: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed queuing of project creation for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a new field.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new field in the specified organization and project.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Body
        The JSON string containing the properties for the field to create.
         
    .PARAMETER Project
        The ID or name of the project. This parameter is optional.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.2-preview.3".
         
    .EXAMPLE
        $body = @"
        {
            "name": "New Work Item Field",
            "referenceName": "SupportedOperations.GreaterThanEquals",
            "description": null,
            "type": "string",
            "usage": "workItem",
            "readOnly": false,
            "canSortBy": true,
            "isQueryable": true,
            "supportedOperations": [
            {
                "referenceName": "SupportedOperations.Equals",
                "name": "="
            }
            ],
            "isIdentity": true,
            "isPicklist": false,
            "isPicklistSuggested": false,
            "url": null
        }
        "@
         
        Add-ADOWitField -Organization "fabrikam" -Token "my-token" -Body $body -Project "MyProject"
         
        Creates a new field in the specified project.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWitField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$Project = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a new field for Organization: $Organization"
        if ($Project) {
            Write-PSFMessage -Level Verbose -Message "Project: $Project"
        }
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = if ($Project) {
                "$Project/_apis/wit/fields"
            } else {
                "_apis/wit/fields"
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a new field for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemField2"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a new field for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a new work item in Azure DevOps.
         
    .DESCRIPTION
        This function creates a new work item in a specified Azure DevOps project using the provided parameters.
        It supports optional parameters to bypass rules, suppress notifications, validate changes, and expand additional attributes of the work item.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        The name or ID of the Azure DevOps project where the work item will be created.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Type
        The type of the work item to create (e.g., Task, Bug, User Story).
         
    .PARAMETER Body
        The JSON Patch document containing the fields and values for the work item.
         
    .PARAMETER ValidateOnly
        (Optional) Indicates if you only want to validate the changes without saving the work item. Default is `$false`.
         
    .PARAMETER BypassRules
        (Optional) Indicates if work item type rules should be bypassed. Default is `$false`.
         
    .PARAMETER SuppressNotifications
        (Optional) Indicates if notifications should be suppressed for this change. Default is `$false`.
         
    .PARAMETER Expand
        (Optional) Specifies the expand parameters for work item attributes. Possible values are `None`, `Relations`, `Fields`, `Links`, or `All`.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `$Script:ADOApiVersion`.
         
    .EXAMPLE
        # Example 1: Create a new Task work item
        $body = @"
        {
            "op": "add",
            "path": "/fields/System.Title",
            "value": "Sales Order Process",
        }
        "@
         
        Add-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Type "Task" -Body $body
         
    .EXAMPLE
        # Example 2: Create a new Bug work item with validation only
        $body = @"
        {
            "op": "add",
            "path": "/fields/System.Title",
            "value": "Sample Bug",
        }
        "@
        Add-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Type "Bug" -Body $body -ValidateOnly $true
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Add-ADOWorkItem {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter(Mandatory = $false)]
        [switch]$ValidateOnly,

        [Parameter(Mandatory = $false)]
        [switch]$BypassRules,

        [Parameter(Mandatory = $false)]
        [switch]$SuppressNotifications,

        [Parameter(Mandatory = $false)]
        [ValidateSet("None", "Relations", "Fields", "Links", "All")]
        [string]$Expand = "None",

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a new work item in Project: $Project, Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "$Project/_apis/wit/workitems/$Type"

            # Append query parameters
            if ($ValidateOnly) {
                $apiUri += "?validateOnly=$ValidateOnly"
            }
            if ($BypassRules) {
                $apiUri += if ($apiUri.Contains("?")) { "&bypassRules=$BypassRules" } else { "?bypassRules=$BypassRules" }
            }
            if ($SuppressNotifications) {
                $apiUri += if ($apiUri.Contains("?")) { "&suppressNotifications=$SuppressNotifications" } else { "?suppressNotifications=$SuppressNotifications" }
            }
            if ($Expand -ne "None") {
                $apiUri += if ($apiUri.Contains("?")) { "&`$expand=$Expand" } else { "?`$expand=$Expand" }
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Headers @{"Content-Type" = "application/json-patch+json"} `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created work item in Project: $Project, Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItem"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create work item: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of work item in Project: $Project, Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a new work item type in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new work item type in a specified process.
        The request body is passed as a string variable.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type will be created.
         
    .PARAMETER Body
        The JSON string containing the properties for the new work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "Change Request",
            "description": "Tracks requests for changes",
            "color": "f6546a",
            "icon": "icon_airplane",
            "isDisabled": false,
            "inheritsFrom": null
        }
        "@
         
        Add-ADOWorkItemType -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -Body $body
         
        Creates a new work item type named "Change Request" in the specified process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemType {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "Create")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of work item type in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workitemtypes"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion `
                                             -Headers @{ "Content-Type" = "application/json"}

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created work item type in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create work item type: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of work item type in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Adds a field to a work item type.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and add a field to a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Body
        The JSON string containing the properties for the new field.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "referenceName": "Custom.Fields.Colors",
            "defaultValue": "",
            "allowGroups": false
        }
        "@
         
        Add-ADOWorkItemTypeField -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Adds a new field to the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypeField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting addition of a field to work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/fields"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully added a field to work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeFieldObject" 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to add a field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed addition of a field to work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Adds a group to the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and add a new group to a specified section on a page in a work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page to add the group to.
         
    .PARAMETER SectionId
        The ID of the section to add the group to.
         
    .PARAMETER Body
        The JSON string containing the properties for the group to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "controls": null,
            "id": null,
            "label": "NewGroup",
            "order": null,
            "overridden": null,
            "inherited": null,
            "visible": true
        }
        "@
         
        Add-ADOWorkItemTypeGroup -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "page-id" -SectionId "section-id" -Body $body
         
        Adds a new group to the specified section on the page.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypeGroup {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting addition of a group to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId/sections/$SectionId/groups"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully added a group to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to add a group: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed addition of a group to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a control in a group.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a new control in a specified group.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER GroupId
        The ID of the group to add the control to.
         
    .PARAMETER Body
        The JSON string containing the properties for the control to create.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "order": null,
            "label": "",
            "readOnly": false,
            "visible": true,
            "controlType": null,
            "metadata": null,
            "inherited": null,
            "overridden": null,
            "watermark": null,
            "contribution": {
                "contributionId": "ms-devlabs.toggle-control.toggle-control-contribution",
                "inputs": {
                    "FieldName": "System.BoardColumnDone"
                },
                "height": null,
                "showOnDeletedWorkItem": null
            },
            "isContribution": true,
            "height": null
        }
        "@
         
        Add-ADOWorkItemTypeGroupControl -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -GroupId "group-id" -Body $body
         
        Creates a new control in the specified group.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypeGroupControl {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion 
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a control in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/groups/$GroupId/controls"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a control in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupControlObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create a control: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a control in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Adds a page to the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and add a page to the layout of a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Body
        The JSON string containing the properties for the new page.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "sections": [
            {
                "id": "Section1",
                "groups": [],
                "overridden": false
            },
            {
                "id": "Section2",
                "groups": [],
                "overridden": false
            }
            ],
            "id": "",
            "label": "Page1",
            "order": 1,
            "visible": true,
            "locked": false,
            "pageType": "custom"
        }
        "@
         
        Add-ADOWorkItemTypePage -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Adds a new page to the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypePage {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting addition of a page to work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully added a page to work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypePageObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to add a page: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed addition of a page to work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Adds a rule to a work item type in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and add a rule to a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Body
        The JSON string containing the properties for the new rule.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "myRule",
            "conditions": [
            {
                "conditionType": "$when",
                "field": "Microsoft.VSTS.Common.Priority",
                "value": "1"
            },
            {
                "conditionType": "$when",
                "field": "System.State",
                "value": "Active"
            }
            ],
            "actions": [
            {
                "actionType": "$copyValue",
                "targetField": "Microsoft.VSTS.Common.Severity",
                "value": "1 - Critical"
            }
            ],
            "isDisabled": true
        }
        "@
         
        Add-ADOWorkItemTypeRule -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Adds a new rule to the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypeRule {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting addition of a rule to work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/rules"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully added a rule to work item type '$WitRefName' in ProcessId: $ProcessId"
        return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeRuleObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to add a rule: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed addition of a rule to work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Creates a state definition in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and create a state definition for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Body
        The JSON string containing the properties for the new state.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "Ready to test",
            "color": "b2b2b2",
            "stateCategory": "Proposed"
        }
        "@
         
        Add-ADOWorkItemTypeState -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Creates a new state definition for the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Add-ADOWorkItemTypeState {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting creation of a state for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully created a state for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeStateObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to create a state: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed creation of a state for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Disables throwing of exceptions
         
    .DESCRIPTION
        Restore the default exception behavior of the module to not support throwing exceptions
         
        Useful when the default behavior was changed with Enable-ADOException and the default behavior should be restored
         
    .EXAMPLE
        Disable-ADOException
         
        This will restore the default behavior of the module to not support throwing exceptions.
         
    .NOTES
        Tags: Exception, Exceptions, Warning, Warnings
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
         
    .LINK
        Enable-ADOException
#>


function Disable-ADOException {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param ()

    Write-PSFMessage -Level Verbose -Message "Disabling exception across the entire module." -Target $configurationValue

    Set-PSFFeature -Name 'PSFramework.InheritEnableException' -Value $false -ModuleName "ado.core"
    Set-PSFFeature -Name 'PSFramework.InheritEnableException' -Value $false -ModuleName "PSOAuthHelper"
    $PSDefaultParameterValues['*:EnableException'] = $false
}


<#
    .SYNOPSIS
        Enable exceptions to be thrown
         
    .DESCRIPTION
        Change the default exception behavior of the module to support throwing exceptions
         
        Useful when the module is used in an automated fashion, like inside Azure DevOps pipelines and large PowerShell scripts
         
    .EXAMPLE
        PS C:\>Enable-ADOException
         
        This will for the rest of the current PowerShell session make sure that exceptions will be thrown.
         
    .NOTES
        Tags: Exception, Exceptions, Warning, Warnings
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
         
    .LINK
        Disable-ADOException
#>


function Enable-ADOException {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param ()

    Write-PSFMessage -Level Verbose -Message "Enabling exception across the entire module." -Target $configurationValue

    Set-PSFFeature -Name 'PSFramework.InheritEnableException' -Value $true -ModuleName "ado.core"
    Set-PSFFeature -Name 'PSFramework.InheritEnableException' -Value $true -ModuleName "PSOAuthHelper"
    $PSDefaultParameterValues['*:EnableException'] = $true
}


<#
    .SYNOPSIS
        Retrieves a picklist by its ID.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific picklist by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ListId
        The ID of the picklist to retrieve.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOPickList -Organization "fabrikam" -Token "my-token" -ListId "661eb38e-6f0b-484a-bc53-27a57c2e2d50"
         
        Retrieves the specified picklist by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOPickList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of picklist with ID '$ListId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/lists/$ListId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved picklist with ID '$ListId' for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.PickListObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve picklist: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of picklist with ID '$ListId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves metadata of the picklists.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve metadata for all picklists in the organization.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOPickListList -Organization "fabrikam" -Token "my-token"
         
        Retrieves metadata for all picklists in the specified organization.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOPickListList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of picklist metadata for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/lists"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved picklist metadata for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.PickListObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve picklist metadata: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of picklist metadata for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a single process by its ID.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific process by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessTypeId
        The ID of the process to retrieve.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the process (e.g., projects, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOProcess -Organization "fabrikam" -Token "my-token" -ProcessTypeId "adcc42ab-9882-485e-a3ed-7678f01f66bc"
         
        Retrieves the specified process by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProcess {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [ValidateSet("projects", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of process with ID '$ProcessTypeId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$($ProcessTypeId)" + "?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved process with ID '$ProcessTypeId' for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve process: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of process with ID '$ProcessTypeId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a behavior of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific behavior for a specified process.
        It supports optional parameters to expand specific properties of the behavior.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER BehaviorRefName
        The reference name of the behavior.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the behavior (e.g., fields, combinedFields, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOProcessBehavior -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -BehaviorRefName "System.RequirementBacklogBehavior"
         
        Retrieves the specified behavior for the process.
         
    .EXAMPLE
        Get-ADOProcessBehavior -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -BehaviorRefName "System.RequirementBacklogBehavior" -Expand "fields"
         
        Retrieves the specified behavior for the process with fields expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProcessBehavior {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [ValidateSet("fields", "combinedFields", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of behavior '$BehaviorRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId/behaviors/$BehaviorRefName?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved behavior '$BehaviorRefName' for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessBehaviorObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve behavior: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of behavior '$BehaviorRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all behaviors in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve all behaviors for a specified process.
        It supports optional parameters to expand specific properties of the behaviors.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the behaviors (e.g., fields, combinedFields, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOProcessBehaviorList -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b"
         
        Retrieves all behaviors for the specified process.
         
    .EXAMPLE
        Get-ADOProcessBehaviorList -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -Expand "fields"
         
        Retrieves all behaviors for the specified process with fields expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProcessBehaviorList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [ValidateSet("fields", "combinedFields", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of behaviors for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId" + "/behaviors?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved behaviors for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessBehaviorObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve behaviors: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of behaviors for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all processes including system and inherited.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve metadata for all processes in the organization.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the processes (e.g., projects, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOProcessList -Organization "fabrikam" -Token "my-token"
         
        Retrieves metadata for all processes in the specified organization.
         
    .EXAMPLE
        Get-ADOProcessList -Organization "fabrikam" -Token "my-token" -Expand "projects"
         
        Retrieves metadata for all processes in the specified organization with projects expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProcessList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

        [Parameter()]
        [ValidateSet("projects", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of process list for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved process list for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve process list: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of process list for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a specific project in the Azure DevOps organization by its ID or name.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific project.
        It supports optional parameters to include capabilities and history in the response.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProjectId
        The ID or name of the project to retrieve.
         
    .PARAMETER IncludeCapabilities
        Whether to include capabilities (such as source control) in the team project result. Default is $false.
         
    .PARAMETER IncludeHistory
        Whether to search within renamed projects (that had such name in the past). Default is $false.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is set globally.
         
    .EXAMPLE
        Get-ADOProject -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c"
         
        Retrieves the project with the specified ID.
         
    .EXAMPLE
        Get-ADOProject -Organization "fabrikam" -Token "my-token" -ProjectId "MyProject" -IncludeCapabilities -IncludeHistory
         
        Retrieves the project with the specified name, including capabilities and history.
         
    .NOTES
        The project ID can be either the GUID or the name of the project.
        The function will return the project details in a structured format.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProject {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [switch]$IncludeCapabilities,

        [Parameter()]
        [switch]$IncludeHistory,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of project details for ProjectId: $ProjectId in Organization: $Organization"
        $apiUri = "_apis/projects/$($ProjectId)?"
        if ($IncludeCapabilities) {
            $apiUri += "includeCapabilities=$IncludeCapabilities&"
        }
        if ($IncludeHistory) {
            $apiUri += "includeHistory=$IncludeHistory&"
        }

        # Remove trailing '&' or '?' if present
        $apiUri = $apiUri.TrimEnd('&', '?')
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters


            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method GET `
                                             -ApiVersion $ApiVersion 

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved project details for ProjectId: $ProjectId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProjectObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve project details: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of project details for ProjectId: $ProjectId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of projects in the Azure DevOps organization that the authenticated user has access to.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a list of projects.
        It supports optional parameters such as state filter, pagination, and default team image URL.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER StateFilter
        Filter on team projects in a specific state (e.g., WellFormed, Deleted, All). Default is WellFormed.
         
    .PARAMETER Top
        The maximum number of projects to return.
         
    .PARAMETER Skip
        The number of projects to skip.
         
    .PARAMETER ContinuationToken
        Pointer that shows how many projects have already been fetched.
         
    .PARAMETER GetDefaultTeamImageUrl
        Whether to include the default team image URL in the response.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is set globally.
         
    .EXAMPLE
        Get-ADOProjectList -Organization "fabrikam" -Token "my-token"
         
        Retrieves all projects in the specified organization.
         
    .EXAMPLE
        Get-ADOProjectList -Organization "fabrikam" -Token "my-token" -StateFilter "WellFormed" -Top 10
         
        Retrieves the first 10 well-formed projects in the specified organization.
         
    .NOTES
        The function will return the project list in a structured format.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProjectList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

        [Parameter()]
        [ProjectState]$StateFilter = [ProjectState]::All,

        [Parameter()]
        [int]$Top = $null,

        [Parameter()]
        [int]$Skip = $null,

        [Parameter()]
        [int]$ContinuationToken = $null,

        [Parameter()]
        [switch]$GetDefaultTeamImageUrl,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start        
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Building API URI for retrieving project list."
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/projects?"
            if ($StateFilter) {
                $apiUri += "stateFilter=$StateFilter&"
            }
            if ($Top) {
                $apiUri += "`$top=$Top&"
            }
            if ($Skip) {
                $apiUri += "`$skip=$Skip&"
            }
            if ($ContinuationToken) {
                $apiUri += "continuationToken=$ContinuationToken&"
            }
            if ($GetDefaultTeamImageUrl) {
                $apiUri += "getDefaultTeamImageUrl=$GetDefaultTeamImageUrl&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Determine if OnlyFirstPage should be passed
            $onlyFirstPage = $Top -ne $null

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            if ($onlyFirstPage) {
                Write-PSFMessage -Level Verbose -Message "Fetching only the first page of results."
                $response = Invoke-ADOApiRequest -Organization $Organization `
                                                 -Token $Token `
                                                 -Method GET `
                                                 -ApiUri $apiUri `
                                                 -ApiVersion $ApiVersion `
                                                 -OnlyFirstPage
            } else {
                Write-PSFMessage -Level Verbose -Message "Fetching all results."
                $response = Invoke-ADOApiRequest -Organization $Organization `
                                                 -Token $Token `
                                                 -ApiVersion $ApiVersion `
                                                 -Method GET `
                                                 -ApiUri $apiUri
            }

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved project list."
            return $response.Results
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve project list: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieving project list."
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a collection of team project properties in Azure DevOps.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve properties of a specific project.
        It supports optional parameters to filter properties by specific keys.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProjectId
        The ID of the project to retrieve properties for.
         
    .PARAMETER Keys
        A comma-delimited string of team project property names to filter the results. Wildcard characters ("?" and "*") are supported.
        If no key is specified, all properties will be returned.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is set globally.
         
    .EXAMPLE
        Get-ADOProjectPropertieList -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c"
         
        Retrieves all properties for the specified project.
         
    .EXAMPLE
        Get-ADOProjectPropertieList -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c" -Keys "System.CurrentProcessTemplateId,*SourceControl*"
         
        Retrieves specific properties for the specified project.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOProjectPropertieList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$Keys = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of project properties for ProjectId: $ProjectId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/projects/$ProjectId/properties?"
            if ($Keys) {
                $apiUri += "keys=$Keys&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -ApiVersion $ApiVersion
            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved project properties for ProjectId: $ProjectId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProjectProperty" 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve project properties: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of project properties for ProjectId: $ProjectId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Gets information on a specific field.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve metadata for a specific field in the specified organization and project.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER FieldNameOrRefName
        The simple name or reference name of the field to retrieve.
         
    .PARAMETER Project
        The ID or name of the project. This parameter is optional.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.2-preview.3".
         
    .EXAMPLE
        Get-ADOWitField -Organization "fabrikam" -Token "my-token" -FieldNameOrRefName "System.IterationPath"
         
        Retrieves metadata for the specified field in the organization.
         
    .EXAMPLE
        Get-ADOWitField -Organization "fabrikam" -Token "my-token" -FieldNameOrRefName "System.IterationPath" -Project "MyProject"
         
        Retrieves metadata for the specified field in the specified project.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWitField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$Project = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of field '$FieldNameOrRefName' for Organization: $Organization"
        if ($Project) {
            Write-PSFMessage -Level Verbose -Message "Project: $Project"
        }
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = if ($Project) {
                "$Project/_apis/wit/fields/$FieldNameOrRefName"
            } else {
                "_apis/wit/fields/$FieldNameOrRefName"
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved field '$FieldNameOrRefName' for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemField2"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of field '$FieldNameOrRefName' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves information for all fields.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve metadata for all fields in the specified organization and project.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Project
        The ID or name of the project. This parameter is optional.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the fields (e.g., extensionFields, includeDeleted, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.2-preview.3".
         
    .EXAMPLE
        Get-ADOWitFieldList -Organization "fabrikam" -Token "my-token"
         
        Retrieves metadata for all fields in the specified organization.
         
    .EXAMPLE
        Get-ADOWitFieldList -Organization "fabrikam" -Token "my-token" -Project "MyProject" -Expand "extensionFields"
         
        Retrieves metadata for all fields in the specified project with extension fields expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWitFieldList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

        [Parameter()]
        [string]$Project = $null,

        [Parameter()]
        [ValidateSet("extensionFields", "includeDeleted", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of fields for Organization: $Organization"
        if ($Project) {
            Write-PSFMessage -Level Verbose -Message "Project: $Project"
        }
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = if ($Project) {
                "$Project/_apis/wit/fields?"
            } else {
                "_apis/wit/fields?"
            }

            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved fields for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemField2"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve fields: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of fields for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a single work item from Azure DevOps.
         
    .DESCRIPTION
        This function retrieves a single work item from Azure DevOps using its ID.
        It supports optional parameters to specify fields, expand attributes, and retrieve the work item as of a specific date.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Id
        The ID of the work item to retrieve.
         
    .PARAMETER Fields
        (Optional) A comma-separated list of fields to include in the response.
         
    .PARAMETER Expand
        (Optional) Specifies the expand parameters for work item attributes. Possible values are `None`, `Relations`, `Fields`, `Links`, or `All`.
         
    .PARAMETER AsOf
        (Optional) The UTC date-time string to retrieve the work item as of a specific date.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Retrieve a work item by ID
         
        Get-ADOWorkItem -Organization "my-org" -Token "my-token" -Id 12345
         
    .EXAMPLE
        # Example 2: Retrieve a work item with specific fields and expand attributes
         
        Get-ADOWorkItem -Organization "my-org" -Token "my-token" -Id 12345 -Fields "System.Title,System.State" -Expand "Relations"
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Get-ADOWorkItem {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

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

        [Parameter(Mandatory = $true)]
        [int]$Id,

        [Parameter(Mandatory = $false)]
        [string]$Fields,

        [Parameter(Mandatory = $false)]
        [ValidateSet("None", "Relations", "Fields", "Links", "All")]
        [string]$Expand = "None",

        [Parameter(Mandatory = $false)]
        [datetime]$AsOf,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "_apis/wit/workitems/$Id"
            if ($Project) { $apiUri = "$Project/$apiUri" }

            # Append query parameters
            if ($Fields) {
                $apiUri += "?fields=$Fields"
            }
            if ($Expand -ne "None") {
                $apiUri += if ($apiUri.Contains("?")) { "&`$expand=$Expand" } else { "?`$expand=$Expand" }
            }
            if ($AsOf) {
                $asOfString = $AsOf.ToString("yyyy-MM-ddTHH:mm:ssZ")
                $apiUri += if ($apiUri.Contains("?")) { "&asOf=$asOfString" } else { "?asOf=$asOfString" }
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved work item ID: $Id in Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItem"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve work item ID: $Id : $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a batch of work items from Azure DevOps by their IDs.
         
    .DESCRIPTION
        This function retrieves a batch of work items from Azure DevOps using their IDs.
        It supports optional parameters to specify fields, expand attributes, control error policy, and retrieve work items as of a specific date.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Ids
        The list of work item IDs to retrieve (maximum 200).
         
    .PARAMETER Fields
        (Optional) A list of fields to include in the response.
         
    .PARAMETER Expand
        (Optional) Specifies the expand parameters for work item attributes. Possible values are `None`, `Relations`, `Fields`, `Links`, or `All`.
         
    .PARAMETER AsOf
        (Optional) The UTC date-time string to retrieve the work items as of a specific date.
         
    .PARAMETER ErrorPolicy
        (Optional) The error policy for the request. Possible values are `Fail` or `Omit`.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Retrieve a batch of work items by IDs
         
        Get-ADOWorkItemsBatch -Organization "my-org" -Token "my-token" -Ids @(297, 299, 300)
         
    .EXAMPLE
        # Example 2: Retrieve a batch of work items with specific fields and expand attributes
         
        Get-ADOWorkItemsBatch -Organization "my-org" -Token "my-token" -Ids @(297, 299, 300) -Fields @("System.Id", "System.Title") -Expand "Relations"
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Get-ADOWorkItemsBatch {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

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

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

        [Parameter(Mandatory = $false)]
        [string[]]$Fields,

        [Parameter(Mandatory = $false)]
        [ValidateSet("None", "Relations", "Fields", "Links", "All")]
        [string]$Expand = "None",

        [Parameter(Mandatory = $false)]
        [datetime]$AsOf,

        [Parameter(Mandatory = $false)]
        [ValidateSet("Fail", "Omit")]
        [string]$ErrorPolicy = "Fail",

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of work items batch in Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "_apis/wit/workitemsbatch"
            if ($Project) { $apiUri = "$Project/$apiUri" }

            # Build the request body
            $body = @{
                ids = $Ids
            }
            if ($Fields) { $body.fields = $Fields }
            if ($Expand -ne "None") { $body.'$expand' = $Expand }
            if ($AsOf) { $body.asOf = $AsOf.ToString("yyyy-MM-ddTHH:mm:ssZ") }
            if ($ErrorPolicy) { $body.errorPolicy = $ErrorPolicy }
            $body = $body | ConvertTo-Json -Depth 10

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -Body $body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved work items batch in Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItemBatch"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve work items batch: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of work items batch in Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of work items by their IDs.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a list of work items based on their IDs.
        Additional parameters allow filtering by fields, expanding attributes, and specifying error handling policies.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER Project
        The ID or name of the project. This parameter is optional.
         
    .PARAMETER Ids
        A comma-separated list of work item IDs to retrieve (maximum 200 IDs).
         
    .PARAMETER Fields
        A comma-separated list of requested fields. This parameter is optional.
         
    .PARAMETER Expand
        Optional parameter to expand specific attributes of the work items (e.g., None, Relations, Fields, Links, All).
         
    .PARAMETER AsOf
        Optional parameter to specify the UTC date-time string for retrieving work items as of a specific time.
         
    .PARAMETER ErrorPolicy
        Optional parameter to specify the error policy (e.g., Fail, Omit).
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        Get-ADOWorkItemsList -Organization "fabrikam" -Token "my-token" -Ids "297,299,300"
         
        Retrieves the specified work items by their IDs.
         
    .EXAMPLE
        Get-ADOWorkItemsList -Organization "fabrikam" -Token "my-token" -Ids "297,299,300" -Fields "System.Id,System.Title,System.WorkItemType" -Expand "Fields"
         
        Retrieves the specified work items with specific fields expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemsList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

        [Parameter()]
        [string]$Project = $null,

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

        [Parameter()]
        [string]$Fields = $null,

        [Parameter()]
        [ValidateSet("None", "Relations", "Fields", "Links", "All")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$AsOf = $null,

        [Parameter()]
        [ValidateSet("Fail", "Omit")]
        [string]$ErrorPolicy = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of work items for Organization: $Organization"
        if ($Project) {
            Write-PSFMessage -Level Verbose -Message "Project: $Project"
        }
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = if ($Project) {
                "$Project/_apis/wit/workitems?ids=$Ids"
            } else {
                "_apis/wit/workitems?ids=$Ids"
            }

            if ($Fields) {
                $apiUri += "&fields=$Fields"
            }
            if ($Expand) {
                $apiUri += "&`$expand=$Expand"
            }
            if ($AsOf) {
                $apiUri += "&asOf=$AsOf"
            }
            if ($ErrorPolicy) {
                $apiUri += "&errorPolicy=$ErrorPolicy"
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved work items for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItem"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve work items: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of work items for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a single work item type in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a single work item type in a process.
        It supports optional parameters to expand specific properties of the work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the work item type (e.g., behaviors, layout, states).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemType -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest"
         
        Retrieves the specified work item type in the given process.
         
    .EXAMPLE
        Get-ADOWorkItemType -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Expand "layout"
         
        Retrieves the specified work item type with the layout property expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemType {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [ValidateSet("behaviors", "layout", "states", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion =  $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$($ProcessId)/workitemtypes/$WitRefName" + "?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve work item type: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a specific field in a work item type.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific field in a specified work item type.
        It supports optional parameters to expand specific properties of the field.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER FieldRefName
        The reference name of the field to retrieve.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the field (e.g., allowedValues, all, none).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeField -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -FieldRefName "System.State"
         
        Retrieves the specified field in the work item type.
         
    .EXAMPLE
        Get-ADOWorkItemTypeField -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -FieldRefName "System.State" -Expand "allowedValues"
         
        Retrieves the specified field with allowed values expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [ValidateSet("all", "allowedValues", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/fields/$FieldRefName" + "?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeFieldObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all fields in a work item type.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve all fields in a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeFieldList -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest"
         
        Retrieves all fields in the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeFieldList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of fields for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/fields"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved fields for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeFieldObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve fields: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of fields for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Gets the form layout of a work item type in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve the form layout of a specified work item type in a process.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.2-preview.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeLayout -Organization "fabrikam" -Token "my-token" -ProcessId "a6c1d9b6-ea27-407d-8c40-c9b7ab112bb6" -WitRefName "Agile1.Bug"
         
        Retrieves the form layout of the specified work item type in the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeLayout {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of form layout for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved form layout for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.FormLayout"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve form layout: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of form layout for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all work item types in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve all work item types in a process.
        It supports optional parameters to expand specific properties of the work item types.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER Expand
        Optional parameter to expand specific properties of the work item types (e.g., behaviors, layout, states).
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeList -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218"
         
        Retrieves all work item types in the specified process.
         
    .EXAMPLE
        Get-ADOWorkItemTypeList -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -Expand "states"
         
        Retrieves all work item types in the specified process with the states property expanded.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [ValidateSet("behaviors", "layout", "states", "none")]
        [string]$Expand = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of work item types for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId" + "/workitemtypes?"
            if ($Expand) {
                $apiUri += "`$expand=$Expand&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the API URI
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved work item types for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve work item types: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of work item types for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a single rule in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a specific rule for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER RuleId
        The ID of the rule to retrieve.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeRule -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -RuleId "9c24d726-da1d-48ad-a2e8-032a80fc794b"
         
        Retrieves the specified rule for the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeRule {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/rules/$RuleId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeRuleObject"
       } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve rule: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all rules in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve all rules for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeRuleList -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest"
         
        Retrieves all rules for the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeRuleList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of rules for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/rules"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved rules for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeRuleObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve rules: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of rules for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a single state definition in a work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve a single state definition for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER StateId
        The ID of the state to retrieve.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeState -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -StateId "7b7e3e8c-e500-40b6-ad56-d59b8d64d757"
         
        Retrieves the specified state definition for the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeState {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states/$StateId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeStateObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve state: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Retrieves a list of all state definitions in a work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and retrieve all state definitions for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Get-ADOWorkItemTypeStateList -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest"
         
        Retrieves all state definitions for the specified work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Get-ADOWorkItemTypeStateList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting retrieval of state definitions for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully retrieved state definitions for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeStateObject" 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to retrieve state definitions: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed retrieval of state definitions for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Hides a state definition in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and hide a state definition in a specified work item type of a process.
        Only states with `customizationType: System` can be hidden.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER StateId
        The ID of the state to hide.
         
    .PARAMETER Hidden
        Boolean value indicating whether the state should be hidden.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "hidden": "true"
        }
        "@
         
        Hide-ADOWorkItemTypeState -Organization "fabrikam" -Token "my-token" -ProcessId "a6c1d9b6-ea27-407d-8c40-c9b7ab112bb6" -WitRefName "Agile1.Bug" -StateId "f36cfea7-889a-448e-b5d1-fbc9b134ec82" -Hidden $true
         
        Hides the specified state definition in the work item type of the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Hide-ADOWorkItemTypeState {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter(Mandatory = $true)]
        [ValidateSet("true", "false")]
        [string]$Hidden,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting to hide state definition '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states/$StateId"

            # Build the request body
            $body = @{
                hidden = $Hidden
            } | ConvertTo-Json -Depth 10

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully hid state definition '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeStateObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to hide state definition: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed hiding of state definition '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Checks the existence of a WIQL query in Azure DevOps using a query ID.
         
    .DESCRIPTION
        This function allows you to check the existence of a WIQL query in Azure DevOps by providing the query ID.
        It supports optional parameters to limit the number of results, enable time precision, and specify a team context.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Team
        (Optional) The name or ID of the Azure DevOps team.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER QueryId
        The ID of the WIQL query to check.
         
    .PARAMETER TimePrecision
        (Optional) Whether or not to use time precision. Default is `$false`.
         
    .PARAMETER Top
        (Optional) The maximum number of results to return.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Check the existence of a WIQL query by ID
         
        Invoke-ADOWiqlQuery -Organization "my-org" -Project "my-project" -Token "my-token" -QueryId "12345678-1234-1234-1234-123456789abc"
         
    .EXAMPLE
        # Example 2: Check the existence of a WIQL query by ID with time precision and limit results to 10
         
        Invoke-ADOWiqlQuery -Organization "my-org" -Project "my-project" -Token "my-token" -QueryId "12345678-1234-1234-1234-123456789abc" -TimePrecision $true -Top 10
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Invoke-ADOWiqlQuery {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

        [Parameter(Mandatory = $false)]
        [string]$Team,

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

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

        [Parameter(Mandatory = $false)]
        [switch]$TimePrecision,

        [Parameter(Mandatory = $false)]
        [int]$Top,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting WIQL query existence check in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/wit/wiql/$QueryId"
            if ($Project) { $apiUri = "$Project/$apiUri" }
            if ($Team) { $apiUri = "$Team/$apiUri" }

            # Append query parameters directly to the URI
            $queryParams = @()
            if ($TimePrecision) { $queryParams += "timePrecision=$TimePrecision" }
            if ($Top) { $queryParams += "`$top=$Top" }
            if ($queryParams.Count -gt 0) {
                $apiUri += "?" + ($queryParams -join "&")
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "HEAD" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully checked WIQL query existence in Organization: $Organization, Project: $Project"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItemQueryResult"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to check WIQL query existence: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed WIQL query existence check in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Executes a WIQL query in Azure DevOps using a query ID and retrieves the results.
         
    .DESCRIPTION
        This function allows you to execute a WIQL query in Azure DevOps by providing the query ID.
        It supports optional parameters to limit the number of results, enable time precision, and specify a team context.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Team
        (Optional) The name or ID of the Azure DevOps team.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER QueryId
        The ID of the WIQL query to execute.
         
    .PARAMETER TimePrecision
        (Optional) Whether or not to use time precision. Default is `$false`.
         
    .PARAMETER Top
        (Optional) The maximum number of results to return.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Execute a WIQL query by ID
         
        Invoke-ADOWiqlQueryById -Organization "my-org" -Project "my-project" -Token "my-token" -QueryId "12345678-1234-1234-1234-123456789abc"
         
    .EXAMPLE
        # Example 2: Execute a WIQL query by ID with time precision and limit results to 10
         
        Invoke-ADOWiqlQueryById -Organization "my-org" -Project "my-project" -Token "my-token" -QueryId "12345678-1234-1234-1234-123456789abc" -TimePrecision $true -Top 10
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Invoke-ADOWiqlQueryById {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

        [Parameter(Mandatory = $false)]
        [string]$Team,

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

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

        [Parameter(Mandatory = $false)]
        [switch]$TimePrecision,

        [Parameter(Mandatory = $false)]
        [int]$Top,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting WIQL query execution by ID in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/wit/wiql/$QueryId"
            if ($Project) { $apiUri = "$Project/$apiUri" }
            if ($Team) { $apiUri = "$Team/$apiUri" }

            # Append query parameters directly to the URI
            $queryParams = @()
            if ($TimePrecision) { $queryParams += "timePrecision=$TimePrecision" }
            if ($Top) { $queryParams += "`$top=$Top" }
            if ($queryParams.Count -gt 0) {
                $apiUri += "?" + ($queryParams -join "&")
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "GET" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully executed WIQL query by ID in Organization: $Organization, Project: $Project"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItemQueryResult"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to execute WIQL query by ID: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed WIQL query execution by ID in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Executes a WIQL (Work Item Query Language) query in Azure DevOps and retrieves the results.
         
    .DESCRIPTION
        This function allows you to execute a WIQL query in Azure DevOps to retrieve work items or work item links.
        It supports optional parameters to limit the number of results, enable time precision, and specify a team context.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Team
        (Optional) The name or ID of the Azure DevOps team.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Query
        The WIQL query string to execute.
         
    .PARAMETER TimePrecision
        (Optional) Whether or not to use time precision. Default is `$false`.
         
    .PARAMETER Top
        (Optional) The maximum number of results to return.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Execute a WIQL query to retrieve all active tasks
         
        $query = "Select [System.Id], [System.Title], [System.State] From WorkItems Where [System.WorkItemType] = 'Task' AND [State] <> 'Closed' order by [System.CreatedDate] desc"
        Invoke-ADOWiqlQueryByWiql -Organization "my-org" -Project "my-project" -Token "my-token" -Query $query
         
    .EXAMPLE
        # Example 2: Execute a WIQL query with time precision and limit results to 10
         
        $query = "Select [System.Id], [System.Title] From WorkItems Where [System.WorkItemType] = 'Bug'"
        Invoke-ADOWiqlQueryByWiql -Organization "my-org" -Project "my-project" -Token "my-token" -Query $query -TimePrecision $true -Top 10
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Invoke-ADOWiqlQueryByWiql {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

        [Parameter(Mandatory = $false)]
        [string]$Team,

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

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

        [Parameter(Mandatory = $false)]
        [switch]$TimePrecision,

        [Parameter(Mandatory = $false)]
        [int]$Top,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting WIQL query execution in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/wit/wiql"
            if ($Project) { $apiUri = "$Project/$apiUri" }
            if ($Team) { $apiUri = "$Team/$apiUri" }

            # Append query parameters directly to the URI
            $queryParams = @()
            if ($TimePrecision) { $queryParams += "timePrecision=$TimePrecision" }
            if ($Top) { $queryParams += "`$top=$Top" }
            if ($queryParams.Count -gt 0) {
                $apiUri += "?" + ($queryParams -join "&")
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Prepare the request body
            $body = @{
                query = $Query
            } | ConvertTo-Json -Depth 10

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "POST" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -Body $body `
                                            -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully executed WIQL query in Organization: $Organization, Project: $Project"
            return $response.Results | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItemQueryResult"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to execute WIQL query: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed WIQL query execution in Organization: $Organization, Project: $Project"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Moves a control to a specified group.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and move a control to a new group in a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER GroupId
        The ID of the group to move the control to.
         
    .PARAMETER ControlId
        The ID of the control to move.
         
    .PARAMETER Body
        The JSON string containing the properties for the control to move.
         
    .PARAMETER RemoveFromGroupId
        Optional parameter specifying the group ID to remove the control from.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "label": "",
            "readonly": false,
            "id": "c1681eea-cf9e-4a32-aee9-83e97fde894a",
            "isContribution": true,
            "visible": true,
            "contribution": {
                "contributionId": "ms-devlabs.toggle-control.toggle-control-contribution",
                "inputs": {
                    "FieldName": "System.BoardColumnDone",
                    "TrueLabel": "new value"
                }
            },
            "order": 0
        }
        "@
         
        Move-ADOWorkItemTypeGroupControl -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -GroupId "new-group-id" -ControlId "control-id" -Body $body -RemoveFromGroupId "old-group-id"
         
        Moves the specified control to a new group.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Move-ADOWorkItemTypeGroupControl {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

        [Parameter()]
        [string]$RemoveFromGroupId = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting move of control '$ControlId' to group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/groups/$GroupId/controls/$ControlId?"
            if ($RemoveFromGroupId) {
                $apiUri += "removeFromGroupId=$RemoveFromGroupId&"
            }

            # Remove trailing '&' or '?' if present
            $apiUri = $apiUri.TrimEnd('&', '?')

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully moved control '$ControlId' to group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupControlObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to move control: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed move of control '$ControlId' to group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Moves a group to a different page and section.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and move a group to a new page and section in a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page to move the group to.
         
    .PARAMETER SectionId
        The ID of the section to move the group to.
         
    .PARAMETER GroupId
        The ID of the group to move.
         
    .PARAMETER RemoveFromPageId
        The ID of the page to remove the group from.
         
    .PARAMETER RemoveFromSectionId
        The ID of the section to remove the group from.
         
    .PARAMETER Body
        The JSON string containing the properties for the group to move.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "controls": null,
            "id": "35654520-69b9-446d-946a-00e0e958f2b2",
            "label": "Group1",
            "order": null,
            "overridden": null,
            "inherited": null,
            "visible": null
        }
        "@
         
        Move-ADOWorkItemTypeGroupToPage -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "new-page-id" -SectionId "new-section-id" -GroupId "group-id" -RemoveFromPageId "old-page-id" -RemoveFromSectionId "old-section-id" -Body $body
         
        Moves the specified group to a new page and section.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Move-ADOWorkItemTypeGroupToPage {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting move of group '$GroupId' to page '$PageId' and section '$SectionId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId/sections/$SectionId/groups/$($GroupId)?"
            $apiUri += "removeFromPageId=$RemoveFromPageId&removeFromSectionId=$RemoveFromSectionId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully moved group '$GroupId' to page '$PageId' and section '$SectionId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to move group: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed move of group '$GroupId' to page '$PageId' and section '$SectionId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Moves a group to a different section.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and move a group to a new section in a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page the group is in.
         
    .PARAMETER SectionId
        The ID of the section to move the group to.
         
    .PARAMETER GroupId
        The ID of the group to move.
         
    .PARAMETER RemoveFromSectionId
        The ID of the section to remove the group from.
         
    .PARAMETER Body
        The JSON string containing the properties for the group to move.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "id": "faf0f718-776c-422a-9424-3c5f7952901c",
            "label": "NewGroup1",
            "controls": null,
            "order": 1,
            "visible": true,
            "contribution": null,
            "isContribution": false,
            "height": null
        }
        "@
         
        Move-ADOWorkItemTypeGroupToSection -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "page-id" -SectionId "new-section-id" -GroupId "group-id" -RemoveFromSectionId "old-section-id" -Body $body
         
        Moves the specified group to a new section.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Move-ADOWorkItemTypeGroupToSection {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting move of group '$GroupId' to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI with optional parameters
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId/sections/$SectionId/groups/$GroupId?"
            $apiUri += "removeFromSectionId=$RemoveFromSectionId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully moved group '$GroupId' to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to move group: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed move of group '$GroupId' to section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a picklist.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and delete a picklist by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ListId
        The ID of the picklist to delete.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOPickList -Organization "fabrikam" -Token "my-token" -ListId "661eb38e-6f0b-484a-bc53-27a57c2e2d50"
         
        Deletes the specified picklist by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOPickList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of picklist with ID '$ListId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/lists/$ListId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed picklist with ID '$ListId' for Organization: $Organization"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove picklist: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of picklist with ID '$ListId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a process by its ID.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and delete a specific process by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessTypeId
        The ID of the process to delete.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOProcess -Organization "fabrikam" -Token "my-token" -ProcessTypeId "adcc42ab-9882-485e-a3ed-7678f01f66bc"
         
        Deletes the specified process by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOProcess {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of process with ID '$ProcessTypeId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessTypeId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed process with ID '$ProcessTypeId' for Organization: $Organization"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove process: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of process with ID '$ProcessTypeId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a behavior in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a behavior from a specified process.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER BehaviorRefName
        The reference name of the behavior to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOProcessBehavior -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -BehaviorRefName "Custom.891ef145-4c43-4151-a756-7a8b2d489ee5"
         
        Removes the specified behavior from the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOProcessBehavior {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of behavior '$BehaviorRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/behaviors/$BehaviorRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{ "Content-Type" = "application/json"  } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed behavior '$BehaviorRefName' for ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove behavior: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of behavior '$BehaviorRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Queues a project to be deleted in Azure DevOps.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and queue a project for deletion.
        Use the `GetOperation` API to periodically check the status of the delete operation.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProjectId
        The ID of the project to delete.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is set globally.
         
    .EXAMPLE
        Remove-ADOProject -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c"
         
        Queues the project with the specified ID for deletion.
         
    .NOTES
        This function requires the `Invoke-ADOApiRequest` function to be defined.
        It follows PSFramework best practices for logging and error handling.
        Author: Oleksandr Nikolaiev
#>

function Remove-ADOProject {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting project deletion for ProjectId: $ProjectId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/projects/$ProjectId"

            # Call the Invoke-ADOApiRequest function to queue the project for deletion
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Project deletion queued successfully. Operation ID: $($response.id)"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to queue project deletion: $($_.ErrorDetails.Message)"  -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed project deletion request for ProjectId: $ProjectId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Deletes a field.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and delete a specific field in the specified organization and project.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER FieldNameOrRefName
        The simple name or reference name of the field to delete.
         
    .PARAMETER Project
        The ID or name of the project. This parameter is optional.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.2-preview.3".
         
    .EXAMPLE
        Remove-ADOWitField -Organization "fabrikam" -Token "my-token" -FieldNameOrRefName "System.IterationPath"
         
        Deletes the specified field in the organization.
         
    .EXAMPLE
        Remove-ADOWitField -Organization "fabrikam" -Token "my-token" -FieldNameOrRefName "System.IterationPath" -Project "MyProject"
         
        Deletes the specified field in the specified project.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWitField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

        [Parameter()]
        [string]$Project = $null,

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting deletion of field '$FieldNameOrRefName' for Organization: $Organization"
        if ($Project) {
            Write-PSFMessage -Level Verbose -Message "Project: $Project"
        }
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = if ($Project) {
                "$Project/_apis/wit/fields/$FieldNameOrRefName"
            } else {
                "_apis/wit/fields/$FieldNameOrRefName"
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully deleted field '$FieldNameOrRefName' for Organization: $Organization"
            return
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to delete field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed deletion of field '$FieldNameOrRefName' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Deletes a work item in Azure DevOps.
         
    .DESCRIPTION
        This function deletes a specified work item in Azure DevOps and sends it to the Recycle Bin.
        Optionally, the work item can be permanently destroyed if the `Destroy` parameter is set to `$true`.
        **WARNING**: If `Destroy` is set to `$true`, the deletion is permanent and cannot be undone.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Id
        The ID of the work item to delete.
         
    .PARAMETER Destroy
        (Optional) Indicates if the work item should be permanently destroyed. Default is `$false`.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `$Script:ADOApiVersion`.
         
    .EXAMPLE
        # Example 1: Delete a work item and send it to the Recycle Bin
         
        Remove-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Id 12345
         
    .EXAMPLE
        # Example 2: Permanently delete a work item
         
        Remove-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Id 12345 -Destroy $true
         
    .NOTES
        Author: Oleksandr Nikolaiev (@onikolaiev)
         
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
#>


function Remove-ADOWorkItem {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

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

        [Parameter(Mandatory = $true)]
        [int]$Id,

        [Parameter(Mandatory = $false)]
        [switch]$Destroy,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting deletion of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "_apis/wit/workitems/$Id"
            if ($Project) { $apiUri = "$Project/$apiUri" }

            # Append query parameters
            if ($Destroy) {
                $apiUri += "?destroy=$Destroy"
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully deleted work item ID: $Id in Organization: $Organization"
            return
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to delete work item ID: $Id : $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed deletion of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a work item type in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and delete a work item type in a specified process.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type to delete.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemType -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest"
         
        Removes the specified work item type from the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemType {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting deletion of work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workitemtypes/$WitRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully deleted work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to delete work item type: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed deletion of work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a field from a work item type.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a field from a specified work item type.
        Note: This does not permanently delete the field.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER FieldRefName
        The reference name of the field to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypeField -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -FieldRefName "Custom.Fields.Colors"
         
        Removes the specified field from the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypeField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of field '$FieldRefName' from work item type '$WitRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/fields/$FieldRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -Method "DELETE" `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed field '$FieldRefName' from work item type '$WitRefName' for ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of field '$FieldRefName' from work item type '$WitRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a group from the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a group from a specified section on a page in a work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page the group is in.
         
    .PARAMETER SectionId
        The ID of the section the group is in.
         
    .PARAMETER GroupId
        The ID of the group to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypeGroup -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "page-id" -SectionId "section-id" -GroupId "group-id"
         
        Removes the specified group from the section on the page.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypeGroup {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of group '$GroupId' from section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId/sections/$SectionId/groups/$GroupId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed group '$GroupId' from section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove group: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of group '$GroupId' from section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a control from the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a control from a specified group in a work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER GroupId
        The ID of the group containing the control.
         
    .PARAMETER ControlId
        The ID of the control to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypeGroupControl -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -GroupId "group-id" -ControlId "control-id"
         
        Removes the specified control from the group.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypeGroupControl {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of control '$ControlId' from group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/groups/$GroupId/controls/$ControlId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed control '$ControlId' from group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove control: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of control '$ControlId' from group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a page from the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a page from the layout of a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypePage -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "230f8598-71ed-4192-917e-aa1aacc5174a"
         
        Removes the specified page from the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypePage {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of page '$PageId' from work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed page '$PageId' from work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove page: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of page '$PageId' from work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a rule from the work item type in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a rule from a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER RuleId
        The ID of the rule to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypeRule -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -RuleId "9c24d726-da1d-48ad-a2e8-032a80fc794b"
         
        Removes the specified rule from the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypeRule {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of rule '$RuleId' from work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/rules/$RuleId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed rule '$RuleId' from work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove rule: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of rule '$RuleId' from work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Removes a state definition in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and remove a state definition for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER StateId
        The ID of the state to remove.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        Remove-ADOWorkItemTypeState -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -StateId "7b7e3e8c-e500-40b6-ad56-d59b8d64d757"
         
        Removes the specified state definition for the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Remove-ADOWorkItemTypeState {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting removal of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states/$StateId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "DELETE" `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully removed state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to remove state: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed removal of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Create, update, or delete team project properties in Azure DevOps.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and perform operations on team project properties.
        It supports operations such as add, remove, replace, and more using JSON Patch.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProjectId
        The ID of the project to update properties for.
         
    .PARAMETER Body
        The JSON Patch document as a string, specifying the operations to perform on the project properties.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1-preview.1".
         
    .EXAMPLE
        $body = @"
        [
        {
            "op": "add",
            "path": "/Alias",
            "value": "Fabrikam"
        }
        ]
        "@
         
        Set-ADOProjectPropertieList -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c" -Body $body
         
        Creates or updates the "Alias" property for the specified project.
         
    .EXAMPLE
        $body = @"
        [
        {
            "op": "remove",
            "path": "/Alias"
        }
        ]
        "@
         
        Set-ADOProjectPropertieList -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c" -Body $body
         
        Deletes the "Alias" property for the specified project.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Set-ADOProjectPropertieList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of project properties for ProjectId: $ProjectId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/projects/$ProjectId/properties"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $null = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion `
                                             -Headers @{ "Content-Type" = "application/json" }

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated project properties for ProjectId: $ProjectId"
            return 
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update project properties: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of project properties for ProjectId: $ProjectId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a picklist.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a picklist by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ListId
        The ID of the picklist to update.
         
    .PARAMETER Body
        The JSON string containing the properties for the picklist to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "id": "a07a079a-c79e-4221-9436-a9d732a8a4d0",
            "name": null,
            "type": null,
            "items": [
            "Blue",
            "Red"
            ],
            "isSuggested": false,
            "url": null
        }
        "@
         
        Update-ADOPickList -Organization "fabrikam" -Token "my-token" -ListId "a07a079a-c79e-4221-9436-a9d732a8a4d0" -Body $body
         
        Updates the specified picklist by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOPickList {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of picklist with ID '$ListId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/lists/$ListId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated picklist with ID '$ListId' for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.PickListObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update picklist: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of picklist with ID '$ListId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Edits a process by its ID.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a specific process by its ID.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessTypeId
        The ID of the process to edit.
         
    .PARAMETER Body
        The JSON string containing the properties to update for the process.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "MyNewAgileProcess_Renamed",
            "description": "My new renamed process",
            "isDefault": false,
            "isEnabled": false
        }
        "@
         
        Update-ADOProcess -Organization "fabrikam" -Token "my-token" -ProcessTypeId "fb70612d-c6d5-421a-ace1-04939e81b669" -Body $body
         
        Updates the specified process by its ID.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOProcess {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of process with ID '$ProcessTypeId' for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessTypeId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated process with ID '$ProcessTypeId' for Organization: $Organization"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update process: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of process with ID '$ProcessTypeId' for Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a behavior in the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a specific behavior for a specified process.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER BehaviorRefName
        The reference name of the behavior.
         
    .PARAMETER Body
        The JSON string containing the properties for the behavior to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "NewCustomBehavior",
            "color": "FFFABC"
        }
        "@
         
        Update-ADOProcessBehavior -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -BehaviorRefName "Custom.4b8fdba0-7064-458d-b55c-522b39059a62" -Body $body
         
        Updates the specified behavior for the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOProcessBehavior {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of behavior '$BehaviorRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/behaviors/$BehaviorRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated behavior '$BehaviorRefName' for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.ProcessBehaviorObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update behavior: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of behavior '$BehaviorRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates an existing Azure DevOps project.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update an existing project's properties.
        It expects the request body as a JSON string parameter.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProjectId
        The ID of the project to update.
         
    .PARAMETER Body
        The JSON string containing the properties to update for the project.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use.
         
    .EXAMPLE
        $body = @"
        {
            "name": "New Project Name",
            "description": "Updated description",
            "visibility": "Private"
        }
        "@
         
        Update-ADOProject -Organization "fabrikam" -Token "my-token" -ProjectId "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c" -Body $body
         
        Updates the specified project with the provided properties.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOProject {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update for ProjectId: $ProjectId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/projects/$($ProjectId)"

            # Log the request body
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method Patch `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated project with ProjectId: $ProjectId"
            return $response
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update project: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update for ProjectId: $ProjectId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a field in Azure DevOps.
         
    .DESCRIPTION
        This function updates a specified field in Azure DevOps. It supports optional parameters to lock or unlock the field and to restore or delete the field.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER FieldNameOrRefName
        The name or reference name of the field to update.
         
    .PARAMETER IsLocked
        (Optional) Indicates whether the field should be locked for editing.
         
    .PARAMETER IsDeleted
        (Optional) Indicates whether the field should be restored or deleted.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Lock a field
         
        Update-ADOWitField -Organization "my-org" -Token "my-token" -FieldNameOrRefName "Custom.TestField" -IsLocked $true
         
    .EXAMPLE
        # Example 2: Restore a deleted field
         
        Update-ADOWitField -Organization "my-org" -Token "my-token" -FieldNameOrRefName "Custom.TestField" -IsDeleted $false
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Update-ADOWitField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

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

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

        [Parameter(Mandatory = $false)]
        [switch]$IsLocked,

        [Parameter(Mandatory = $false)]
        [switch]$IsDeleted,

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of field: $FieldNameOrRefName in Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "_apis/wit/fields/$FieldNameOrRefName"
            if ($Project) { $apiUri = "$Project/$apiUri" }

            # Build the request body
            $body = @{}
            if ($IsLocked.IsPresent) { $body.isLocked = $IsLocked }
            if ($IsDeleted.IsPresent) { $body.isDeleted = $IsDeleted }
            $body = $body | ConvertTo-Json -Depth 10

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -Body $body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated field: $FieldNameOrRefName in Organization: $Organization"
            return $response | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItemField2"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update field: $FieldNameOrRefName : $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of field: $FieldNameOrRefName in Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a work item in Azure DevOps.
         
    .DESCRIPTION
        This function updates a specified work item in Azure DevOps using a JSON Patch document.
        It supports optional parameters to validate changes, bypass rules, suppress notifications, and expand additional attributes of the work item.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Project
        (Optional) The name or ID of the Azure DevOps project.
         
    .PARAMETER Token
        The personal access token (PAT) used for authentication.
         
    .PARAMETER Id
        The ID of the work item to update.
         
    .PARAMETER Body
        The JSON Patch document containing the fields and values to update.
         
    .PARAMETER ValidateOnly
        (Optional) Indicates if you only want to validate the changes without saving the work item. Default is `$false`.
         
    .PARAMETER BypassRules
        (Optional) Indicates if work item type rules should be bypassed. Default is `$false`.
         
    .PARAMETER SuppressNotifications
        (Optional) Indicates if notifications should be suppressed for this change. Default is `$false`.
         
    .PARAMETER Expand
        (Optional) Specifies the expand parameters for work item attributes. Possible values are `None`, `Relations`, `Fields`, `Links`, or `All`.
         
    .PARAMETER ApiVersion
        (Optional) The API version to use. Default is `7.1`.
         
    .EXAMPLE
        # Example 1: Update a work item by ID
        $body = @(
            @{
            op = "add"
            path = "/fields/System.Title"
            value = "Updated Title"
        }
        )
         
        Update-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Id 12345 -Body $body
         
    .EXAMPLE
        # Example 2: Validate an update without saving
        $body = @(
            @{
            op = "add"
            path = "/fields/System.History"
            value = "Adding a comment for context"
        }
        )
         
        Update-ADOWorkItem -Organization "my-org" -Project "my-project" -Token "my-token" -Id 12345 -Body $body -ValidateOnly $true
         
    .NOTES
        This function is part of the ADO Tools module and adheres to the conventions used in the module for logging, error handling, and API interaction.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>


function Update-ADOWorkItem {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

        [Parameter(Mandatory = $false)]
        [string]$Project,

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

        [Parameter(Mandatory = $true)]
        [int]$Id,

        [Parameter(Mandatory = $true)]
        [PSCustomObject[]]$Body,

        [Parameter(Mandatory = $false)]
        [switch]$ValidateOnly,

        [Parameter(Mandatory = $false)]
        [switch]$BypassRules,

        [Parameter(Mandatory = $false)]
        [switch]$SuppressNotifications,

        [Parameter(Mandatory = $false)]
        [ValidateSet("None", "Relations", "Fields", "Links", "All")]
        [string]$Expand = "None",

        [Parameter(Mandatory = $false)]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -Start
    }

    process {
        if (Test-PSFFunctionInterrupt) { return }
        try {
            # Build the API URI
            $apiUri = "_apis/wit/workitems/$Id"
            if ($Project) { $apiUri = "$Project/$apiUri" }

            # Append query parameters
            if ($ValidateOnly) {
                $apiUri += "?validateOnly=$ValidateOnly"
            }
            if ($BypassRules) {
                $apiUri += if ($apiUri.Contains("?")) { "&bypassRules=$BypassRules" } else { "?bypassRules=$BypassRules" }
            }
            if ($SuppressNotifications) {
                $apiUri += if ($apiUri.Contains("?")) { "&suppressNotifications=$SuppressNotifications" } else { "?suppressNotifications=$SuppressNotifications" }
            }
            if ($Expand -ne "None") {
                $apiUri += if ($apiUri.Contains("?")) { "&`$expand=$Expand" } else { "?`$expand=$Expand" }
            }

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Headers @{"Content-Type" = "application/json-patch+json"} `
                                             -Body $Body `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated work item ID: $Id in Organization: $Organization"
            return $response | Select-PSFObject * -TypeName "ADO.TOOLS.WorkItem"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update work item ID: $Id : $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of work item ID: $Id in Organization: $Organization"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a work item type in a process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a work item type in a specified process.
        The request body is passed as a string variable.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type to update.
         
    .PARAMETER Body
        The JSON string containing the properties to update for the work item type.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "description": "Updated description",
            "color": "f6546a",
            "icon": "icon_airplane",
            "isDisabled": false
        }
        "@
         
        Update-ADOWorkItemType -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Updates the specified work item type in the process.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemType {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workitemtypes/$WitRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update work item type: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a field in a work item type.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a field in a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER FieldRefName
        The reference name of the field to update.
         
    .PARAMETER Body
        The JSON string containing the properties to update for the field.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "defaultValue": "Blue"
        }
        "@
         
        Update-ADOWorkItemTypeField -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -FieldRefName "Custom.Fields.Colors" -Body $body
         
        Updates the specified field in the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypeField {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId in Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/fields/$FieldRefName"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeFieldObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update field: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of field '$FieldRefName' in work item type '$WitRefName' for ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a group in the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a group in a specified section on a page in a work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER PageId
        The ID of the page the group is in.
         
    .PARAMETER SectionId
        The ID of the section the group is in.
         
    .PARAMETER GroupId
        The ID of the group to update.
         
    .PARAMETER Body
        The JSON string containing the properties for the group to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "controls": null,
            "id": "faf0f718-776c-422a-9424-3c5f7952901c",
            "label": "NewGroup1",
            "order": null,
            "overridden": null,
            "inherited": null,
            "visible": null
        }
        "@
         
        Update-ADOWorkItemTypeGroup -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -PageId "page-id" -SectionId "section-id" -GroupId "group-id" -Body $body
         
        Updates the specified group in the section on the page.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypeGroup {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of group '$GroupId' in section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages/$PageId/sections/$SectionId/groups/$GroupId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated group '$GroupId' in section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update group: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of group '$GroupId' in section '$SectionId' on page '$PageId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a control on the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a control in a specified group.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER GroupId
        The ID of the group containing the control.
         
    .PARAMETER ControlId
        The ID of the control to update.
         
    .PARAMETER Body
        The JSON string containing the properties for the control to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "order": null,
            "label": "",
            "readOnly": false,
            "visible": true,
            "controlType": null,
            "id": "c1681eea-cf9e-4a32-aee9-83e97fde894a",
            "metadata": null,
            "inherited": null,
            "overridden": null,
            "watermark": null,
            "contribution": {
                "contributionId": "ms-devlabs.toggle-control.toggle-control-contribution",
                "inputs": {
                    "FieldName": "System.BoardColumnDone",
                    "TrueLabel": "new value"
                },
                "height": null,
                "showOnDeletedWorkItem": null
            },
            "isContribution": true,
            "height": null
        }
        "@
         
        Update-ADOWorkItemTypeGroupControl -Organization "fabrikam" -Token "my-token" -ProcessId "906c7065-2a04-4f61-aac1-b5da9cef040b" -WitRefName "MyNewAgileProcess.ChangeRequest" -GroupId "group-id" -ControlId "control-id" -Body $body
         
        Updates the specified control in the group.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypeGroupControl {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of control '$ControlId' in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/groups/$GroupId/controls/$ControlId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated control '$ControlId' in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeGroupControlObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update control: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of control '$ControlId' in group '$GroupId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a page on the work item form.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a page in the layout of a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER Body
        The JSON string containing the properties for the page to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "sections": null,
            "id": "230f8598-71ed-4192-917e-aa1aacc5174a",
            "label": "Page2",
            "overridden": null,
            "inherited": null,
            "visible": true,
            "locked": false,
            "pageType": "custom",
            "contribution": null
        }
        "@
         
        Update-ADOWorkItemTypePage -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -Body $body
         
        Updates the specified page in the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypePage {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of a page in work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/layout/pages"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{"Content-Type" = "application/json"} `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated a page in work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypePageObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update a page: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of a page in work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a rule in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a rule for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER RuleId
        The ID of the rule to update.
         
    .PARAMETER Body
        The JSON string containing the properties for the rule to update.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "id": "238ea945-a184-47f1-b458-9f858e9e552f",
            "name": "myRule",
            "conditions": [
            {
                "conditionType": "$when",
                "field": "Microsoft.VSTS.Common.Priority",
                "value": "1"
            },
            {
                "conditionType": "$when",
                "field": "System.State",
                "value": "Active"
            }
            ],
            "actions": [
            {
                "actionType": "$copyValue",
                "targetField": "Microsoft.VSTS.Common.Severity",
                "value": "1 - Critical"
            }
            ],
            "isDisabled": true
        }
        "@
         
        Update-ADOWorkItemTypeRule -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -RuleId "238ea945-a184-47f1-b458-9f858e9e552f" -Body $body
         
        Updates the specified rule for the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypeRule {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/rules/$RuleId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PUT" `
                                             -Body $Body `
                                                -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeRuleObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update rule: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of rule '$RuleId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}


<#
    .SYNOPSIS
        Updates a given state definition in the work item type of the process.
         
    .DESCRIPTION
        This function uses the `Invoke-ADOApiRequest` function to call the Azure DevOps REST API and update a state definition for a specified work item type.
         
    .PARAMETER Organization
        The name of the Azure DevOps organization.
         
    .PARAMETER Token
        The authentication token for accessing Azure DevOps.
         
    .PARAMETER ProcessId
        The ID of the process where the work item type exists.
         
    .PARAMETER WitRefName
        The reference name of the work item type.
         
    .PARAMETER StateId
        The ID of the state to update.
         
    .PARAMETER Body
        The JSON string containing the properties to update for the state.
         
    .PARAMETER ApiVersion
        The version of the Azure DevOps REST API to use. Default is "7.1".
         
    .EXAMPLE
        $body = @"
        {
            "name": "CustomState2",
            "color": "5688E0"
        }
        "@
         
        Update-ADOWorkItemTypeState -Organization "fabrikam" -Token "my-token" -ProcessId "c5ef8a1b-4f0d-48ce-96c4-20e62993c218" -WitRefName "MyNewAgileProcess.ChangeRequest" -StateId "dada09e4-6f80-46b5-887b-8051981bcf00" -Body $body
         
        Updates the specified state definition for the work item type.
         
    .NOTES
        This function follows PSFramework best practices for logging and error handling.
         
        Author: Oleksandr Nikolaiev (@onikolaiev)
#>

function Update-ADOWorkItemTypeState {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Organization,

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

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

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

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

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

        [Parameter()]
        [string]$ApiVersion = $Script:ADOApiVersion
    )

    begin {
        Invoke-TimeSignal -Start
        # Log the start of the operation
        Write-PSFMessage -Level Verbose -Message "Starting update of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId for Organization: $Organization"
    }

process {
        if (Test-PSFFunctionInterrupt) { return }      
        try {
            # Build the API URI
            $apiUri = "_apis/work/processes/$ProcessId/workItemTypes/$WitRefName/states/$StateId"

            # Log the request details
            Write-PSFMessage -Level Verbose -Message "API URI: $apiUri"
            Write-PSFMessage -Level Verbose -Message "Request Body: $Body"

            # Call the Invoke-ADOApiRequest function
            $response = Invoke-ADOApiRequest -Organization $Organization `
                                             -Token $Token `
                                             -ApiUri $apiUri `
                                             -Method "PATCH" `
                                             -Body $Body `
                                             -Headers @{ "Content-Type" = "application/json" } `
                                             -ApiVersion $ApiVersion

            # Log the successful response
            Write-PSFMessage -Level Verbose -Message "Successfully updated state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
            return $response.Results | Select-PSFObject * -TypeName "ADO.CORE.WorkItemTypeStateObject"
        } catch {
            # Log the error
            Write-PSFMessage -Level Error -Message "Failed to update state: $($_.ErrorDetails.Message)" -Exception $PSItem.Exception
            Stop-PSFFunction -Message "Stopping because of errors"
            return
        }
    }

    end {
        # Log the end of the operation
        Write-PSFMessage -Level Verbose -Message "Completed update of state '$StateId' for work item type '$WitRefName' in ProcessId: $ProcessId"
        Invoke-TimeSignal -End
    }
}