name: PowerShell Lint & Format

on:
  push:
    paths:
      - "**/*.ps1"
      - ".github/workflows/ps-lint-format.yml"
  pull_request:
    paths:
      - "**/*.ps1"
  workflow_dispatch:

jobs:
  lint-and-format:
    name: Lint & Format PowerShell
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install PSScriptAnalyzer (provides Invoke-ScriptAnalyzer and Invoke-Formatter)
        shell: pwsh
        run: |
          Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Force -SkipPublisherCheck
          Get-Module -ListAvailable PSScriptAnalyzer | Select-Object Name,Version,Path

      - name: Find PowerShell files
        id: find_files
        shell: pwsh
        run: |
          $files = Get-ChildItem -Path . -Recurse -File -Include *.ps1 -ErrorAction SilentlyContinue |
                   Where-Object { $_.FullName -notmatch '\\.git\\' }
          if ($files.Count -eq 0) {
            Write-Host "No PowerShell files found."
            '' | Out-File -FilePath matched_ps_files.txt -Encoding utf8
            exit 0
          }
          $files | ForEach-Object { $_.FullName } | Out-File -FilePath matched_ps_files.txt -Encoding utf8
          Write-Host "Found $($files.Count) PowerShell file(s)."

      - name: Run PSScriptAnalyzer (lint)
        shell: pwsh
        run: |
          if (Test-Path matched_ps_files.txt) {
            $paths = Get-Content matched_ps_files.txt | Where-Object { $_ -ne '' }
          } else {
            Write-Host "No files to lint."
            exit 0
          }
          if ($paths.Count -eq 0) {
            Write-Host "No files to lint."
            exit 0
          }
          Write-Host ("Running Invoke-ScriptAnalyzer on {0} file(s)..." -f $paths.Count)
          $allResults = @()
          foreach ($p in $paths) {
            try {
              # Invoke per-file to avoid binding issues with -Path
              $res = Invoke-ScriptAnalyzer -Path $p -Severity Warning,Error -ErrorAction SilentlyContinue
              if ($res) { $allResults += $res }
            } catch {
              Write-Warning ("Invoke-ScriptAnalyzer failed for {0}: {1}" -f $p, $_)
            }
          }

          if (-not $allResults) {
            Write-Host "No issues found by PSScriptAnalyzer."
            exit 0
          }

          Write-Host ("PSScriptAnalyzer found {0} issue(s):" -f $allResults.Count)
          $allResults | ForEach-Object {
            $file = $_.ScriptName
            $line = $_.Line
            $rule = $_.RuleName
            $severity = $_.Severity
            $message = ($_.Message -replace '\s+',' ')
            Write-Host ("{0} - {1}:{2} - {3} - {4}" -f $severity, $file, $line, $rule, $message)
          }

          Write-Host "Lint step completed (issues printed above)."

      - name: Format PowerShell files (Invoke-Formatter)
        id: format
        shell: pwsh
        run: |
          if (Test-Path matched_ps_files.txt) {
            $paths = Get-Content matched_ps_files.txt | Where-Object { $_ -ne '' }
          } else {
            Write-Host "No files to format."
            '' | Out-File -FilePath ps_formatted_files.txt -Encoding utf8
            exit 0
          }
          if ($paths.Count -eq 0) {
            Write-Host "No files to format."
            '' | Out-File -FilePath ps_formatted_files.txt -Encoding utf8
            exit 0
          }

          $changed = @()
          foreach ($p in $paths) {
            try {
              $orig = Get-Content -Raw -LiteralPath $p -ErrorAction Stop
              $formatted = Invoke-Formatter -ScriptDefinition $orig -ErrorAction Stop
              if ($null -eq $formatted) { continue }
              if ($formatted -ne $orig) {
                Set-Content -LiteralPath $p -Value $formatted -Encoding utf8
                $changed += $p
                Write-Host ("Formatted: {0}" -f $p)
              } else {
                Write-Host ("Unchanged: {0}" -f $p)
              }
            } catch {
              Write-Warning ("Formatting failed for {0}: {1}" -f $p, $_)
            }
          }

          if ($changed.Count -eq 0) {
            Write-Host "No files were reformatted."
            '' | Out-File -FilePath ps_formatted_files.txt -Encoding utf8
          } else {
            $changed | Out-File -FilePath ps_formatted_files.txt -Encoding utf8
            Write-Host ("Reformatted {0} file(s)." -f $changed.Count)
          }

      - name: Commit & push formatted files (if any)
        if: always()
        shell: pwsh
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          if (-not (Test-Path ps_formatted_files.txt)) {
            Write-Host "No formatted-files list found; nothing to commit."
            exit 0
          }
          $formatted = Get-Content ps_formatted_files.txt | Where-Object { $_ -ne '' }
          if ($formatted.Count -eq 0) {
            Write-Host "No formatted files to commit."
            exit 0
          }

          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add *.ps1
          if (git diff --cached --quiet) {
            Write-Host "No changes to commit."
            exit 0
          }
          git commit -m "Apply PowerShell formatting"
          git push origin HEAD:"${{ github.ref_name }}"
