name: Merge-forward skill branches

on:
  push:
    branches: [main]

permissions:
  contents: write
  issues: write

jobs:
  merge-forward:
    if: github.repository == 'qwibitai/nanoclaw'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Configure git
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"

      - name: Merge main into each skill branch
        id: merge
        run: |
          FAILED=""
          SUCCEEDED=""

          # List all remote skill branches
          SKILL_BRANCHES=$(git branch -r --list 'origin/skill/*' | sed 's|origin/||' | xargs)

          if [ -z "$SKILL_BRANCHES" ]; then
            echo "No skill branches found."
            exit 0
          fi

          for BRANCH in $SKILL_BRANCHES; do
            SKILL_NAME=$(echo "$BRANCH" | sed 's|skill/||')
            echo ""
            echo "=== Processing $BRANCH ==="

            # Checkout the skill branch
            git checkout -B "$BRANCH" "origin/$BRANCH"

            # Attempt merge
            if ! git merge main --no-edit; then
              echo "::warning::Merge conflict in $BRANCH"
              git merge --abort
              FAILED="$FAILED $SKILL_NAME"
              continue
            fi

            # Check if there's anything new to push
            if git diff --quiet "origin/$BRANCH"; then
              echo "$BRANCH is already up to date with main."
              SUCCEEDED="$SUCCEEDED $SKILL_NAME"
              continue
            fi

            # Install deps and validate
            npm ci

            if ! npm run build; then
              echo "::warning::Build failed for $BRANCH"
              git reset --hard "origin/$BRANCH"
              FAILED="$FAILED $SKILL_NAME"
              continue
            fi

            if ! npm test 2>/dev/null; then
              echo "::warning::Tests failed for $BRANCH"
              git reset --hard "origin/$BRANCH"
              FAILED="$FAILED $SKILL_NAME"
              continue
            fi

            # Push the updated branch
            git push origin "$BRANCH"
            SUCCEEDED="$SUCCEEDED $SKILL_NAME"
            echo "$BRANCH merged and pushed successfully."
          done

          echo ""
          echo "=== Results ==="
          echo "Succeeded: $SUCCEEDED"
          echo "Failed: $FAILED"

          # Export for issue creation
          echo "failed=$FAILED" >> "$GITHUB_OUTPUT"
          echo "succeeded=$SUCCEEDED" >> "$GITHUB_OUTPUT"

      - name: Open issue for failed merges
        if: steps.merge.outputs.failed != ''
        uses: actions/github-script@v7
        with:
          script: |
            const failed = '${{ steps.merge.outputs.failed }}'.trim().split(/\s+/);
            const sha = context.sha.substring(0, 7);
            const body = [
              `The merge-forward workflow failed to merge \`main\` (${sha}) into the following skill branches:`,
              '',
              ...failed.map(s => `- \`skill/${s}\`: merge conflict, build failure, or test failure`),
              '',
              'Please resolve manually:',
              '```bash',
              ...failed.map(s => [
                `git checkout skill/${s}`,
                `git merge main`,
                `# resolve conflicts, then: git push`,
                ''
              ]).flat(),
              '```',
              '',
              `Triggered by push to main: ${context.sha}`
            ].join('\n');

            await github.rest.issues.create({
              owner: context.repo.owner,
              repo: context.repo.repo,
              title: `Merge-forward failed for ${failed.length} skill branch(es) after ${sha}`,
              body,
              labels: ['skill-maintenance']
            });

      - name: Notify channel forks
        if: always()
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.FORK_DISPATCH_TOKEN || secrets.GITHUB_TOKEN }}
          script: |
            const forks = [
              'nanoclaw-whatsapp',
              'nanoclaw-telegram',
              'nanoclaw-discord',
              'nanoclaw-slack',
              'nanoclaw-gmail',
            ];
            const sha = context.sha.substring(0, 7);
            for (const repo of forks) {
              try {
                await github.rest.repos.createDispatchEvent({
                  owner: 'qwibitai',
                  repo,
                  event_type: 'upstream-main-updated',
                  client_payload: { sha: context.sha },
                });
                console.log(`Notified ${repo}`);
              } catch (e) {
                console.log(`Failed to notify ${repo}: ${e.message}`);
              }
            }
