Functions/GenXdev.Coding.PowerShell.Modules/Start-NextRefactor.ps1

################################################################################
<#
.SYNOPSIS
Continues or restarts a code refactoring session.
 
.DESCRIPTION
Manages code refactoring operations by processing refactor definitions in
priority order. Handles file selection, progress tracking, error handling, and
provides interactive user control over the refactoring process.
 
.PARAMETER Name
Name pattern(s) of refactors to process. Accepts wildcards. Default is "*".
 
.PARAMETER FilesToAdd
Files to include in the refactoring process.
 
.PARAMETER FilesToRemove
Files to exclude from the refactoring process.
 
.PARAMETER CleanUpDeletedFiles
Remove files that no longer exist from the refactor set.
 
.PARAMETER Reset
Restart processing from the beginning of the refactor set.
 
.PARAMETER ResetLMSelections
Restart all LLM selections in the refactoring process.
 
.PARAMETER MarkAllCompleted
Marks all files in the refactor set as completed.
 
.PARAMETER RedoLast
Repeat the last refactoring operation.
 
.PARAMETER EditPrompt
Only modify the AI prompt for the refactoring.
 
.PARAMETER Speak
Enables text-to-speech for refactoring progress and notifications.
 
.EXAMPLE
Start-NextRefactor -Name "RefactorProject" -Reset -CleanUpDeletedFiles
Restarts refactoring for "RefactorProject" and removes deleted files.
 
.EXAMPLE
nextrefactor -Name "*Test*" -Speak
Processes all refactor sets matching "*Test*" pattern with speech enabled.
#>

function Start-NextRefactor {

    [CmdletBinding(SupportsShouldProcess)]
    [Alias('nextrefactor')]

    param (
        #######################################################################
        [Parameter(
            Mandatory = $false,
            Position = 0,
            HelpMessage = 'The name of the refactor, accepts wildcards',
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [SupportsWildcards()]
        [string[]] $Name = @('*'),
        #######################################################################
        [Parameter(
            Mandatory = $false,
            Position = 1,
            HelpMessage = 'Filenames to add'
        )]
        [ValidateNotNull()]
        [System.IO.FileInfo[]] $FilesToAdd = @(),
        #######################################################################
        [Parameter(
            Mandatory = $false,
            Position = 2,
            HelpMessage = 'Filenames to remove'
        )]
        [ValidateNotNull()]
        [System.IO.FileInfo[]] $FilesToRemove = @(),
        #######################################################################
        [Parameter(
            Mandatory = $false,
            Position = 3,
            HelpMessage = 'Clean up deleted files'
        )]
        [switch] $CleanUpDeletedFiles,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Start from the beginning of the refactor set'
        )]
        [switch] $Reset,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Restart all LLM selections'
        )]
        [switch] $ResetLMSelections,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Mark all files as refactored'
        )]
        [switch] $MarkAllCompleted,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Redo the last refactor'
        )]
        [switch] $RedoLast,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Switch to only edit the AI prompt'
        )]
        [switch] $EditPrompt,
        #######################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Speak out the details of next refactor'
        )]
        [switch] $Speak
        #######################################################################
    )

    begin {

        # output detailed module filter pattern for troubleshooting
        Microsoft.PowerShell.Utility\Write-Verbose (
            "Starting refactoring operation for patterns: $($Name -join ', ')"
        )

        # load and sort refactor definitions by priority first
        [GenXdev.Helpers.RefactorDefinition[]] $refactorSet = GenXdev.Coding\Get-Refactor `
            -Name $Name |
            Microsoft.PowerShell.Utility\Sort-Object -Property Priority -Descending

        # exit if no matching refactors found
        if ($null -eq $refactorSet) {

            Microsoft.PowerShell.Utility\Write-Warning (
                "No refactor set found matching patterns: $($Name -join ', ')"
            )
            return
        }

        # pass the loaded refactor objects directly and only perform auto selections
        $null = GenXdev.Coding\Update-Refactor `
            -Refactor $refactorSet `
            -PerformAutoSelections `
            -RedoLast:$RedoLast `
            -Reset:$Reset `
            -MarkAllCompleted:$MarkAllCompleted `
            -CleanUpDeletedFiles:$CleanUpDeletedFiles `
            -FilesToRemove $FilesToRemove `
            -ResetLMSelections:$ResetLMSelections `
            -Verbose:$Verbose
    }


    process {

        # process each refactor definition in priority order
        foreach ($refactorDefinition in $refactorSet) {

            if ($PSCmdlet.ShouldProcess(
                    "Refactor set '$($refactorDefinition.Name)'",
                    'Process refactoring')) {

                Microsoft.PowerShell.Utility\Write-Verbose (
                    "Processing refactor: $($refactorDefinition.Name)"
                )

                try {
                    # update configuration with new files and process settings
                    $null = GenXdev.Coding\Update-Refactor `
                        -Refactor @($refactorDefinition) `
                        -Verbose:$Verbose
                }
                catch {
                    Microsoft.PowerShell.Utility\Write-Warning (
                        "Failed to update refactor set: $_"
                    )
                }

                # main refactoring loop - process files one at a time
                while ($refactorDefinition.State.Selected.Count -gt 0) {

                    # reset status to indicate active refactoring when items are available
                    if ($refactorDefinition.State.Status -eq 'Refactored') {
                        $refactorDefinition.State.Status = 'Refactoring'
                    }

                    # determine next file to process
                    if ($refactorDefinition.State.Selected.Count -gt 0) {
                        # get next file from selection queue
                        $next = $refactorDefinition.State.Selected[0]
                        $null = $refactorDefinition.State.Selected.RemoveAt(0)

                        # update selection tracking index after removing item
                        $refactorDefinition.State.SelectedIndex = [Math]::Max(
                            -1,
                            $refactorDefinition.State.SelectedIndex - 1
                        )

                        # add to refactored list immediately to track progress
                        $null = $refactorDefinition.State.Refactored.Add($next)
                        $refactorDefinition.State.RefactoredIndex =
                            $refactorDefinition.State.Refactored.Count - 1
                    }
                    else {
                        # process unprocessed file from refactored list
                        $nextIndex = $refactorDefinition.State.RefactoredIndex + 1
                        $next = $refactorDefinition.State.Refactored[$nextIndex]

                        Microsoft.PowerShell.Utility\Write-Verbose (
                            "Processing unprocessed file at index $nextIndex`: $next"
                        )

                        # check if file still exists
                        if (-not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $next -PathType Leaf)) {
                            Microsoft.PowerShell.Utility\Write-Verbose (
                                "File no longer exists, advancing RefactoredIndex: $next"
                            )
                            $refactorDefinition.State.RefactoredIndex = $nextIndex
                            continue
                        }

                        # advance the index for this file
                        $refactorDefinition.State.RefactoredIndex = $nextIndex
                    }

                    # process current file
                    $refactorDefinition.State.Status = 'Refactoring'
                    $fileName = GenXdev.FileSystem\Find-Item $next -NoRecurse -PassThru -ErrorAction SilentlyContinue |
                        Microsoft.PowerShell.Utility\Select-Object -ExpandProperty Name
                    $infoText = (
                        "Refactoring file '$fileName' of set " +
                        "'$($refactorDefinition.Name)' using prompt " +
                        "'$($refactorDefinition.RefactorSettings.PromptKey)'"
                    )

                    Microsoft.PowerShell.Utility\Write-Host `
                        -ForegroundColor Blue $infoText

                    if ($Speak) {

                        GenXdev.Console\Start-TextToSpeech $infoText
                    }

                    $continueProcessing = $true
                    while ($continueProcessing) {

                        try {
                            # perform refactoring on current file
                            GenXdev.Coding\Assert-RefactorFile `
                                -RefactorSettings $refactorDefinition.RefactorSettings `
                                -Path $next `
                                -EditPrompt:$EditPrompt

                            if ($EditPrompt) {

                                return
                            }

                            # refactoring succeeded, show progress
                            $infoText = (
                                "Refactoring set named $($refactorDefinition.Name) " +
                                "now $($refactorDefinition.State.PercentageComplete)% " +
                                "completed"
                            )

                            GenXdev.Coding\Get-Refactor -Name:$Name

                            Microsoft.PowerShell.Utility\Write-Host `
                                -ForegroundColor Green $infoText

                            if ($Speak) {

                                GenXdev.Console\Start-TextToSpeech $infoText
                            }

                            if ($Speak) {

                                GenXdev.Console\Start-TextToSpeech 'What to do next?'
                            }

                            # get user input for next action after successful refactor
                            $userAnswer = $host.ui.PromptForChoice(
                                'Make a choice',
                                'What to do next?',
                                @('&Continue', '&Redo', '&Stop'),
                                0
                            )

                            switch ($userAnswer) {
                                0 {
                                    # continue to next file
                                    $continueProcessing = $false
                                    break
                                }
                                1 {
                                    # redo current file - keep in while loop
                                    if ($Speak) {

                                        GenXdev.Console\Start-TextToSpeech `
                                            'Redoing current file'
                                    }
                                    break
                                }
                                2 {
                                    $refactorDefinition.State.Status = 'Stopped'
                                    return
                                }
                            }
                        }
                        catch {
                            if ($Speak) {

                                GenXdev.Console\Start-TextToSpeech (
                                    'An error occurred with message: ' +
                                    $_.Exception.Message
                                )
                            }
                            # log error details and timestamp
                            $now = Microsoft.PowerShell.Utility\Get-Date
                            $expandedPath = GenXdev.FileSystem\Expand-Path $next
                            $null = $refactorDefinition.Log.Add(@{
                                    Timestamp = $now
                                    Message   = (
                                        "Error refactoring file $expandedPath`: " +
                                        "$($_.Exception.Message)"
                                    )
                                })

                            Microsoft.PowerShell.Utility\Write-Error `
                                $_.Exception.Message
                            $refactorDefinition.State.Status = 'Error'

                            if ($Speak) {

                                GenXdev.Console\Start-TextToSpeech `
                                    'What to do next?'
                            }

                            # handle error with user input
                            $userAnswer = $host.ui.PromptForChoice(
                                'Make a choice',
                                'What to do next?',
                                @('&Continue', '&Redo', '&Stop'),
                                0
                            )

                            switch ($userAnswer) {
                                0 {
                                    # continue to next file despite error
                                    $refactorDefinition.State.Status = 'Refactoring'
                                    $continueProcessing = $false
                                    break
                                }
                                1 {
                                    # redo current file - keep in while loop
                                    $refactorDefinition.State.Status = 'Refactoring'
                                    break
                                }
                                2 {
                                    $refactorDefinition.State.Status = 'Stopped'
                                    throw 'Refactor stopped'
                                    return
                                }
                            }
                        }
                    }

                    try {
                        # save current progress after processing file
                        $null = GenXdev.Coding\Update-Refactor `
                            -Refactor @($refactorDefinition) `
                        -Verbose:$Verbose
                    }
                    catch {
                        Microsoft.PowerShell.Utility\Write-Warning (
                            "Failed to update refactor state: $_"
                        )
                    }
                }

                # all files processed successfully
                if ($Speak) {

                    GenXdev.Console\Start-TextToSpeech (
                        "Completed refactoring set: " +
                        "'$($refactorDefinition.Name)'"
                    )
                }

                Microsoft.PowerShell.Utility\Write-Verbose (
                    "Completed refactoring $($refactorDefinition.Name)"
                )
                $refactorDefinition.State.Status = 'Refactored'

                try {
                    # save final state
                    $null = GenXdev.Coding\Update-Refactor `
                        -Refactor @($refactorDefinition) `
                        -Verbose:$Verbose
                }
                catch {
                    Microsoft.PowerShell.Utility\Write-Warning (
                        "Failed to update refactor state: $_"
                    )
                }
            }
        }

        Microsoft.PowerShell.Utility\Write-Host -ForegroundColor Green 'All done.'

        if ($Speak) {

            GenXdev.Console\Start-TextToSpeech 'All refactorings completed'
        }
    }

    end {

    }
}
################################################################################