Public/Test-CCGitHub.ps1

function Test-CCGitHub {
    <#
    .SYNOPSIS
        Runs all GitHub configuration compliance checks.

    .DESCRIPTION
        Orchestrates all GitHub checks: branch protection, security, settings, and collaboration.
        Returns structured results suitable for CI pipelines.

    .PARAMETER Repository
        GitHub repository in format "owner/repo". Auto-detected from git remote if not specified.

    .PARAMETER Token
        GitHub token. Falls back to GITHUB_TOKEN, GH_TOKEN, or gh CLI.

    .PARAMETER Standard
        Standard tier: core, active, minimal. Default: core.

    .PARAMETER Config
        Path to per-repo config file (.codecompass/config.yml or .repo-health.yml).

    .PARAMETER FailOn
        Fail with exit code 1 if any check reaches this severity: Error, Warning, or None (never fail).

    .PARAMETER OutputFormat
        Output format: Console (default), Json, or Quiet (exit code only).

    .PARAMETER Detailed
        Show detailed per-check output in console mode.

    .PARAMETER Categories
        Run only specific categories. Default: all.

    .OUTPUTS
        [PSCustomObject[]] Array of all check results.

    .EXAMPLE
        Test-CCGitHub
        # Audits current repo using 'core' standard

    .EXAMPLE
        Test-CCGitHub -Repository 'The-Code-Kitchen/LeadForge' -Standard active

    .EXAMPLE
        Test-CCGitHub -Standard core -FailOn Error -OutputFormat Json
        # CI mode — JSON output, exit 1 on errors
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter()]
        [string]$Repository,

        [Parameter()]
        [string]$Token,

        [Parameter()]
        [ValidateSet('core', 'active', 'minimal')]
        [string]$Standard = 'core',

        [Parameter()]
        [string]$Config,

        [Parameter()]
        [ValidateSet('Error', 'Warning', 'None')]
        [string]$FailOn = 'None',

        [Parameter()]
        [ValidateSet('Console', 'Json', 'Quiet')]
        [string]$OutputFormat = 'Console',

        [Parameter()]
        [switch]$Detailed,

        [Parameter()]
        [ValidateSet('BranchProtection', 'Security', 'Settings', 'Collaboration')]
        [string[]]$Categories
    )

    $allResults = [System.Collections.ArrayList]::new()

    # Resolve common params
    $token = Resolve-CCToken -Token $Token
    if (-not $token) { throw "No GitHub token available. Set GITHUB_TOKEN, GH_TOKEN, or run 'gh auth login'." }

    $repo = Resolve-CCRepository -Repository $Repository
    if (-not $repo) { throw "Cannot determine repository. Specify -Repository 'owner/repo'." }

    # Auto-detect config if not specified
    if (-not $Config) {
        $candidates = @('.codecompass/config.yml', '.codecompass/config.yaml', '.repo-health.yml')
        foreach ($candidate in $candidates) {
            if (Test-Path $candidate) { $Config = $candidate; break }
        }
    }

    $commonParams = @{
        Repository = $repo
        Token      = $token
        Standard   = $Standard
    }
    if ($Config) { $commonParams['Config'] = $Config }

    # Console header
    if ($OutputFormat -eq 'Console') {
        Write-Host ""
        Write-Host " CodeCompass.GitHub Audit" -ForegroundColor Cyan
        Write-Host " Repository: $repo" -ForegroundColor Gray
        Write-Host " Standard: $Standard" -ForegroundColor Gray
        Write-Host ""
    }

    # Run checks by category
    $categoriesToRun = if ($Categories) { $Categories } else { @('BranchProtection', 'Security', 'Settings', 'Collaboration') }

    if ('BranchProtection' -in $categoriesToRun) {
        if ($OutputFormat -eq 'Console') { Write-Host " Branch Protection" -ForegroundColor Yellow }
        $bpResults = Test-CCBranchProtection @commonParams
        if ($bpResults) { $bpResults | ForEach-Object { [void]$allResults.Add($_) } }
        if ($OutputFormat -eq 'Console') { Write-CCCategoryConsole -Results $bpResults -Detailed:$Detailed }
    }

    if ('Security' -in $categoriesToRun) {
        if ($OutputFormat -eq 'Console') { Write-Host " Security" -ForegroundColor Yellow }
        $secResults = Test-CCSecurityConfig @commonParams
        if ($secResults) { $secResults | ForEach-Object { [void]$allResults.Add($_) } }
        if ($OutputFormat -eq 'Console') { Write-CCCategoryConsole -Results $secResults -Detailed:$Detailed }
    }

    if ('Settings' -in $categoriesToRun) {
        if ($OutputFormat -eq 'Console') { Write-Host " Repository Settings" -ForegroundColor Yellow }
        $setResults = Test-CCRepoSettings @commonParams
        if ($setResults) { $setResults | ForEach-Object { [void]$allResults.Add($_) } }
        if ($OutputFormat -eq 'Console') { Write-CCCategoryConsole -Results $setResults -Detailed:$Detailed }
    }

    if ('Collaboration' -in $categoriesToRun) {
        if ($OutputFormat -eq 'Console') { Write-Host " Collaboration" -ForegroundColor Yellow }
        $colResults = Test-CCCollaboration @commonParams
        if ($colResults) { $colResults | ForEach-Object { [void]$allResults.Add($_) } }
        if ($OutputFormat -eq 'Console') { Write-CCCategoryConsole -Results $colResults -Detailed:$Detailed }
    }

    # Summary
    $passed = @($allResults | Where-Object Status -eq 'Pass').Count
    $failed = @($allResults | Where-Object Status -eq 'Fail').Count
    $warnings = @($allResults | Where-Object Status -eq 'Warning').Count
    $skipped = @($allResults | Where-Object Status -eq 'Skipped').Count

    if ($OutputFormat -eq 'Console') {
        Write-Host ""
        Write-Host " ─────────────────────────────────────────" -ForegroundColor Gray
        $summaryColor = if ($failed -gt 0) { 'Red' } elseif ($warnings -gt 0) { 'Yellow' } else { 'Green' }
        Write-Host " Pass: $passed | Fail: $failed | Warning: $warnings | Skipped: $skipped" -ForegroundColor $summaryColor

        if ($failed -eq 0 -and $warnings -eq 0) {
            Write-Host " All checks passed!" -ForegroundColor Green
        }
        elseif ($failed -gt 0) {
            Write-Host " Repository has configuration issues." -ForegroundColor Red
            Write-Host " Run Repair-CCGitHub to auto-fix available issues." -ForegroundColor Gray
        }
        Write-Host ""
    }
    elseif ($OutputFormat -eq 'Json') {
        $output = [PSCustomObject]@{
            repository = $repo
            standard   = $Standard
            timestamp  = (Get-Date -Format 'o')
            summary    = [PSCustomObject]@{ pass = $passed; fail = $failed; warning = $warnings; skipped = $skipped }
            results    = $allResults.ToArray()
        }
        $output | ConvertTo-Json -Depth 5
    }

    # FailOn logic
    if ($FailOn -eq 'Error' -and $failed -gt 0) {
        $host.SetShouldExit(1)
        exit 1
    }
    elseif ($FailOn -eq 'Warning' -and ($failed -gt 0 -or $warnings -gt 0)) {
        $host.SetShouldExit(1)
        exit 1
    }

    return $allResults.ToArray()
}

function Write-CCCategoryConsole {
    <#
    .SYNOPSIS
        Writes per-category results to console.
    #>

    param(
        [PSCustomObject[]]$Results,
        [switch]$Detailed
    )

    if (-not $Results -or $Results.Count -eq 0) {
        Write-Host " (no checks)" -ForegroundColor Gray
        return
    }

    if ($Detailed) {
        foreach ($r in $Results) {
            $icon = switch ($r.Status) {
                'Pass' { ' +' }
                'Fail' { ' x' }
                'Warning' { ' !' }
                'Skipped' { ' -' }
            }
            $color = switch ($r.Status) {
                'Pass' { 'Green' }
                'Fail' { 'Red' }
                'Warning' { 'Yellow' }
                'Skipped' { 'Gray' }
            }
            Write-Host " $icon [$($r.CheckId)] $($r.Message)" -ForegroundColor $color
        }
    }
    else {
        $p = @($Results | Where-Object Status -eq 'Pass').Count
        $f = @($Results | Where-Object Status -eq 'Fail').Count
        $w = @($Results | Where-Object Status -eq 'Warning').Count
        $color = if ($f -gt 0) { 'Red' } elseif ($w -gt 0) { 'Yellow' } else { 'Green' }
        Write-Host " Pass: $p | Fail: $f | Warning: $w" -ForegroundColor $color
    }
    Write-Host ""
}