Public/Add-GitIdentity.ps1

function Add-GitIdentity {
<#
.SYNOPSIS
Adds or extends a Git/SSH identity.
.DESCRIPTION
Creates (or updates) per-alias git config, SSH key (optional), host block, and includeIf entries for provided folders.
.PARAMETER Alias
Identity alias (unique).
.PARAMETER Platform
Platform name (github|azure|gitlab|bitbucket). Default github.
.PARAMETER Name
Git user.name
.PARAMETER Email
Git user.email
.PARAMETER Username
Credential username for platform.
.PARAMETER Folders
One or more repository root folders (gitdir scope). If an existing identity exists, new folders are appended.
.PARAMETER User
Windows user profile (defaults to current user).
.PARAMETER ForceRegenKeys
Regenerate SSH key even if exists.
.PARAMETER DryRun
Simulate actions.
.PARAMETER FileLog
Enable file logging.
.PARAMETER Verbosity
Log verbosity (Silent|Error|Warn|Info|Debug).
.EXAMPLE
Add-GitIdentity -Alias work -Name "Jane Doe" -Email jane@corp.com -Username janed -Folders C:\Repos\Work1,C:\Repos\Work2
#>


    param(
        [Parameter(Mandatory)][string]$Alias,
        [string]$Platform,
        [Parameter(Mandatory)][string]$Name,
        [Parameter(Mandatory)][string]$Email,
        [Parameter(Mandatory)][string]$Username,
        [Parameter(Mandatory)][string[]]$Folders,
        [string]$User,
        [ValidateSet('ed25519','rsa')][string]$SshAlgorithm,
        [switch]$SshForceRegenKeys,
        [string[]]$SshUser,
        [switch]$DryRun,
        [switch]$FileLog,
        [ValidateSet('Silent','Error','Warn','Info','Debug')][string]$Verbosity = 'Warn'
    )
    # Determinar algoritmo efectivo usando configuración centralizada
    $effectiveSshAlgorithm = $SshAlgorithm
    if (-not $effectiveSshAlgorithm) {
        $platKey = if ($Platform) { $Platform.ToLowerInvariant() } else { '' }
        if ($platKey -and $script:GIPlatformMap.ContainsKey($platKey)) {
            $effectiveSshAlgorithm = $script:GIPlatformMap[$platKey].SshAlgorithm
        } else {
            $effectiveSshAlgorithm = $script:DefaultSshAlgorithm
        }
    }

    # Determinar usuario(s) SSH efectivo(s) usando configuración centralizada
    $effectiveSshUser = $SshUser
    if (-not $effectiveSshUser -or $effectiveSshUser.Count -eq 0) {
        $platKey = if ($Platform) { $Platform.ToLowerInvariant() } else { '' }
        if ($platKey -and $script:GIPlatformMap.ContainsKey($platKey)) {
            # Procesar el array de SshUsers, reemplazando {{USERNAME}} por el $Username real
            $effectiveSshUser = @($script:GIPlatformMap[$platKey].SshUsers | ForEach-Object {
                if ($_ -eq '{{USERNAME}}') { 
                    if ($Username) { $Username } else { $null }
                } else { 
                    $_ 
                }
            } | Where-Object { $_ -ne $null })
        } else {
            $effectiveSshUser = @('git')
        }
    } elseif ($effectiveSshUser -is [string]) {
        $effectiveSshUser = @($effectiveSshUser)
    }
    Write-GILog  -Level INFO -Message "Using SSH users: $($effectiveSshUser -join ', ')"

    $script:GitIdentitiesVerbosity = $Verbosity
    $userHome = Get-GIUserHome -User $User
    Set-GILogFile -UserHome $userHome -FileLog:$FileLog
    Write-GILog -Level INFO -Message "Adding identity $Alias"

    # Derivar plataforma si no se pasa explícitamente (regla minimal)
    if (-not $PSBoundParameters.ContainsKey('Platform') -or [string]::IsNullOrWhiteSpace($Platform)) {
        try {
            $derivedHost = Get-GIAliasCanonicalHost -Alias $Alias -Email $Email
            # Buscar plataforma por CanonicalHost
            $Platform = 'github'  # fallback
            foreach ($key in $script:GIPlatformMap.Keys) {
                if ($script:GIPlatformMap[$key].CanonicalHost -eq $derivedHost) {
                    $Platform = $key
                    break
                }
            }
            Write-GILog -Level DEBUG -Message "Derived platform=$Platform from host=$derivedHost"
        } catch { Write-GILog -Level DEBUG -Message "Platform derivation fallback: $($_.Exception.Message)"; if (-not $Platform) { $Platform='github' } }
    }

    # Normalize folders
    $normalized = @()
    foreach ($f in $Folders) { $nf = Get-GINormalizedFolderPath -Path $f; if ($nf) { $normalized += $nf } }
    if ($normalized.Count -eq 0) { throw 'No valid folders provided.' }

    # Provision artifacts in user folder
    try {
        # Configure Windows Credential Manager if needed
        Set-GICredentialHelper -UserHome $userHome -DryRun:$DryRun

        $sshKeyPath = "~/.ssh/id_${Alias}"
        $aliasCfg = Set-GIAliasGitConfig -UserHome $userHome -Alias $Alias -Name $Name -Email $Email -Username $Username -SshKeyPath $sshKeyPath -SshUser $effectiveSshUser -DryRun:$DryRun
        Write-GILog -Level DEBUG -Message "Alias gitconfig ensured: $aliasCfg"
        Set-GIIncludeIfBlocks -UserHome $userHome -Alias $Alias -Folders $normalized -DryRun:$DryRun
        $keyPath = Set-GISshKey -UserHome $userHome -Alias $Alias -Email $Email -Algorithm $effectiveSshAlgorithm -Force:$SshForceRegenKeys -DryRun:$DryRun
        # Set-GISshHostBlock -UserHome $userHome -Alias $Alias -Platform $Platform -DryRun:$DryRun | Out-Null # Commented out: SSH config now managed via git config core.sshCommand instead
    } catch {
        Write-GILog -Level ERROR -Message "Provisioning error: $($_.Exception.Message)"
    }
    Write-GILog -Level INFO -Message 'Provisioning steps executed.'
}