scripts/setup-strangeloop.ps1

#Requires -Version 7.0

<#
.SYNOPSIS
    strangeloop CLI Setup Script v1.0.0

.DESCRIPTION
    A comprehensive setup script with advanced phase targeting, environment detection, and project initialization capabilities.
    Features granular tool modules, environment-specific setup, and a 10-phase execution model.

.PARAMETER loop-name
    The name of the loop to set up (optional)

.PARAMETER project-name
    The name of the project to create (optional)

.PARAMETER project-path
    The parent directory path where the project folder will be created (optional)

.PARAMETER from-phase
    Start execution from this phase and continue through all subsequent phases
    Valid values: prerequisites, authentication, discovery, environment, wsl, project, git, pipelines, vscode, completion

.PARAMETER only-phase
    Execute only this specific phase (skips all others)
    Valid values: prerequisites, authentication, discovery, environment, wsl, project, git, pipelines, vscode, completion

.PARAMETER skip-phases
    Array of phases to skip during execution
    Valid values: prerequisites, authentication, discovery, environment, wsl, project, git, pipelines, vscode, completion

.PARAMETER list-phases
    Display available phases and their descriptions

.PARAMETER what-if
    Preview what actions would be performed without making any actual changes

.PARAMETER Verbose
    Enable verbose output with detailed explanations and additional information

.EXAMPLE
    .\setup-strangeloop.ps1
    Run the complete setup process with all phases

.EXAMPLE
    .\setup-strangeloop.ps1 -loop-name "Test-api" -project-name "MyApp"
    Run setup with specific loop and project names

.EXAMPLE
    .\setup-strangeloop.ps1 -only-phase pipelines -project-name "MyApp" -project-path "/parent/directory"
    Run only the pipelines phase with project created in /parent/directory/MyApp

.EXAMPLE
    .\setup-strangeloop.ps1 -from-phase environment
    Start from environment phase and run all subsequent phases

.EXAMPLE
    .\setup-strangeloop.ps1 -skip-phases authentication,wsl
    Run all phases except authentication and WSL setup

.EXAMPLE
    .\setup-strangeloop.ps1 -what-if
    Preview what actions would be performed without making any changes

.EXAMPLE
    .\setup-strangeloop.ps1 -Verbose
    Run with detailed logging and explanations
#>


[CmdletBinding()]
param(
    [string]${loop-name},
    [string]${project-name},
    [string]${project-path},
    [ValidateSet("prerequisites", "authentication", "discovery", "environment", "wsl", "project", "git", "pipelines", "vscode", "completion")]
    [string]${from-phase},
    [ValidateSet("prerequisites", "authentication", "discovery", "environment", "wsl", "project", "git", "pipelines", "vscode", "completion")]
    [string]${only-phase},
    [ValidateSet("prerequisites", "authentication", "discovery", "environment", "wsl", "project", "git", "pipelines", "vscode", "completion")]
    [string[]]${skip-phases},
    [switch]${list-phases},
    [switch]${what-if},
    [switch]$Help
)

# Set strict mode and error handling
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

# Script metadata
$ScriptVersion = "1.0.0"

# Import shared utilities by dot-sourcing
try {
    . (Join-Path $PSScriptRoot "modules\shared\write-functions.ps1")
    . (Join-Path $PSScriptRoot "modules\shared\test-functions.ps1") 
    . (Join-Path $PSScriptRoot "modules\shared\loop-functions.ps1")
    . (Join-Path $PSScriptRoot "modules\shared\phase-functions.ps1")
    . (Join-Path $PSScriptRoot "modules\shared\validation-functions.ps1")
    . (Join-Path $PSScriptRoot "modules\shared\display-functions.ps1")
} catch {
    Write-Error "Failed to import shared modules: $($_.Exception.Message)"
    exit 1
}

# Phase execution functions
# Individual phase functions

# Local Invoke-Phase function compatible with existing calls
function Invoke-Phase {
    param(
        [string]$PhaseName,
        [string]$ScriptPath,
        [hashtable]$Parameters = @{}
    )
    
    # Add what-if parameter if it was specified and the child script supports it
    if (${what-if}) {
        $Parameters['what-if'] = $true
        Write-Host "🔍 (what-if) Executing Phase: $PhaseName" -ForegroundColor Yellow
    }
    
    try {
        $fullScriptPath = Join-Path $PSScriptRoot $ScriptPath
        if (-not (Test-Path $fullScriptPath)) {
            throw "Phase script not found: $fullScriptPath"
        }
        
        if (${what-if}) {
            Write-Host "🔍 (what-if) Would execute: $fullScriptPath" -ForegroundColor Yellow
            # Check if the script supports what-if parameter
            $scriptContent = Get-Content $fullScriptPath -Raw
            if ($scriptContent -match '\$\{what-if\}') {
                Write-Host "🔍 (what-if) Script supports what-if - passing parameter" -ForegroundColor Yellow
            } else {
                Write-Host "⚠️ (what-if) Script does not support what-if - would run normally" -ForegroundColor Yellow
                # For scripts that don't support what-if, we still try to call them but they'll ignore the parameter
            }
        }
        
        $result = & $fullScriptPath @Parameters
        return $result
    } catch {
        if (${what-if}) {
            Write-Host "❌ (what-if) Phase '$PhaseName' would fail: $($_.Exception.Message)" -ForegroundColor Red
        } else {
            Write-Error "Phase '$PhaseName' failed: $($_.Exception.Message)"
            throw
        }
    }
}
function Invoke-Prerequisites {
    param()
    
    Write-Host "📋 Phase 1: Prerequisites" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    $result = Invoke-Phase "Prerequisites" "modules\prerequisites\setup-prerequisites.ps1"
    Write-Host ""
    return $result
}

function Invoke-Authentication {
    param()
    
    Write-Host "🔐 Phase 2: Authentication" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    $result = Invoke-Phase "Authentication" "modules\authentication\setup-authentication.ps1"
    Write-Host ""
    return $result
}

function Invoke-Discovery {
    param(
        [string]$LoopName
    )
    
    Write-Host "🔍 Phase 3: Discovery" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    $discoveryResults = $null
    
    # If loop name is provided, try to validate it first
    if ($LoopName) {
        Write-Host "📋 Validating provided loop: $LoopName" -ForegroundColor Yellow
        $discoveryResults = Test-LoopAndGetRequirements -LoopName $LoopName
        
        if ($discoveryResults) {
            # Loop is valid, skip discovery phase
            Write-Success "✓ Loop validation successful - Discovery phase skipped"
        } else {
            # Loop is invalid - fail immediately when loop name was explicitly provided
            Write-Error "Invalid loop name: '$LoopName'. Use -list-phases to see available loops or run without -loop-name for interactive selection."
            return @{ Success = $false; Phase = "Discovery"; Error = "Invalid loop name provided: $LoopName" }
        }
    } else {
        # No loop name provided, run full discovery
        $discoveryResults = Invoke-Phase "Discovery" "modules\discovery\setup-discovery.ps1" @{}
        
        if ($discoveryResults -and $discoveryResults.Success) {
            Write-Success "Discovery completed successfully"
        } else {
            throw "Discovery phase failed"
        }
    }
    
    Write-Host ""
    return $discoveryResults
}

function Invoke-Environment {
    param(
        [string]$LoopName,
        [hashtable]$DiscoveryResults
    )
    
    Write-Host "🏗️ Phase 4: Environment Setup" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    $envParams = @{}
    if ($LoopName) { $envParams['loop-name'] = $LoopName }
    
    # Pass discovery results to environment setup
    if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements) {
        $envParams['requirements'] = $DiscoveryResults.EnvironmentRequirements
    }
    
    $result = Invoke-Phase "Environment" "modules\environment\setup-environment.ps1" $envParams
    Write-Host ""
    return $result
}

function Invoke-WSLSetup {
    param(
        [hashtable]$DiscoveryResults
    )
    
    $requiresWSL = $false
    if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements.RequiresWSL) {
        $requiresWSL = $true
    }
    
    if ($requiresWSL) {
        Write-Host "🐧 Phase 4.5: WSL Setup" -ForegroundColor Cyan
        Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
        $wslParams = @{}
        $result = Invoke-Phase "WSL Setup" "modules\wsl\initialize-wsl.ps1" $wslParams
        Write-Host ""
        return $result
    } else {
        Write-Host "🐧 Phase 4.5: WSL Setup" -ForegroundColor Cyan
        Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
        Write-Host "ℹ WSL setup skipped - selected loop runs on Windows" -ForegroundColor Blue
        Write-Host ""
        return @{ Success = $true; Skipped = $true; Reason = "Not required for Windows loops" }
    }
}

function Invoke-ProjectSetup {
    param(
        [string]$LoopName,
        [string]$ProjectName,
        [string]$ProjectPath,
        [hashtable]$DiscoveryResults,
        [string]$BaseDirectory
    )
    
    Write-Host "🚀 Phase 5: Project Creation and Setup" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    $projectParams = @{}
    if ($LoopName) { 
        $projectParams['loop-name'] = $LoopName 
    } elseif ($DiscoveryResults -and $DiscoveryResults.SelectedLoop) {
        $projectParams['loop-name'] = $DiscoveryResults.SelectedLoop
    }
    if ($ProjectName) { $projectParams['project-name'] = $ProjectName }
    if ($ProjectPath) { $projectParams['project-path'] = $ProjectPath }
    
    # Validate path compatibility with loop requirements
    if ($ProjectPath -and $DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements) {
        $isWindowsPath = $ProjectPath -match '^[A-Za-z]:\\'
        $isWSLPath = $ProjectPath.StartsWith('/') -or $ProjectPath.Contains('/home/')
        $requiresWSL = $DiscoveryResults.EnvironmentRequirements.RequiresWSL
        
        if ($requiresWSL -and $isWindowsPath) {
            Write-Error "❌ Path format mismatch: WSL loop '$LoopName' requires a WSL path (e.g., /home/user/...), but Windows path provided: '$ProjectPath'"
            Write-Host "Please use a WSL path format like: /home/$env:USERNAME/AdsSnR_Containers/services" -ForegroundColor Yellow
            exit 1
        } elseif (-not $requiresWSL -and $isWSLPath) {
            Write-Error "❌ Path format mismatch: Windows loop '$LoopName' requires a Windows path (e.g., Q:\src\...), but WSL path provided: '$ProjectPath'"
            Write-Host "Please use a Windows path format like: Q:\src\AdsSnR_Containers\services" -ForegroundColor Yellow
            exit 1
        }
    }
    
    # Pass platform information for proper project creation
    if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements) {
        $projectParams['platform'] = $DiscoveryResults.EnvironmentRequirements.Platform
        $projectParams['requires-wsl'] = $DiscoveryResults.EnvironmentRequirements.RequiresWSL
    }
    # Pass the original bootstrap directory as an absolute path for consistent path suggestions
    if ($BaseDirectory) { $projectParams['base-directory'] = $BaseDirectory }
    
    $result = Invoke-Phase "Project Creation and Setup" "modules\project\initialize-project.ps1" $projectParams
    Write-Host ""
    return $result
}

function Invoke-GitSetup {
    param(
        [string]$LoopName,
        [string]$ProjectName,
        [string]$ProjectPath,
        [hashtable]$DiscoveryResults,
        [hashtable]$ProjectResults
    )
    
    Write-Host "📚 Phase 5.5: Git Source Control Setup" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    # Check if Git phase should be skipped based on project initialization results
    if ($ProjectResults -and $ProjectResults.ContainsKey('PhaseSkips') -and $ProjectResults.PhaseSkips -and $ProjectResults.PhaseSkips.Git) {
        Write-Info "⏭️ Skipping Git Source Control Setup - User chose to skip git integration"
        Write-Host ""
        return @{ Success = $true; Skipped = $true; Reason = "User choice - no source control" }
    }
    
    # Running in isolation mode if we have required parameters AND the project phase was not actually run
    $runningInIsolationMode = ($ProjectPath -and $ProjectName -and $LoopName) -and 
                            (-not $ProjectResults -or ($ProjectResults -is [hashtable] -and $ProjectResults.ContainsKey('Skipped') -and $ProjectResults.Skipped -eq $true))
    
    if ((-not $ProjectResults -or ($ProjectResults -is [hashtable] -and -not $ProjectResults.Success)) -and -not $runningInIsolationMode) {
        Write-Warning "⏭️ Skipping Git Source Control Setup - Project creation failed"
        Write-Info "Git repository setup requires a successfully created project"
        Write-Host ""
        return @{ Success = $false; Skipped = $true; Reason = "Project creation failed" }
    }
    
    $gitParams = @{}
    
    # Get project details from the project creation results
    if ($ProjectResults -and $ProjectResults.Success -and 
        $ProjectResults.ContainsKey('ProjectPath')) {
        $gitParams['project-path'] = $ProjectResults.ProjectPath
        $gitParams['project-name'] = $ProjectResults.ProjectName
        $gitParams['loop-name'] = $ProjectResults.LoopName
        
        # Pass GitContext information if available
        if ($ProjectResults.ContainsKey('GitContext')) {
            $gitParams['git-context'] = $ProjectResults.GitContext
        }
        
        # Set platform and WSL requirements based on discovery results
        if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements) {
            $gitParams['platform'] = $DiscoveryResults.EnvironmentRequirements.Platform
            $gitParams['requires-wsl'] = $DiscoveryResults.EnvironmentRequirements.RequiresWSL
        }
    } elseif ($runningInIsolationMode) {
        # Isolation mode: use provided parameters directly
        # Note: project-path is now parent directory, so construct full path
        if ($ProjectPath -and $ProjectName) {
            if ($ProjectPath.StartsWith("/") -or $ProjectPath.Contains("/home/")) {
                # WSL path - use forward slash
                $fullProjectPath = "$ProjectPath/$ProjectName"
            } else {
                # Windows path - use Join-Path
                $fullProjectPath = Join-Path $ProjectPath $ProjectName
            }
            
            $gitParams['project-path'] = $fullProjectPath
            $gitParams['project-name'] = $ProjectName
            $gitParams['loop-name'] = $LoopName
            # Default platform to Windows since we don't have discovery results
            $gitParams['platform'] = "Windows"
            $gitParams['requires-wsl'] = $false
        }
    } else {
        # Isolation mode: use command line parameters directly
        if ($ProjectPath -and $ProjectName -and $LoopName) {
            # Note: project-path is now parent directory, so construct full path
            if ($ProjectPath.StartsWith("/") -or $ProjectPath.Contains("/home/")) {
                # WSL path - use forward slash
                $fullProjectPath = "$ProjectPath/$ProjectName"
            } else {
                # Windows path - use Join-Path
                $fullProjectPath = Join-Path $ProjectPath $ProjectName
            }
            
            $gitParams['project-path'] = $fullProjectPath
            $gitParams['project-name'] = $ProjectName
            $gitParams['loop-name'] = $LoopName
            
            # Determine platform based on loop name for isolation mode
            $windowsOnlyLoops = @('asp-dotnet-framework-api', 'ads-snr-basic', 'flask-windows')
            if ($LoopName -in $windowsOnlyLoops) {
                $gitParams['platform'] = 'Windows'
                $gitParams['requires-wsl'] = $false
            } else {
                $gitParams['platform'] = 'WSL'
                $gitParams['requires-wsl'] = $true
            }
            
            Write-Info "Running Git phase in isolation mode with provided parameters"
        } else {
            Write-Warning "Isolation mode requires -project-path, -project-name, and -loop-name parameters"
        }
    }
    
    if ($gitParams.ContainsKey('project-path')) {
        $result = Invoke-Phase "Git Source Control Setup" "modules\git\setup-git-source-control.ps1" $gitParams
        Write-Host ""
        return $result
    } else {
        Write-Warning "No project path available for Git setup"
        Write-Host ""
        return @{ Success = $false; Skipped = $true; Reason = "No project path available" }
    }
}

function Invoke-PipelineSetup {
    param(
        [hashtable]$ProjectResults,
        [hashtable]$GitResults,
        [hashtable]$DiscoveryResults,
        [string]$ProjectName,
        [switch]$BypassDependencyChecks
    )
    
    Write-Host "🚀 Phase 6: Pipeline Setup" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    # Check if Pipeline phase should be skipped based on project initialization results
    if ($ProjectResults -and $ProjectResults.ContainsKey('PhaseSkips') -and $ProjectResults.PhaseSkips -and $ProjectResults.PhaseSkips.Pipeline) {
        Write-Info "⏭️ Skipping Pipeline Setup - User chose to skip source control/pipelines"
        Write-Host ""
        return @{ Success = $true; Skipped = $true; Reason = "User choice - no source control" }
    }
    
    # Skip dependency checks when running as target phase
    if (-not $BypassDependencyChecks) {
        # Check if project creation was successful
        if (-not $ProjectResults -or ($ProjectResults -is [hashtable] -and -not $ProjectResults.Success)) {
            Write-Warning "⏭️ Skipping Pipeline Setup - Project creation failed"
            Write-Info "Pipeline setup requires a successfully created project"
            Write-Host ""
            return @{ Success = $false; Skipped = $true; Reason = "Project creation failed" }
        }
        
        # Check if Git remote was configured
        $hasRemoteRepo = $false
        
        if ($GitResults -and $GitResults.Success -and -not ($GitResults.ContainsKey('Skipped') -and $GitResults.Skipped)) {
            # Git setup was completed successfully, check if remote was configured
            $hasRemoteRepo = $GitResults.RemoteConfigured -eq $true
        }
        
        if (-not $hasRemoteRepo) {
            if ($GitResults -and $GitResults.ContainsKey('Skipped') -and $GitResults.Skipped) {
                Write-Warning "⏭️ Skipping Pipeline Setup - Git setup was skipped"
                Write-Info "Azure DevOps pipelines require Git source control to be set up with a remote repository."
                Write-Info "To set up pipelines later:"
                Write-Info " 1. Run Git setup: .\modules\git\setup-git-source-control.ps1"
                Write-Info " 2. Configure a remote repository during Git setup"
                Write-Info " 3. Run the pipeline setup: .\modules\pipelines\setup-pipelines-1es.ps1"
            } else {
                Write-Warning "⏭️ Skipping Pipeline Setup - No remote Git repository configured"
                Write-Info "Azure DevOps pipelines require a remote Git repository to be configured."
                Write-Info "To set up pipelines later:"
                Write-Info " 1. Configure a remote repository: git remote add origin <repository-url>"
                Write-Info " 2. Push your code: git push -u origin <branch-name>"
                Write-Info " 3. Run the pipeline setup script: .\modules\pipelines\setup-pipelines-1es.ps1"
            }
            Write-Host ""
            return @{ Success = $true; Skipped = $true; Reason = "No remote repository configured" }
        }
    } else {
        Write-Info "Running pipeline setup independently - dependency checks bypassed"
    }
    
    # Ask user if they want to set up pipelines
    Write-Host ""
    Write-Host "🚀 Azure DevOps Pipeline Setup" -ForegroundColor Yellow
    Write-Host "This will create Azure DevOps pipelines for your project in the organized folder structure." -ForegroundColor Gray
    Write-Host "You will be prompted to choose the base location for your pipelines." -ForegroundColor Gray
    Write-Host ""
    $setupPipelines = Read-UserPrompt -Prompt "Would you like to set up Azure DevOps pipelines?" -ValidValues @("y","n")
    
    if (Test-YesResponse $setupPipelines) {
        $pipelineParams = @{}
        
        # Get project details from the project creation results
        if ($ProjectResults -and $ProjectResults.Success -and 
            $ProjectResults.ContainsKey('ProjectPath') -and $ProjectResults.ProjectPath) {
            $pipelineParams['project-path'] = $ProjectResults.ProjectPath
            $pipelineParams['project-name'] = $ProjectResults.ProjectName
            
            # Set WSL requirements based on discovery results
            if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements -and $DiscoveryResults.EnvironmentRequirements.RequiresWSL) {
                $pipelineParams['requires-wsl'] = $true
            }
        } elseif ($BypassDependencyChecks -and $ProjectName) {
            # When bypassing dependency checks, use provided project path or prompt
            Write-Host ""
            Write-Host "Pipeline Setup - Independent Mode" -ForegroundColor Yellow
            Write-Host "Since dependency phases were skipped, using provided project details:" -ForegroundColor Gray
            Write-Host ""
            
            $projectPath = ${project-path}
            if (-not $projectPath) {
                $projectPath = Read-UserPrompt -Prompt "Project path (absolute path to your project directory)"
                if (-not $projectPath) {
                    Write-Error "Project path is required for pipeline setup"
                    return @{ Success = $false; Skipped = $true; Reason = "No project path provided" }
                }
            }
            
            Write-Info "Using project path: $projectPath"
            $pipelineParams['project-path'] = $projectPath
            $pipelineParams['project-name'] = $ProjectName
            
            # Auto-detect WSL requirements from path or ask
            if ($projectPath.StartsWith('/') -or $projectPath.Contains('/home/')) {
                Write-Info "Auto-detected WSL requirement from path format"
                $pipelineParams['requires-wsl'] = $true
            } else {
                $useWSL = Read-UserPrompt -Prompt "Does this project require WSL?" -ValidValues @("y","n")
                if (Test-YesResponse $useWSL) {
                    $pipelineParams['requires-wsl'] = $true
                }
            }
        } elseif ($DiscoveryResults -and $DiscoveryResults.SelectedLoop) {
            # Fallback: reconstruct project details if project creation results not available
            Write-Warning "Project path not available from project results, using fallback path construction"
            $appName = if ($ProjectName) { $ProjectName } else { "Test-$($DiscoveryResults.SelectedLoop)-app" }
            if ($DiscoveryResults.EnvironmentRequirements.RequiresWSL) {
                try {
                    $wslUser = & wsl -- whoami 2>$null
                    if ($wslUser) {
                        $pipelineParams['project-path'] = "/home/$($wslUser.Trim())/AdsSnR_Containers/services/$appName"
                    } else {
                        $pipelineParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
                    }
                } catch {
                    $pipelineParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
                }
                $pipelineParams['requires-wsl'] = $true
            } else {
                $pipelineParams['project-path'] = "Q:\src\AdsSnR_Containers\services\$appName"
            }
            $pipelineParams['project-name'] = $appName
        }
        
        # Add verbose flag if specified
        if ($VerbosePreference -eq 'Continue') {
            $pipelineParams['VerboseLogging'] = $true
        }
        
        if ($pipelineParams.ContainsKey('project-path')) {
            $result = Invoke-Phase "Pipeline Setup" "modules\pipelines\setup-pipelines-1es.ps1" $pipelineParams
            Write-Host ""
            return $result
        } else {
            Write-Warning "No project path available for Pipeline setup"
            Write-Host ""
            return @{ Success = $false; Skipped = $true; Reason = "No project path available" }
        }
    } else {
        Write-Info "⏭️ Pipeline setup skipped by user choice"
        Write-Host ""
        return @{ Success = $true; Skipped = $true; Reason = "User choice" }
    }
}

function Invoke-VSCodeSetup {
    param(
        [string]$LoopName,
        [string]$ProjectPath,
        [hashtable]$ProjectResults,
        [hashtable]$DiscoveryResults,
        [string]$ProjectName
    )
    
    Write-Host "💻 Phase 8: VS Code Integration" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    # Check if project creation was successful
    if ((-not $ProjectResults) -or ($ProjectResults -is [hashtable] -and -not $ProjectResults.Success)) {
        Write-Warning "⏭️ Skipping VS Code Integration - Project creation failed"
        Write-Info "VS Code integration requires a successfully created project"
        Write-Host ""
        return @{ Success = $false; Skipped = $true; Reason = "Project creation failed" }
    }
    
    $vscodeParams = @{}
    
    # First priority: Use directly provided parameters (for targeted execution)
    if ($ProjectPath) {
        $vscodeParams['project-path'] = $ProjectPath
    }
    if ($ProjectName) {
        $vscodeParams['project-name'] = $ProjectName
    }
    if ($LoopName) {
        $vscodeParams['loop-name'] = $LoopName
    }
    
    # Get project path from the project creation results if not provided directly
    if ($ProjectResults -and -not $vscodeParams.ContainsKey('project-path')) {
        
        # Handle different return types
        if ($ProjectResults -is [hashtable] -and $ProjectResults.ContainsKey('Success') -and $ProjectResults.Success) {
            # Project returned object with Success property - use the actual path that was created
            if ($ProjectResults.ContainsKey('ProjectPath')) {
                $vscodeParams['project-path'] = $ProjectResults.ProjectPath
            }
            if ($ProjectResults.ContainsKey('LoopName') -and -not $vscodeParams.ContainsKey('loop-name')) {
                $vscodeParams['loop-name'] = $ProjectResults.LoopName
            }
            
            # Set platform and WSL requirements based on discovery results
            if ($DiscoveryResults -and $DiscoveryResults.EnvironmentRequirements) {
                $vscodeParams['platform'] = $DiscoveryResults.EnvironmentRequirements.Platform
                $vscodeParams['requires-wsl'] = $DiscoveryResults.EnvironmentRequirements.RequiresWSL
            }
        } elseif ($ProjectResults -and $DiscoveryResults -and $DiscoveryResults.ContainsKey('SelectedLoop') -and $DiscoveryResults.SelectedLoop) {
            # Project succeeded but returned simple value - reconstruct path
            $appName = if ($ProjectName) { $ProjectName } else { "Test-$($DiscoveryResults.SelectedLoop)-app" }
            if ($DiscoveryResults.ContainsKey('EnvironmentRequirements') -and $DiscoveryResults.EnvironmentRequirements.RequiresWSL) {
                try {
                    $wslUser = & wsl -- whoami 2>$null
                    if ($wslUser) {
                        $vscodeParams['project-path'] = "/home/$($wslUser.Trim())/AdsSnR_Containers/services/$appName"
                    } else {
                        $vscodeParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
                    }
                } catch {
                    $vscodeParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
                }
                $vscodeParams['requires-wsl'] = $true
            } else {
                $vscodeParams['project-path'] = "Q:\src\AdsSnR_Containers\services\$appName"
            }
            $vscodeParams['loop-name'] = $DiscoveryResults.SelectedLoop
            
            # Set platform and WSL requirements based on discovery results
            if ($DiscoveryResults -and $DiscoveryResults.ContainsKey('EnvironmentRequirements') -and $DiscoveryResults.EnvironmentRequirements) {
                $vscodeParams['platform'] = $DiscoveryResults.EnvironmentRequirements.Platform
                $vscodeParams['requires-wsl'] = $DiscoveryResults.EnvironmentRequirements.RequiresWSL
            }
        }
    } elseif ($DiscoveryResults -and $DiscoveryResults.ContainsKey('SelectedLoop') -and $DiscoveryResults.SelectedLoop -and -not $vscodeParams.ContainsKey('project-path')) {
        # Fallback: reconstruct project path if project creation results not available
        if ($DiscoveryResults.ContainsKey('EnvironmentRequirements') -and $DiscoveryResults.EnvironmentRequirements.RequiresWSL) {
            # For WSL projects, get the project location that was created
            $appName = if ($ProjectName) { $ProjectName } else { "Test-$($DiscoveryResults.SelectedLoop)-app" }
            try {
                $wslUser = & wsl -- whoami 2>$null
                if ($wslUser) {
                    $vscodeParams['project-path'] = "/home/$($wslUser.Trim())/AdsSnR_Containers/services/$appName"
                } else {
                    $vscodeParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
                }
            } catch {
                $vscodeParams['project-path'] = "/home/\$USER/AdsSnR_Containers/services/$appName"
            }
            $vscodeParams['requires-wsl'] = $true
        } else {
            # For Windows projects - use the standardized path
            $appName = if ($ProjectName) { $ProjectName } else { "Test-$($DiscoveryResults.SelectedLoop)-app" }
            $vscodeParams['project-path'] = "Q:\src\AdsSnR_Containers\services\$appName"
        }
        if ($DiscoveryResults.ContainsKey('SelectedLoop') -and -not $vscodeParams.ContainsKey('loop-name')) {
            $vscodeParams['loop-name'] = $DiscoveryResults.SelectedLoop
        }
        if ($DiscoveryResults.ContainsKey('EnvironmentRequirements') -and $DiscoveryResults.EnvironmentRequirements.ContainsKey('Platform')) {
            $vscodeParams['platform'] = $DiscoveryResults.EnvironmentRequirements.Platform
        }
    }
    
    # Ensure platform and WSL detection for isolated VSCode execution
    if (-not $vscodeParams.ContainsKey('platform') -and $LoopName) {
        # Determine environment requirements based on loop type (same logic as discovery module)
        $windowsOnlyLoops = @('asp-dotnet-framework-api', 'ads-snr-basic', 'flask-windows')
        $requiresWindows = $LoopName -in $windowsOnlyLoops
        $requiresWSL = -not $requiresWindows
        
        $vscodeParams['platform'] = if ($requiresWindows) { 'Windows' } else { 'WSL' }
        $vscodeParams['requires-wsl'] = $requiresWSL
    }
    
    if ($vscodeParams.ContainsKey('project-path')) {
        $result = Invoke-Phase "VS Code Integration" "modules\vscode\setup-vscode.ps1" $vscodeParams
        Write-Host ""
        return $result
    } else {
        Write-Warning "No project path available for VS Code setup"
        Write-Host ""
        return @{ Success = $false; Skipped = $true; Reason = "No project path available" }
    }
}

function Invoke-Completion {
    param(
        [hashtable]$PhaseResults,
        [datetime]$StartTime
    )
    
    Write-Host "✅ Phase 10: Completion and Summary" -ForegroundColor Cyan
    Write-Host "──────────────────────────────────────────────────────────" -ForegroundColor DarkCyan
    
    $completionParams = @{
        'phase-results' = $PhaseResults
        'start-time' = $StartTime
    }
    
    $result = Invoke-Phase "Completion and Summary" "modules\completion\setup-completion.ps1" $completionParams
    Write-Host ""
    return $result
}

# Main execution function
# Main execution function
function Start-Setup {
    $startTime = Get-Date
    $phaseResults = @{}
    $discoveryResults = $null
    
    try {
        Show-Banner -Version $ScriptVersion
        
        # Set execution policy to allow script execution
        try {
            $currentPolicy = Get-ExecutionPolicy -Scope CurrentUser
            if ($currentPolicy -eq "Restricted" -or $currentPolicy -eq "Undefined") {
                Write-Host "🔐 Setting PowerShell execution policy..." -ForegroundColor Yellow
                Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
                Write-Host "✓ PowerShell execution policy set to RemoteSigned for current user" -ForegroundColor Green
            } else {
                Write-Host "✓ PowerShell execution policy is already configured ($currentPolicy)" -ForegroundColor Green
            }
        } catch {
            Write-Warning "Could not set execution policy: $($_.Exception.Message)"
            Write-Warning "You may need to run: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser"
        }
        Write-Host ""
        
        # Phase 1: Prerequisites
        if (Test-ShouldRunPhase -PhaseName "prerequisites" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['Prerequisites'] = Invoke-Prerequisites
        } else {
            Write-Host "⏭️ Skipping Phase 1: Prerequisites (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Prerequisites'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 2: Authentication
        if (Test-ShouldRunPhase -PhaseName "authentication" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['Authentication'] = Invoke-Authentication
        } else {
            Write-Host "⏭️ Skipping Phase 2: Authentication (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Authentication'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 3: Discovery
        if (Test-ShouldRunPhase -PhaseName "discovery" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $discoveryResults = Invoke-Discovery -LoopName ${loop-name}
            $phaseResults['Discovery'] = $discoveryResults
        } else {
            Write-Host "⏭️ Skipping Phase 3: Discovery (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Discovery'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 4: Environment Setup
        if (Test-ShouldRunPhase -PhaseName "environment" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['Environment'] = Invoke-Environment -LoopName ${loop-name} -DiscoveryResults $discoveryResults
        } else {
            Write-Host "⏭️ Skipping Phase 4: Environment Setup (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Environment'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 4.5: WSL Setup (only if WSL is required by the selected loop)
        if (Test-ShouldRunPhase -PhaseName "wsl" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['WSL'] = Invoke-WSLSetup -DiscoveryResults $discoveryResults
        } else {
            Write-Host "⏭️ Skipping Phase 4.5: WSL Setup (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['WSL'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 5: Project Creation and Setup
        if (Test-ShouldRunPhase -PhaseName "project" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $projectResults = Invoke-ProjectSetup -LoopName ${loop-name} -ProjectName ${project-name} -ProjectPath ${project-path} -DiscoveryResults $discoveryResults -BaseDirectory $PSScriptRoot
            $phaseResults['Project'] = $projectResults
        } else {
            Write-Host "⏭️ Skipping Phase 5: Project Creation and Setup (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Project'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 5.5: Git Source Control Setup
        if (Test-ShouldRunPhase -PhaseName "git" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['Git'] = Invoke-GitSetup -ProjectPath ${project-path} -ProjectName ${project-name} -LoopName ${loop-name} -DiscoveryResults $discoveryResults -ProjectResults $phaseResults['Project']
        } else {
            Write-Host "⏭️ Skipping Phase 5.5: Git Source Control Setup (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Git'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 6: Pipeline Setup
        if (Test-ShouldRunPhase -PhaseName "pipelines" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            # When running pipelines as only phase, bypass dependency checks
            $isIndependentExecution = ${only-phase} -eq "pipelines"
            $phaseResults['Pipelines'] = Invoke-PipelineSetup -ProjectResults $phaseResults['Project'] -GitResults $phaseResults['Git'] -DiscoveryResults $discoveryResults -ProjectName ${project-name} -BypassDependencyChecks:$isIndependentExecution
        } else {
            Write-Host "⏭️ Skipping Phase 6: Pipeline Setup (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Pipelines'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 7: VS Code Integration
        if (Test-ShouldRunPhase -PhaseName "vscode" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['VSCode'] = Invoke-VSCodeSetup -LoopName ${loop-name} -ProjectPath ${project-path} -ProjectResults $phaseResults['Project'] -DiscoveryResults $discoveryResults -ProjectName ${project-name}
        } else {
            Write-Host "⏭️ Skipping Phase 7: VS Code Integration (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['VSCode'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
        # Phase 10: Completion and Summary
        if (Test-ShouldRunPhase -PhaseName "completion" -OnlyPhase ${only-phase} -FromPhase ${from-phase} -SkipPhases ${skip-phases}) {
            $phaseResults['Completion'] = Invoke-Completion -PhaseResults $phaseResults -StartTime $startTime
        } else {
            Write-Host "⏭️ Skipping Phase 10: Completion and Summary (not in target/excluded)" -ForegroundColor Yellow
            $phaseResults['Completion'] = @{ Success = $true; Skipped = $true; Reason = "Phase filtering" }
        }
        
    } catch {
        # Handle failure with completion phase
        try {
            $completionParams = @{
                'phase-results' = $phaseResults
                'start-time' = $startTime
                'failed' = $true
            }
            & (Join-Path $PSScriptRoot "modules\completion\setup-completion.ps1") @completionParams
        } catch {
            # If completion fails too, just show basic error
        }
        
        Write-Host ""
        Write-Host "╔═══════════════════════════════════════════════════════════════════╗" -ForegroundColor Red
        Write-Host "║ ❌ SETUP FAILED ║" -ForegroundColor Red
        Write-Host "║ ║" -ForegroundColor Red
        Write-Host "║ Error: $($_.Exception.Message.PadRight(58)) ║" -ForegroundColor Red
        Write-Host "╚═══════════════════════════════════════════════════════════════════╝" -ForegroundColor Red
        Write-Host ""
        exit 1
    }
}

# Phase listing function
# Parameter validation and help handling

# Parameter validation and help handling
if (${list-phases}) {
    Show-Phases -ShowOrder -ShowDependencies
    exit 0
}

if ($Help) {
    Show-Help -ShowExamples -ShowPhases
    exit 0
}

# Validate parameters using shared validation functions
$boundParams = if ($PSBoundParameters) { $PSBoundParameters } else { @{} }
$validationResult = Test-ParameterValidation -BoundParameters $boundParams
Show-ValidationErrors -ValidationResult $validationResult -ExitOnError

# Show what-if notification if in preview mode
if (${what-if}) {
    Write-Host ""
    Write-Host "🔍 " -NoNewline -ForegroundColor Yellow
    Write-Host "what-if Mode: Previewing actions without making changes" -ForegroundColor Yellow
    Write-Host " No actual installations, configurations, or file modifications will be performed" -ForegroundColor Gray
    Write-Host ""
}

# Start the setup process
Start-Setup