---
name: Open PRs in Ethereum plugins to update SDK

on:
  workflow_dispatch:
  # TODO add auto trigger once finalized

jobs:
  build-repositories-matrix:
    name: Build repo matrix
    runs-on: ubuntu-latest
    env:
      GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
    steps:
      - name: List plugin repositories
        id: list-repos
        run: |
          # Retrieve the list of repositories from LedgerHQ organization
          raw_repo_list=$(gh repo list LedgerHQ -L 2000 \
                          --json name \
                          --json isPrivate \
                          --json isArchived \
                          --jq '.[] | select(.isPrivate == false and .isArchived == false and select(.name | startswith("app-plugin-"))) | .name')
          # Format the repository list as a JSON array
          formatted_repo_list="["
          while IFS= read -r repo; do
            formatted_repo_list+="\"$repo\", "
          done < <(echo "$raw_repo_list")
          formatted_repo_list=${formatted_repo_list%%, }"]"
          echo "Formatted Repository List: $formatted_repo_list"
          # Set output
          echo "repo_list=$formatted_repo_list" >> $GITHUB_OUTPUT
    outputs:
      repo-matrix: ${{ steps.list-repos.outputs.repo_list }}


  get-sdk-ref:
    name: Get latest SDK reference
    runs-on: ubuntu-latest
    steps:
      - name: Checkout SDK repository
        uses: actions/checkout@v3
        with:
          repository: LedgerHQ/ethereum-plugin-sdk
          ref: develop
      - name: Retrieve SDK reference
        id: get-hash
        run: |
          # Get the short SHA reference of the latest commit in the SDK repository
          sdk_ref=$(git rev-parse --short HEAD)
          echo "SDK Reference: $sdk_ref"
          # Set output
          echo "sdk_ref=$sdk_ref" >> $GITHUB_OUTPUT
    outputs:
      sdk_ref: ${{ steps.get-hash.outputs.sdk_ref }}


  open-issue:
    name: Open SDK update summary issue
    runs-on: ubuntu-latest
    needs: get-sdk-ref
    env:
      GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
    steps:
      - name: Create 'auto' label if missing
        run: |
          if [[ -z $(gh label list --repo ${{ github.repository }} --search auto) ]]; then
            gh label create 'auto' --repo ${{ github.repository }} --color 'b4a8d1' --description 'Automatically created'
          fi
      - name: Open SDK Update Issue
        id: open-issue
        run: |
          # Create a new issue with the SDK reference in the SDK repository
          issue_url=$(gh issue create \
                        --repo ${{ github.repository }} \
                        --label auto \
                        --title "Bumping Eth plugin SDK to latest version ${{ needs.get-sdk-ref.outputs.sdk_ref }}" \
                        --body "Placeholder")
          echo "Issue URL: $issue_url"
          # Set output
          echo "issue_url=$issue_url" >> $GITHUB_OUTPUT
    outputs:
      issue_url: ${{ steps.open-issue.outputs.issue_url }}


  open-prs:
    name: Open pull requests
    runs-on: ubuntu-latest
    needs: [build-repositories-matrix, open-issue, get-sdk-ref]
    strategy:
      fail-fast: false
      matrix:
        repo: ${{ fromJSON(needs.build-repositories-matrix.outputs.repo-matrix) }}
    env:
      GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}

    steps:
      - name: Checkout plugin repository
        uses: actions/checkout@v3
        with:
          repository: LedgerHQ/${{ matrix.repo }}
          submodules: recursive
          ref: develop
          # by default the action uses fetch-depth = 1, which creates
          # shallow repositories from which we can't push
          fetch-depth: 0
          # needed, else the push inside the action will use default credentials
          # instead of provided ones
          persist-credentials: false

      - name: Update submodule
        run: |
          cd ethereum-plugin-sdk/
          git checkout ${{ needs.get-sdk-ref.outputs.sdk_ref }}

      - name: Commit changes
        id: commit-changes
        run: |
          # Set credentials for commit creation
          git config --global user.name "github-actions[bot]"
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
          # Branch name and title will be unique by design
          branch_name="auto/bump_sdk_to_${{ needs.get-sdk-ref.outputs.sdk_ref }}"
          title="[auto-update] Bump SDK to latest develop version ${{ needs.get-sdk-ref.outputs.sdk_ref }}"
          echo "Branch Name: $branch_name"
          echo "Title: $title"
          git status
          git commit -am "$title"
          # Set output
          echo "title=$title" >> $GITHUB_OUTPUT
          echo "branch_name=$branch_name" >> $GITHUB_OUTPUT

      - name: Push commit
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.CI_BOT_TOKEN }}
          branch: ${{ steps.commit-changes.outputs.branch_name }}
          repository: LedgerHQ/${{ matrix.repo }}
          force: true

      - name: Create 'auto' label if missing
        run: |
          if [[ -z $(gh label list --search auto) ]]; then
            gh label create 'auto' --color 'b4a8d1' --description 'Automatically created'
          fi

      - name: Create pull request and commment on SDK issue
        run: |
          # Github limits the number of possible PR being opened in a given time window.
          # The limits are 20 creation per minute and 150 per hour.
          # As suggested in the Github documentation, put a sleep between each POST call
          # 3 seconds should be sufficient but let's sleep 4 seconds just in case.
          sleep $((4 * ${{ strategy.job-index }}))
          # Create the PR with a placeholder body. Will be consolidated at a later step
          pr_url=$(gh pr create \
                     --base 'develop' \
                     --head '${{ steps.commit-changes.outputs.branch_name }}' \
                     --label 'auto' \
                     --title '${{ steps.commit-changes.outputs.title }}' \
                     --body 'Created by a Github workflow')
          echo "Pull request URL: $pr_url"
          # Log the url of the PR in the issue on SDK side. We'll collect them from the issue later
          gh issue comment "${{ needs.open-issue.outputs.issue_url }}" --body "OPENED $pr_url"


  clean-issue:
    name: Clean SDK update summary issue
    runs-on: ubuntu-latest
    needs: [get-sdk-ref, open-issue, open-prs]
    env:
      GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
    steps:
      - name: Collect all comments on the SDK issue
        run: |
          # Get the full text of the issue: metadata + title + rich comments
          content="$(gh issue view --comments "${{ needs.open-issue.outputs.issue_url }}")"
          # New header of the issue body
          header="Bumping Ethereum plugin SDK to latest version ${{ needs.get-sdk-ref.outputs.sdk_ref }} for all Ethereum plugins:"
          # Filter the full text of the issue to collect only the PR urls
          lines=""
          while IFS= read -r line; do
            if [[ "$line" =~ "OPENED" ]]; then
              lines+=$(echo "$line" | cut -d ' ' -f2)$'\n'
            fi
          done < <(echo "$content")
          # Use print to resolve the '\n' chars
          new_body="$(printf "$header\n$lines")"
          echo "New issue body: $new_body"
          # Set the consolidated body of the issue
          gh issue edit "${{ needs.open-issue.outputs.issue_url }}" --body "$new_body"

      - name: Clean comments on the SDK issue
        run: |
          # gh api uses id instead of url
          issue_id="$(basename "${{ needs.open-issue.outputs.issue_url }}")"
          # Get url of all comments on the issue
          comment_urls="$(gh api "repos/${{ github.repository }}/issues/${issue_id}/comments" --jq '.[].url')"
          # Delete each comment using the Github REST api
          while IFS= read -r url; do
            echo "Deleting comment: $comment_urls"
            gh api -X DELETE "$url"
          done < <(echo "$comment_urls")
