name: Update OpenAPI client

on:
  repository_dispatch:
    types: [openapi-spec-updated]
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0

      - name: Set up tools
        uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4

      - name: Cache Go modules
        uses: actions/cache@v4
        with:
          path: |
            ~/go/pkg/mod
            ~/.cache/go-build
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: ${{ runner.os }}-go-

      - name: Write OpenAPI spec
        run: |
          curl -sSL https://raw.githubusercontent.com/kubeasy-dev/monorepo/main/apps/api/openapi.json -o openapi.json

      - name: Normalize OpenAPI spec (3.1 → 3.0 nullable compat)
        run: |
          python3 - <<'EOF'
          import json

          def normalize(obj):
              if isinstance(obj, dict):
                  if isinstance(obj.get("type"), list):
                      types = obj["type"]
                      non_null = [t for t in types if t != "null"]
                      obj["type"] = non_null[0] if len(non_null) == 1 else non_null
                      if "null" in types:
                          obj["nullable"] = True
                  return {k: normalize(v) for k, v in obj.items()}
              elif isinstance(obj, list):
                  return [normalize(i) for i in obj]
              return obj

          with open("openapi.json") as f:
              data = json.load(f)
          data = normalize(data)
          # oapi-codegen v2 does not support OpenAPI 3.1 — downgrade to 3.0.3
          if data.get("openapi", "").startswith("3.1"):
              data["openapi"] = "3.0.3"
          with open("openapi.json", "w") as f:
              json.dump(data, f, indent=2)
          EOF

      - name: Generate API client
        run: mise run generate:api

      - name: Build and test generated code
        run: |
          go build ./...
          go test ./internal/api/...

      - name: Generate GitHub App token
        uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
        id: app-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
          owner: ${{ github.repository_owner }}

      - name: Get GitHub App User ID
        id: get-user-id
        run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
        env:
          GH_TOKEN: ${{ steps.app-token.outputs.token }}

      - name: Configure git
        run: |
          git config --local user.name "${{ steps.app-token.outputs.app-slug }}[bot]"
          git config --local user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com"

      - name: Create or update PR
        env:
          GH_TOKEN: ${{ steps.app-token.outputs.token }}
        run: |
          BRANCH_NAME="chore/update-openapi-from-website"

          git fetch origin

          # Stash les changements générés avant de switch de branche
          git stash --include-untracked

          if git ls-remote --exit-code --heads origin "$BRANCH_NAME" >/dev/null 2>&1; then
            git checkout "$BRANCH_NAME"
            git pull origin "$BRANCH_NAME"
          else
            git checkout -b "$BRANCH_NAME"
          fi

          # Restaurer les changements
          git stash pop

          git add openapi.json internal/apigen/client.gen.go
          if git diff --staged --quiet; then
            echo "No changes to commit"
            exit 0
          fi
          git commit -m "chore: update OpenAPI spec and generated client from website"
          git push origin "$BRANCH_NAME" --force-with-lease

          gh pr create \
            --title "chore: update OpenAPI spec and generated client from website" \
            --body "Auto-generated from website OpenAPI schema changes.

          **Changes:**
          - Updated \`openapi.json\` spec
          - Regenerated \`internal/apigen/client.gen.go\`

          Review and merge when ready." \
            --base main \
            --head "$BRANCH_NAME" || echo "PR already exists, updated with new commits"
