name: Code Style Check

on:
  push:
  pull_request:
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:
  clang-format:
    runs-on: ubuntu-latest
    env:
      STYLE_FIX_BRANCH: codex/style-autofix-${{ github.run_id }}-${{ github.run_attempt }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install clang-format
        run: |
          sudo apt-get update
          sudo apt-get install -y clang-format

      - name: Resolve base ref
        id: base
        shell: bash
        run: |
          set -euo pipefail
          if [[ "${{ github.event_name }}" == "pull_request" ]]; then
            echo "base_ref=${{ github.event.pull_request.head.ref }}" >> "$GITHUB_OUTPUT"
          else
            echo "base_ref=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
          fi

      - name: Detect auto-fix capability
        id: capability
        shell: bash
        run: |
          set -euo pipefail
          can_fix=false
          if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            can_fix=true
          elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]]; then
            can_fix=true
          fi
          echo "can_fix=$can_fix" >> "$GITHUB_OUTPUT"

      - name: Run clang-format and detect drift
        id: format
        shell: bash
        run: |
          set -euo pipefail

          mapfile -t files < <(
            git ls-files \
              '*.c' '*.h' '*.cc' '*.cpp' '*.cxx' '*.hpp' '*.hxx' \
              | grep -Ev '^(limine/|third_party/|build/|build-cmake/)' || true
          )

          if [[ ${#files[@]} -eq 0 ]]; then
            echo "No C/C++ files to check."
            echo "changed=false" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          for f in "${files[@]}"; do
            clang-format -i "$f"
          done

          if git diff --quiet -- "${files[@]}"; then
            echo "changed=false" >> "$GITHUB_OUTPUT"
            echo "Code style check passed."
            exit 0
          fi

          echo "changed=true" >> "$GITHUB_OUTPUT"
          echo "Style drift detected. Auto-fix patch:"
          echo ""
          git diff -- "${files[@]}"

      - name: Create auto-fix PR
        id: cpr
        if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix == 'true'
        continue-on-error: true
        uses: peter-evans/create-pull-request@v7
        with:
          token: ${{ secrets.STYLE_PR_TOKEN != '' && secrets.STYLE_PR_TOKEN || secrets.GITHUB_TOKEN }}
          commit-message: "style: auto-format C/C++ sources with clang-format"
          title: "style: auto-format C/C++ sources"
          body: |
            This PR was generated automatically by CI style check.

            - Trigger: `${{ github.event_name }}`
            - Base branch: `${{ steps.base.outputs.base_ref }}`
            - Formatter: `clang-format`
          branch: ${{ env.STYLE_FIX_BRANCH }}
          base: ${{ steps.base.outputs.base_ref }}
          delete-branch: true
          labels: |
            automated
            style

      - name: Report auto-fix PR result
        if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix == 'true'
        shell: bash
        run: |
          if [[ "${{ steps.cpr.outcome }}" == "success" ]]; then
            echo "Auto-fix PR created: ${{ steps.cpr.outputs.pull-request-url }}"
            exit 0
          fi

          echo "::warning::Auto-fix branch was pushed, but PR creation is blocked by repository policy."
          echo "::warning::Enable 'Allow GitHub Actions to create and approve pull requests' OR set secret STYLE_PR_TOKEN (PAT with repo scope)."
          echo "Manual PR URL:"
          echo "https://github.com/${{ github.repository }}/compare/${{ steps.base.outputs.base_ref }}...${{ env.STYLE_FIX_BRANCH }}?expand=1"
          exit 0

      - name: Fail when style drift cannot be auto-fixed
        if: steps.format.outputs.changed == 'true' && steps.capability.outputs.can_fix != 'true'
        shell: bash
        run: |
          echo "Style drift found, but this event does not have permission to auto-create a fix PR."
          echo "Please run clang-format locally and push the result."
          exit 1
