modules/interactive_components.ps1

<#
.SYNOPSIS
    PSConsoleUI - Interactive Components
.DESCRIPTION
    Interactive UI components including menus, choices, inputs.
#>


function Show-ConsoleMenu {
    <#
    .SYNOPSIS
        Displays an interactive menu with numbered options.
    #>

    [CmdletBinding()]
    param(
        [string]$Title,
        [array]$Options,
        [string]$Color = 'Cyan',
        [string]$OptionColor = 'Gray',
        [string]$Footer = '',
        [switch]$NoClear
    )

    if (-not $Color -or $Color.Trim() -eq '') { $Color = 'Cyan' }
    if (-not $OptionColor -or $OptionColor.Trim() -eq '') { $OptionColor = 'Gray' }
    
    # Respect Global Dev Mode (Infinite Scroll)
    if (-not $NoClear -and -not $Global:CassielDevMode) {
        Clear-Host
    }
    $width = 60
    
    $border = '=' * $width
    Write-Host ''
    Write-Host $border -ForegroundColor $Color
    $padding = [Math]::Floor(($width - $Title.Length) / 2)
    Write-Host ((' ' * $padding) + $Title) -ForegroundColor White
    Write-Host $border -ForegroundColor $Color
    Write-Host ''
    
    $selectableCount = 0
    for ($i = 0; $i -lt $Options.Count; $i++) {
        $opt = $Options[$i]
        
        if ($opt -match '^---') {
            Write-Host (' ' + $opt) -ForegroundColor DarkGray
        }
        elseif ($opt -match '^\[') {
            Write-Host (' ' + $opt) -ForegroundColor $Color
        }
        else {
            $selectableCount++
            $text = $opt
            $itemColor = $OptionColor
            if ($opt -match '^\{([a-zA-Z]+)\}(.*)') {
                $itemColor = $matches[1]
                $text = $matches[2]
            }
            Write-Host ' [' -NoNewline -ForegroundColor Gray
            Write-Host ([string]$selectableCount) -NoNewline -ForegroundColor $Color
            Write-Host '] ' -NoNewline -ForegroundColor Gray
            Write-Host $text -ForegroundColor $itemColor
        }
    }
    
    if ($Footer) {
        Write-Host ''
        Write-Host (' ' + $Footer) -ForegroundColor Yellow
    }
    
    Write-Host ''
    return $selectableCount
}

function Read-ConsoleChoice {
    <#
    .SYNOPSIS
        Reads and validates a numeric menu choice from the user.
    #>

    [CmdletBinding()]
    param(
        [int]$MaxChoice,
        [string]$Prompt = 'Selecciona una opcion',
        [bool]$AllowZero = $true
    )
    
    if ($AllowZero) {
        Write-Host '(0 para salir)' -ForegroundColor Gray
    }
    
    Write-Host ''

    do {
        Write-Host ($Prompt + ': ') -NoNewline -ForegroundColor Cyan
        
        $val = Read-Host
        
        if ($val -match '^\d+$') {
            $choice = [int]$val
            if ($AllowZero -and $choice -eq 0) {
                return 0
            }
            if ($choice -ge 1 -and $choice -le $MaxChoice) {
                return $choice
            }
        }
        
        Write-Host ' [!] Opcion invalida. Intenta de nuevo.' -ForegroundColor Red
        Write-Host ''
    } while ($true)
}

function Invoke-ConsoleMenu {
    <#
    .SYNOPSIS
        Displays an interactive menu and executes selected actions.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Title,
        
        [Parameter(Mandatory = $true)]
        [array]$MenuItems,
        
        [Parameter(Mandatory = $false)]
        [string]$Footer = ''
    )
    
    do {
        $options = $MenuItems | ForEach-Object { $_.Label }
        $count = Show-ConsoleMenu -Title $Title -Options $options -Footer $Footer
        
        $choice = Read-ConsoleChoice -MaxChoice $count -AllowZero $true
        
        if ($choice -eq 0) {
            break
        }
        
        $selectedItem = $MenuItems[$choice - 1]
        if ($selectedItem.Action) {
            & $selectedItem.Action
        }
        
        Write-Host ''
        Write-Host ' Presiona Enter para continuar...' -ForegroundColor Gray
        Read-Host
        
    } while ($true)
}

function Read-ConsoleMultiChoice {
    <#
    .SYNOPSIS
        Reads multiple selections from a list of options.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [array]$Options,
        
        [Parameter(Mandatory = $false)]
        [string]$Prompt = 'Seleccione opciones (Separadas por coma)'
    )
    
    Write-Host (' ' + $Prompt) -ForegroundColor Cyan
    $i = 1
    foreach ($opt in $Options) {
        Write-Host (' [' + $i + '] ' + $opt)
        $i++
    }
    
    $val = Read-Host ' > '
    if (-not $val) { return @() }
    
    $selectedIndices = $val.Split(',')
    $results = @()
    foreach ($idx in $selectedIndices) {
        if ($idx -match '^\d+$' -and [int]$idx -le $Options.Count) {
            $results += $Options[[int]$idx - 1]
        }
    }
    return $results
}

function Write-ConsoleTable {
    param(
        [Parameter()]
        [array]$Data,
        [Parameter()]
        [array]$Columns,
        [string]$Title = '',
        [string]$ColorMapProperty = '', 
        [hashtable]$ColorMap = @{}
    )

    if ($Data.Count -eq 0) {
        Write-Host ' (No data to display)' -ForegroundColor Gray
        return
    }

    # Helper: Wrap Text
    function Get-WrappedLines {
        param([string]$Text, [int]$Width)
        if ([string]::IsNullOrEmpty($Text)) { return @('') }
        $rawLines = $Text -split "`n"
        $finalLines = @()
        foreach ($line in $rawLines) {
            if ($line.Length -le $Width) {
                $finalLines += $line
            }
            else {
                $currentLine = ''
                $words = $line -split ' '
                foreach ($word in $words) {
                    if (($currentLine.Length + $word.Length + 1) -le $Width) {
                        $currentLine += ($word + ' ')
                    }
                    else {
                        $finalLines += $currentLine.Trim()
                        $currentLine = ($word + ' ')
                    }
                }
                if ($currentLine) { $finalLines += $currentLine.Trim() }
            }
        }
        return $finalLines
    }
    
    # Simple table rendering
    Write-Host ''
    if ($Title) { Write-Host (' ' + $Title) -ForegroundColor Cyan }
    
    # Headers
    Write-Host ' ' -NoNewline
    foreach ($col in $Columns) {
        Write-Host ($col.Header.PadRight($col.Width)) -NoNewline -ForegroundColor Yellow
    }
    Write-Host ''
    
    # Rows
    foreach ($row in $Data) {
        Write-Host ' ' -NoNewline
        foreach ($col in $Columns) {
            $val = $row.($col.Property)
            Write-Host ([string]$val).PadRight($col.Width) -NoNewline -ForegroundColor White
        }
        Write-Host ''
    }
    Write-Host ''
}

function Invoke-ConsoleSpinner {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message, 
        
        [Parameter(Mandatory = $true)]
        [Alias('ScriptBlock')]
        [scriptblock]$Action
    )
    Write-Host $Message -NoNewline
    $spinner = @('|', '/', '-', '\')
    $job = Start-Job -ScriptBlock $Action
    while ($job.State -eq 'Running') {
        foreach ($s in $spinner) {
            Write-Host "`b$s" -NoNewline
            Start-Sleep -Milliseconds 100
        }
    }
    Receive-Job $job
    Write-Host "`bDone" -ForegroundColor Green
}

function Write-ConsoleProgress {
    param([string]$Activity, [int]$Percent)
    Write-Progress -Activity $Activity -PercentComplete $Percent
}

function Show-ConsoleProgress {
    <#
    .SYNOPSIS
        Displays a visual progress bar in the console.
    .DESCRIPTION
        Shows a progress bar with percentage using safe ASCII characters.
    .PARAMETER Activity
        Description of the activity being performed.
    .PARAMETER PercentComplete
        Percentage complete (0-100).
    .PARAMETER BarLength
        Length of the progress bar (default: 20).
    .PARAMETER Color
        Color of the filled portion (default: Cyan).
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Activity,
        
        [Parameter(Mandatory = $true)]
        [ValidateRange(0, 100)]
        [int]$PercentComplete,
        
        [int]$BarLength = 20,
        [string]$Color = 'Cyan'
    )
    
    # Calculate filled and empty portions
    $filled = [Math]::Floor(($PercentComplete / 100) * $BarLength)
    $empty = $BarLength - $filled
    
    # Build progress bar using safe ASCII characters
    $filledBar = '#' * $filled
    $emptyBar = '.' * $empty
    
    # Display progress bar
    Write-Host " $Activity " -NoNewline
    Write-Host '[' -NoNewline -ForegroundColor Gray
    Write-Host $filledBar -NoNewline -ForegroundColor $Color
    Write-Host $emptyBar -NoNewline -ForegroundColor DarkGray
    Write-Host '] ' -NoNewline -ForegroundColor Gray
    Write-Host "$PercentComplete%" -ForegroundColor $Color
}

function Read-ConsoleInput {
    param([string]$Prompt)
    return Read-Host -Prompt $Prompt
}

function Read-ConsoleConfirmation {
    param([string]$Message)
    $response = Read-Host "$Message (y/n)"
    return $response -eq 'y'
}

function Read-ConsolePassword {
    param([string]$Prompt)
    return Read-Host -Prompt $Prompt -AsSecureString
}

function Show-ConsoleNotification {
    param([string]$Message, [string]$Type = 'Info')
    Write-Host "[$Type] $Message" -ForegroundColor Yellow
}


# No local Export-ModuleMember here - handled by main module