#Requires -Version 7.4

function Invoke-vSEALTaskAction {
    <#
    .SYNOPSIS
        Enables or disables a scheduled task.

    .DESCRIPTION
        Executes enable/disable actions on Windows scheduled tasks with verification.
        Handles missing tasks gracefully by returning Skipped status (common when
        tasks vary by Windows edition). Returns a consistent result structure with
        baseline, timing, and verification status.

    .PARAMETER Name
        The full task path including task name.
        Example: 'Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser'

    .PARAMETER Action
        The action to perform: Enable or Disable.

    .OUTPUTS
        [PSCustomObject] Result object with Action, Target, Status, Message, Baseline, Duration.

    .EXAMPLE
        Invoke-vSEALTaskAction -Name 'Microsoft\Windows\Defrag\ScheduledDefrag' -Action Disable
        Disables the scheduled defragmentation task.

    .EXAMPLE
        Invoke-vSEALTaskAction -Name 'Microsoft\Windows\Maintenance\WinSAT' -Action Enable
        Enables the WinSAT maintenance task.
    #>
    [CmdletBinding()]
    [OutputType([psobject])]
    param(
        [Parameter(Mandatory, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory, Position = 1)]
        [ValidateSet('Enable', 'Disable')]
        [string]$Action
    )

    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

    # Normalize input: remove leading backslash if present
    $normalizedName = $Name.TrimStart('\')

    # Parse task path and name
    # For 'Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser'
    # TaskName = 'Microsoft Compatibility Appraiser'
    # TaskPath = '\Microsoft\Windows\Application Experience\'
    $parts = $normalizedName -split '\\'
    $taskName = $parts[-1]
    if ($parts.Length -gt 1) {
        $taskPath = '\' + ($parts[0..($parts.Length - 2)] -join '\') + '\'
    }
    else {
        $taskPath = '\'
    }

    Write-vSEALLog -Message "Task action '$Action' on: $Name (TaskPath=$taskPath, TaskName=$taskName)" -Level 'VERBOSE'

    # COLLECT: Get current task state
    $originalState = $null
    try {
        $task = Get-ScheduledTask -TaskPath $taskPath -TaskName $taskName -ErrorAction Stop
        $originalState = $task.State.ToString()
        Write-vSEALLog -Message "Task current state: $originalState" -Level 'VERBOSE'
    }
    catch [Microsoft.PowerShell.Cmdletization.Cim.CimJobException] {
        # Task not found
        $stopwatch.Stop()
        Write-vSEALLog -Message "Task not found: $Name (may not exist on this Windows edition)" -Level 'VERBOSE'
        return [PSCustomObject]@{
            Action   = "task.$($Action.ToLower())"
            Target   = $Name
            Status   = 'Skipped'
            Message  = 'Task not found (may not exist on this Windows edition)'
            Baseline = @{ State = $null }
            Duration = [int]$stopwatch.ElapsedMilliseconds
        }
    }
    catch {
        # Other error during collection
        $stopwatch.Stop()
        Write-vSEALLog -Message "Failed to get task '$Name': $($_.Exception.Message)" -Level 'ERROR'
        return [PSCustomObject]@{
            Action   = "task.$($Action.ToLower())"
            Target   = $Name
            Status   = 'Failed'
            Message  = "Failed to get task: $($_.Exception.Message)"
            Baseline = @{ State = $null }
            Duration = [int]$stopwatch.ElapsedMilliseconds
        }
    }

    # EXECUTE: Perform the action (use TaskPath/TaskName to avoid stale object references)
    try {
        if ($Action -eq 'Disable') {
            $null = Disable-ScheduledTask -TaskPath $taskPath -TaskName $taskName -ErrorAction Stop
            Write-vSEALLog -Message "Disabled task: $Name" -Level 'VERBOSE'
        }
        else {
            $null = Enable-ScheduledTask -TaskPath $taskPath -TaskName $taskName -ErrorAction Stop
            Write-vSEALLog -Message "Enabled task: $Name" -Level 'VERBOSE'
        }
    }
    catch {
        $stopwatch.Stop()
        Write-vSEALLog -Message "Failed to $Action task '$Name': $($_.Exception.Message)" -Level 'ERROR'
        return [PSCustomObject]@{
            Action   = "task.$($Action.ToLower())"
            Target   = $Name
            Status   = 'Failed'
            Message  = "Failed to $($Action.ToLower()) task: $($_.Exception.Message)"
            Baseline = @{ State = $originalState }
            Duration = [int]$stopwatch.ElapsedMilliseconds
        }
    }

    # VERIFY: Check new state matches expected
    $expectedState = if ($Action -eq 'Disable') { 'Disabled' } else { 'Ready' }
    try {
        $verifyTask = Get-ScheduledTask -TaskPath $taskPath -TaskName $taskName -ErrorAction Stop
        $newState = $verifyTask.State.ToString()
        Write-vSEALLog -Message "Task new state: $newState (expected: $expectedState)" -Level 'VERBOSE'

        # After Enable, task could be Ready or Running (if triggered immediately)
        $stateValid = if ($Action -eq 'Disable') {
            $newState -eq 'Disabled'
        }
        else {
            $newState -eq 'Ready' -or $newState -eq 'Running'
        }

        if (-not $stateValid) {
            $stopwatch.Stop()
            Write-vSEALLog -Message "Verification failed: expected '$expectedState' but got '$newState'" -Level 'ERROR'
            return [PSCustomObject]@{
                Action   = "task.$($Action.ToLower())"
                Target   = $Name
                Status   = 'Failed'
                Message  = "Verification failed: expected state '$expectedState' but got '$newState'"
                Baseline = @{ State = $originalState }
                Duration = [int]$stopwatch.ElapsedMilliseconds
            }
        }
    }
    catch {
        $stopwatch.Stop()
        Write-vSEALLog -Message "Verification failed for task '$Name': $($_.Exception.Message)" -Level 'ERROR'
        return [PSCustomObject]@{
            Action   = "task.$($Action.ToLower())"
            Target   = $Name
            Status   = 'Failed'
            Message  = "Verification failed: $($_.Exception.Message)"
            Baseline = @{ State = $originalState }
            Duration = [int]$stopwatch.ElapsedMilliseconds
        }
    }

    # Success
    $stopwatch.Stop()
    Write-vSEALLog -Message "Task action completed: $Action on $Name ($($stopwatch.ElapsedMilliseconds)ms)" -Level 'VERBOSE'

    return [PSCustomObject]@{
        Action   = "task.$($Action.ToLower())"
        Target   = $Name
        Status   = 'Success'
        Message  = $null
        Baseline = @{ State = $originalState }
        Duration = [int]$stopwatch.ElapsedMilliseconds
    }
}
