src/public/Security/Sync-AitherSecretsToGitHub.ps1

#Requires -Version 7.0

<#
.SYNOPSIS
    Syncs local AitherZero secrets to GitHub repository secrets.

.DESCRIPTION
    Pushes locally stored credentials to GitHub Actions secrets.
    This enables a workflow where:
    1. Store secrets locally using Set-AitherCredential (encrypted, secure)
    2. Sync to GitHub for CI/CD use
    3. Load locally using Initialize-AitherSecrets for dev work
    
    GitHub Secrets are WRITE-ONLY by design - you cannot retrieve them.
    Your local vault is the source of truth.

.PARAMETER Names
    Specific secret names to sync. If not provided, syncs all API keys.

.PARAMETER Owner
    GitHub repository owner. Defaults to 'Aitherium'.

.PARAMETER Repo
    GitHub repository name. Defaults to 'AitherZero-Internal'.

.PARAMETER Force
    Skip confirmation prompts.

.EXAMPLE
    Sync-AitherSecretsToGitHub -Names "OPENAI_API_KEY", "ANTHROPIC_API_KEY"
    
    Syncs specific API keys to GitHub.

.EXAMPLE
    Sync-AitherSecretsToGitHub -Force
    
    Syncs all stored API keys to GitHub without prompting.

.NOTES
    Requires:
    - GitHub CLI (gh) authenticated: gh auth login
    - PyNaCl or libsodium for encryption (gh handles this automatically)
#>

function Sync-AitherSecretsToGitHub {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [string[]]$Names,

        [Parameter()]
        [string]$Owner = "Aitherium",

        [Parameter()]
        [string]$Repo = "AitherZero-Internal",

        [Parameter()]
        [switch]$Force,

        [Parameter()]
        [switch]$ShowOutput
    )

    begin {
        # Verify gh CLI is available and authenticated
        if (-not (Get-Command gh -ErrorAction SilentlyContinue)) {
            throw "GitHub CLI (gh) is not installed. Install it from https://cli.github.com/"
        }

        $authStatus = gh auth status 2>&1
        if ($LASTEXITCODE -ne 0) {
            throw "GitHub CLI is not authenticated. Run 'gh auth login' first."
        }

        # Get credential storage path
        $credentialPath = if ($IsWindows) {
            Join-Path $env:USERPROFILE ".aitherzero" "credentials"
        } else {
            Join-Path $env:HOME ".aitherzero" "credentials"
        }
    }

    process {
        try {
            # Get all stored credentials if no specific names provided
            if (-not $Names) {
                if (-not (Test-Path $credentialPath)) {
                    Write-AitherLog -Level Warning -Message "No credentials stored. Use Set-AitherCredential first." -Source 'Sync-AitherSecretsToGitHub'
                    return
                }

                $credFiles = Get-ChildItem -Path $credentialPath -Filter "*.cred" -File
                $Names = $credFiles | ForEach-Object { $_.BaseName }
            }

            if (-not $Names -or $Names.Count -eq 0) {
                Write-AitherLog -Level Warning -Message "No secrets to sync." -Source 'Sync-AitherSecretsToGitHub'
                return
            }

            $results = @()

            foreach ($name in $Names) {
                try {
                    # Get the secret value
                    $secretValue = Get-AitherCredential -Name $name -AsPlainText -ErrorAction Stop

                    if (-not $secretValue) {
                        Write-AitherLog -Level Warning -Message "Secret '$name' is empty, skipping." -Source 'Sync-AitherSecretsToGitHub'
                        continue
                    }

                    # GitHub secret names must be uppercase with underscores
                    $ghSecretName = $name.ToUpper() -replace '-', '_'

                    if ($PSCmdlet.ShouldProcess("$Owner/$Repo", "Set secret '$ghSecretName'")) {
                        if (-not $Force) {
                            $confirm = Read-Host "Sync '$name' to GitHub as '$ghSecretName'? (y/N)"
                            if ($confirm -notmatch '^[Yy]') {
                                Write-AitherLog -Level Information -Message "Skipped: $name" -Source 'Sync-AitherSecretsToGitHub'
                                continue
                            }
                        }

                        # Use gh CLI to set the secret (handles encryption automatically)
                        $secretValue | gh secret set $ghSecretName --repo "$Owner/$Repo" 2>&1

                        if ($LASTEXITCODE -eq 0) {
                            $results += [PSCustomObject]@{
                                Name = $name
                                GitHubName = $ghSecretName
                                Status = "Synced"
                            }
                            if ($ShowOutput) {
                                Write-AitherLog -Level Information -Message "✅ Synced: $name → $ghSecretName" -Source 'Sync-AitherSecretsToGitHub'
                            }
                        } else {
                            $results += [PSCustomObject]@{
                                Name = $name
                                GitHubName = $ghSecretName
                                Status = "Failed"
                            }
                            Write-AitherLog -Level Warning -Message "Failed to sync '$name'" -Source 'Sync-AitherSecretsToGitHub'
                        }
                    }
                }
                catch {
                    Write-AitherLog -Level Warning -Message "Error syncing '$name': $_" -Source 'Sync-AitherSecretsToGitHub' -Exception $_
                    $results += [PSCustomObject]@{
                        Name = $name
                        GitHubName = ""
                        Status = "Error: $_"
                    }
                }
            }

            return $results
        }
        catch {
            Write-AitherLog -Level Error -Message "Sync failed: $_" -Source 'Sync-AitherSecretsToGitHub' -Exception $_
            throw
        }
    }
}