name: Create Pre-Release PR from Milestone

permissions:
  contents: write
  pull-requests: write
  issues: write

on:
  workflow_dispatch:
    inputs:
      milestone_name:
        description: 'Milestone name to collect closed PRs from'
        required: true
        default: 'v3.8.2'
      target_branch:
        description: 'Target branch to merge the consolidated PR'
        required: true
        default: 'pre-release-v3.8.2'

env:
  MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v3.8.2' }}
  TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v3.8.2' }}
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
  LABEL_NAME: cherry-picked
  TEMP_DIR: /tmp  # Using /tmp as the temporary directory

jobs:
  cherry_pick_milestone_prs:
    runs-on: ubuntu-latest
    steps:
      - name: Setup temp directory
        run: |
          # Create the temporary directory and initialize necessary files
          mkdir -p ${{ env.TEMP_DIR }}
          touch ${{ env.TEMP_DIR }}/pr_numbers.txt
          touch ${{ env.TEMP_DIR }}/commit_hashes.txt
          touch ${{ env.TEMP_DIR }}/pr_title.txt
          touch ${{ env.TEMP_DIR }}/pr_body.txt
          touch ${{ env.TEMP_DIR }}/created_pr_number.txt

      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.BOT_TOKEN }}

      - name: Setup Git User for OpenIM-Robot
        run: |
          # Set up Git credentials for the bot
          git config --global user.email "OpenIM-Robot@users.noreply.github.com"
          git config --global user.name "OpenIM-Robot"

      - name: Fetch Milestone ID and Filter PR Numbers
        env:
          MILESTONE_NAME: ${{ env.MILESTONE_NAME }}
        run: |
          # Fetch milestone details and extract milestone ID
          milestones=$(curl -s -H "Authorization: token $BOT_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            "https://api.github.com/repos/${{ github.repository }}/milestones")
          milestone_id=$(echo "$milestones" | grep -B3 "\"title\": \"$MILESTONE_NAME\"" | grep '"number":' | head -n1 | grep -o '[0-9]\+')
          if [ -z "$milestone_id" ]; then
            echo "Milestone '$MILESTONE_NAME' not found. Exiting."
            exit 1
          fi
          echo "Milestone ID: $milestone_id"
          echo "MILESTONE_ID=$milestone_id" >> $GITHUB_ENV

          # Fetch issues for the milestone
          issues=$(curl -s -H "Authorization: token $BOT_TOKEN" \
                -H "Accept: application/vnd.github+json" \
                "https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100")

          > ${{ env.TEMP_DIR }}/pr_numbers.txt

          # Filter PRs that do not have the 'cherry-picked' label
          for pr_number in $(echo "$issues" | jq -r '.[] | select(.pull_request != null) | .number'); do
            labels=$(curl -s -H "Authorization: token $BOT_TOKEN" \
              -H "Accept: application/vnd.github+json" \
              "https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" | jq -r '.[].name')

            if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
              echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
              echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
            else
              echo "PR #$pr_number already has the 'cherry-picked' label. Skipping."
            fi
          done

          # Sort the filtered PR numbers
          sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt

          echo "Filtered and sorted PR numbers:"
          cat ${{ env.TEMP_DIR }}/pr_numbers.txt || echo "No closed PR numbers found for milestone."

      - name: Fetch Merge Commits for PRs and Generate Title and Body
        run: |
          # Ensure the files are initialized
          > ${{ env.TEMP_DIR }}/commit_hashes.txt
          > ${{ env.TEMP_DIR }}/pr_title.txt
          > ${{ env.TEMP_DIR }}/pr_body.txt

          # Write description to the PR body
          echo "### Description:" >> ${{ env.TEMP_DIR }}/pr_body.txt
          echo "Merging PRs from milestone \`$MILESTONE_NAME\` into target branch \`$TARGET_BRANCH\`." >> ${{ env.TEMP_DIR }}/pr_body.txt
          echo "" >> ${{ env.TEMP_DIR }}/pr_body.txt
          echo "### Need Merge PRs:" >> ${{ env.TEMP_DIR }}/pr_body.txt

          pr_numbers_in_title=""

          # Process sorted PR numbers and generate commit hashes
          for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
            echo "Processing PR #$pr_number"
            pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
              -H "Accept: application/vnd.github+json" \
              "https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
            pr_title=$(echo "$pr_details" | jq -r '.title')
            merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
            short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)

            # Append PR details to the body
            echo "- $pr_title: (#$pr_number) ($short_commit_hash)" >> ${{ env.TEMP_DIR }}/pr_body.txt

            if [ "$merge_commit" != "null" ];then
              echo "$merge_commit" >> ${{ env.TEMP_DIR }}/commit_hashes.txt
              echo "#$pr_number" >> ${{ env.TEMP_DIR }}/pr_title.txt
              pr_numbers_in_title="$pr_numbers_in_title #$pr_number"
            fi
          done

          commit_hashes=$(cat ${{ env.TEMP_DIR }}/commit_hashes.txt | tr '\n' ' ')
          first_commit_hash=$(head -n 1 ${{ env.TEMP_DIR }}/commit_hashes.txt)
          cherry_pick_branch="cherry-pick-${first_commit_hash:0:7}"
          echo "COMMIT_HASHES=$commit_hashes" >> $GITHUB_ENV
          echo "CHERRY_PICK_BRANCH=$cherry_pick_branch" >> $GITHUB_ENV
          echo "pr_numbers_in_title=$pr_numbers_in_title" >> $GITHUB_ENV

      - name: Pull and Cherry-pick Commits, Then Push
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
        run: |
          # Fetch and pull the latest changes from the target branch
          git fetch origin
          git checkout $TARGET_BRANCH
          git pull origin $TARGET_BRANCH

          # Create a new branch for cherry-picking
          git checkout -b $CHERRY_PICK_BRANCH

          # Cherry-pick the commits and handle conflicts
          for commit_hash in $COMMIT_HASHES; do
            echo "Attempting to cherry-pick commit $commit_hash"
            if ! git cherry-pick "$commit_hash" --strategy=recursive -X theirs; then
              echo "Conflict detected for $commit_hash. Resolving with incoming changes."
              conflict_files=$(git diff --name-only --diff-filter=U)
              echo "Conflicting files:"
              echo "$conflict_files"

              for file in $conflict_files; do
                if [ -f "$file" ]; then
                  echo "Resolving conflict for $file"
                  git add "$file"
                else
                  echo "File $file has been deleted. Skipping."
                  git rm "$file"
                fi
              done

              echo "Conflicts resolved. Continuing cherry-pick."
              git cherry-pick --continue
            else
              echo "Cherry-pick successful for commit $commit_hash."
            fi
          done

          # Push the cherry-pick branch to the repository
          git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
          git push origin $CHERRY_PICK_BRANCH --force

      - name: Create Pull Request
        run: |
          # Prepare and create the PR
          pr_title="deps: Merge ${{ env.pr_numbers_in_title }} PRs into $TARGET_BRANCH"
          pr_body=$(cat ${{ env.TEMP_DIR }}/pr_body.txt)

          echo "Prepared PR title:"
          echo "$pr_title"
          echo "Prepared PR body:"
          echo "$pr_body"

          # Create the PR using the GitHub API
          response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            https://api.github.com/repos/${{ github.repository }}/pulls \
            -d "$(jq -n --arg title "$pr_title" \
              --arg head "$CHERRY_PICK_BRANCH" \
              --arg base "$TARGET_BRANCH" \
              --arg body "$pr_body" \
              '{title: $title, head: $head, base: $base, body: $body}')")

          pr_number=$(echo "$response" | jq -r '.number')
          echo "$pr_number" > ${{ env.TEMP_DIR }}/created_pr_number.txt
          echo "Created PR #$pr_number"

      - name: Add Label to Created Pull Request
        run: |
          # Add 'milestone-merge' label to the created PR
          pr_number=$(cat ${{ env.TEMP_DIR }}/created_pr_number.txt)
          echo "Adding label to PR #$pr_number"

          curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            -d '{"labels": ["milestone-merge"]}' \
            "https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels"

          echo "Added 'milestone-merge' label to PR #$pr_number."
