#Requires -Version 7.4

function Invoke-vSEALServiceAction {
    <#
    .SYNOPSIS
        Executes a service action with verification and baseline capture.

    .DESCRIPTION
        Changes Windows service start mode with optional stop, following the vARC
        collect-execute-verify-capture pattern. Captures the original state as
        baseline for rollback support.

        This is a vARC executor function that wraps the underlying service functions
        (Get-vSEALServiceStartMode, Stop-vSEALServiceAndDependencies) with
        consistent result structure and verification.

    .PARAMETER Name
        The name of the Windows service to modify.

    .PARAMETER StartMode
        The target start mode for the service:
        - Automatic: Service starts automatically at system boot
        - Manual: Service starts only when explicitly requested
        - Disabled: Service cannot be started

        Note: Automatic (Delayed Start) requires registry modification and is
        deferred to a future version.

    .PARAMETER StopIfRunning
        If specified and the service is currently running, stop it after changing
        the start mode. Defaults to $true.

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

    .EXAMPLE
        Invoke-vSEALServiceAction -Name 'DiagTrack' -StartMode 'Disabled'
        Disables the Connected User Experiences and Telemetry service.

    .EXAMPLE
        Invoke-vSEALServiceAction -Name 'WSearch' -StartMode 'Manual' -StopIfRunning:$false
        Sets Windows Search to manual start without stopping it if running.

    .NOTES
        Part of the vARC (vSEAL Action Rollback Core) infrastructure.
    #>
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter(Mandatory)]
        [ValidateSet('Automatic', 'Manual', 'Disabled')]
        [string]$StartMode,

        [Parameter()]
        [switch]$StopIfRunning = $true
    )

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

    # Initialize result object
    $result = [PSCustomObject]@{
        Action   = 'service.set'
        Target   = $Name
        Status   = 'Failed'
        Message  = $null
        Baseline = $null
        Duration = 0
    }

    try {
        # COLLECT: Capture original state before modification (EXEC-06 step 1)
        $originalStartMode = $null
        $originalStatus = $null

        # Check if service exists
        $service = Get-Service -Name $Name -ErrorAction SilentlyContinue
        if ($null -eq $service) {
            $result.Status = 'Skipped'
            $result.Message = "Service not found: $Name"
            $stopwatch.Stop()
            $result.Duration = [int]$stopwatch.ElapsedMilliseconds
            return $result
        }

        # Get current start mode and status
        $originalStartMode = Get-vSEALServiceStartMode -Service $Name -ErrorAction Stop
        $originalStatus = $service.Status.ToString()

        # Store baseline
        $result.Baseline = @{
            StartMode = $originalStartMode
            Status    = $originalStatus
        }

        # EXECUTE: Perform the action (EXEC-06 step 2)
        # Change the start mode
        Set-Service -Name $Name -StartupType $StartMode -ErrorAction Stop

        # Stop the service if requested and it's running
        if ($StopIfRunning -and $originalStatus -eq 'Running') {
            Stop-vSEALServiceAndDependencies -Name $Name -ErrorAction Stop
        }

        # VERIFY: Read back and compare (EXEC-06 step 3)
        $newStartMode = Get-vSEALServiceStartMode -Service $Name -ErrorAction SilentlyContinue

        # Normalize for comparison (handle Automatic (Delayed Start) matching Automatic)
        $expectedStartMode = $StartMode
        $actualStartMode = $newStartMode

        # Note: Get-vSEALServiceStartMode may return "Automatic (Delayed Start)" but we only set "Automatic"
        # So "Automatic (Delayed Start)" is acceptable when target is "Automatic"
        $verified = ($actualStartMode -eq $expectedStartMode) -or
                    ($expectedStartMode -eq 'Automatic' -and $actualStartMode -eq 'Automatic (Delayed Start)')

        if ($verified) {
            $result.Status = 'Success'
        } else {
            $result.Message = "Verification failed: expected '$expectedStartMode', got '$actualStartMode'"
        }
    }
    catch {
        $result.Status = 'Failed'
        $result.Message = $_.Exception.Message
    }
    finally {
        $stopwatch.Stop()
        $result.Duration = [int]$stopwatch.ElapsedMilliseconds
    }

    return $result
}
