Functions/Public/Stop-Stopwatch.ps1

function Stop-Stopwatch {
    <#
    .SYNOPSIS
        Stops a named stopwatch and records the elapsed time.
 
    .DESCRIPTION
        Calculates the elapsed time since Start-Stopwatch was called with the same name.
        Stores the duration in a global results dictionary for later retrieval or summary.
        Optionally displays the elapsed time.
 
    .PARAMETER Name
        The same identifier used with Start-Stopwatch.
 
    .PARAMETER ShowElapsed
        Displays the stopwatch name and elapsed time when stopping.
        Can be controlled globally via $Global:ShowStopwatchEnd.
 
    .PARAMETER Quiet
        Suppresses all output, overriding both -ShowElapsed and global settings.
 
    .PARAMETER PassThru
        Returns a PSCustomObject with Name, Duration (TimeSpan), and TotalSeconds.
 
    .OUTPUTS
        None by default. PSCustomObject if -PassThru is specified.
 
    .EXAMPLE
        Start-Stopwatch -Name "Data Import"
        Import-Csv "data.csv" | Process-Data
        Stop-Stopwatch -Name "Data Import" -ShowElapsed
        # Output: Data Import completed in 2 min 34 sec
 
    .EXAMPLE
        $result = Stop-Stopwatch -Name "API Call" -PassThru
        Write-Host "API took $($result.TotalSeconds) seconds"
 
    .EXAMPLE
        $Global:ShowStopwatchEnd = $true
        Stop-Stopwatch -Name "Build"
        # Automatically shows elapsed time
 
    .NOTES
        Author: Sune Alexandersen Narud
        Version: 1.0.0
        Date: February 2026
 
    .LINK
        Start-Stopwatch
        Show-StopwatchSummary
        Get-Stopwatch
    #>


    [CmdletBinding()]
    [OutputType([void], [PSCustomObject])]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter()]
        [switch]$ShowElapsed,

        [Parameter()]
        [switch]$Quiet,

        [Parameter()]
        [switch]$PassThru
    )

    process {
        # Initialize results dictionary if needed
        if (-not $Global:OrionStopwatchResults) {
            $Global:OrionStopwatchResults = @{}
        }

        # Check if the stopwatch was started
        if (-not $Global:OrionStopwatches -or -not $Global:OrionStopwatches.ContainsKey($Name)) {
            if (-not $Quiet) {
                Write-Warning "Stopwatch '$Name' was not started. Use Start-Stopwatch first."
            }
            return
        }

        # Calculate elapsed time
        $startTime = $Global:OrionStopwatches[$Name]
        $endTime = [DateTime]::Now
        $duration = $endTime - $startTime

        # Store the result
        $Global:OrionStopwatchResults[$Name] = [PSCustomObject]@{
            Name         = $Name
            StartTime    = $startTime
            EndTime      = $endTime
            Duration     = $duration
            TotalSeconds = $duration.TotalSeconds
        }

        # Determine if we should display the elapsed time
        $shouldShow = $false
        if (-not $Quiet) {
            $shouldShow = $ShowElapsed -or ($Global:ShowStopwatchEnd -eq $true)
        }

        if ($shouldShow) {
            # Use Format-TimeSpan if available, otherwise format manually
            $formattedTime = if (Get-Command -Name 'Format-TimeSpan' -ErrorAction SilentlyContinue) {
                Format-TimeSpan -TimeSpan $duration
            }
            else {
                # Fallback formatting
                $totalSeconds = $duration.TotalSeconds
                if ($totalSeconds -lt 60) {
                    "$([math]::Round($totalSeconds, 0)) sec"
                }
                else {
                    $minutes = [int]($totalSeconds / 60)
                    $seconds = [int]($totalSeconds % 60)
                    "$minutes min $seconds sec"
                }
            }

            Write-Host ""
            Write-Host " ✓ " -ForegroundColor Green -NoNewline
            Write-Host "$Name" -ForegroundColor White -NoNewline
            Write-Host " completed in " -ForegroundColor DarkGray -NoNewline
            Write-Host "$formattedTime" -ForegroundColor Yellow
        }

        # Clean up the running stopwatch
        $Global:OrionStopwatches.Remove($Name)

        if ($PassThru) {
            return $Global:OrionStopwatchResults[$Name]
        }
    }
}