name: Start Fly Runner

on:
  workflow_call:
    outputs:
      runner-ready:
        description: "Whether the runner is ready"
        value: ${{ jobs.start-runner.outputs.runner-ready }}
      machine-id:
        description: "The Fly machine ID that was started"
        value: ${{ jobs.start-runner.outputs.machine-id }}
      runner-labels:
        description: "Labels to target the self-hosted runner"
        value: ${{ jobs.start-runner.outputs.runner-labels }}
      runner-name:
        description: "Resolved GitHub runner name"
        value: ${{ jobs.start-runner.outputs.runner-name }}

env:
  FLY_RUNNER_APP: ivysaur
  FLY_RUNNER_REGION: iad
  FLY_RUNNER_IMAGE: registry.fly.io/ivysaur:latest

jobs:
  start-runner:
    name: Start Fly Runner
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
    outputs:
      runner-ready: ${{ steps.wait-for-runner.outputs.ready }}
      machine-id: ${{ steps.machine-management.outputs.machine-id }}
      runner-labels: ${{ steps.generate-labels.outputs.labels }}
      runner-name: ${{ steps.wait-for-runner.outputs.runner-name }}

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

      - name: Generate unique runner labels
        id: generate-labels
        run: |
          UNIQUE_LABELS='"self-hosted","${{ github.run_id }}"'
          echo "Generated unique labels: $UNIQUE_LABELS"
          echo "labels=$UNIQUE_LABELS" >> "$GITHUB_OUTPUT"

      - name: Setup Fly CLI
        uses: superfly/flyctl-actions/setup-flyctl@master

      - name: Get Fly app info
        id: get-app-info
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN_TESTING }}
        run: |
          echo "Getting app info for ${FLY_RUNNER_APP}..."
          flyctl status -a "${FLY_RUNNER_APP}"

      - name: Set GH_TOKEN in Fly secrets
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN_TESTING }}
        run: |
          echo "Setting GH_TOKEN in Fly secrets..."
          flyctl secrets set GH_TOKEN="${{ secrets.GH_TOKEN_ACTIONS }}" -a "${FLY_RUNNER_APP}"

      - name: Create Fly machine
        id: machine-management
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN_TESTING }}
        run: |
          set -euo pipefail

          # Always create a fresh ephemeral machine
          FULL_OUTPUT=$(flyctl machines run "${FLY_RUNNER_IMAGE}" \
            -a "${FLY_RUNNER_APP}" \
            --region "${FLY_RUNNER_REGION}" \
            --env RUN_ID=${{ github.run_id }} \
            --env TEST_TYPE="honcho-unified-runner" \
            --vm-size shared-cpu-8x \
            --vm-memory 8192 )

          MACHINE_ID=$(echo "$FULL_OUTPUT" | grep "Machine ID:" | awk '{print $3}')
          echo "Created machine: $MACHINE_ID"
          echo "machine-id=$MACHINE_ID" >> "$GITHUB_OUTPUT"

      - name: Wait for runner to be online
        id: wait-for-runner
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN_ACTIONS }}
          MAX_WAIT: 420
        run: |
          set -euo pipefail
          if [ -z "${GITHUB_TOKEN}" ]; then
            echo "GH_TOKEN secret is required to poll the Actions runner API."
            exit 1
          fi

          EXPECTED_RUNNER_NAME="honcho-unified-runner-${{ github.run_id }}"
          echo "Waiting for runner named ${EXPECTED_RUNNER_NAME} to come online..."

          WAITED=0
          RUNNER_NAME=""
          while [ $WAITED -lt $MAX_WAIT ]; do
            RESPONSE=$(curl -s \
              -H "Authorization: Bearer ${GITHUB_TOKEN}" \
              -H "Accept: application/vnd.github.v3+json" \
              "https://api.github.com/repos/${{ github.repository }}/actions/runners")

            if echo "$RESPONSE" | grep -q '"message"'; then
              echo "API Error: $(echo "$RESPONSE" | jq -r '.message')"
              exit 1
            fi

            # Find runner with exact name and is online and not busy
            RUNNER_LINE=$(echo "$RESPONSE" | jq -r --arg runner_name "$EXPECTED_RUNNER_NAME" '.runners[]? | select(.name == $runner_name) | select(.status == "online") | select(.busy == false) | "\(.name)|\(.id)"' | head -n 1)

            if [ -n "$RUNNER_LINE" ]; then
              RUNNER_NAME=$(echo "$RUNNER_LINE" | cut -d'|' -f1)
              echo "✅ Found runner: ${RUNNER_NAME}"
              echo "ready=true" >> "$GITHUB_OUTPUT"
              echo "runner-name=${RUNNER_NAME}" >> "$GITHUB_OUTPUT"
              exit 0
            fi

            echo "⏳ Waiting for runner... (${WAITED}s elapsed)"
            sleep 15
            WAITED=$((WAITED + 15))
          done

          echo "Runner failed to come online within ${MAX_WAIT} seconds"
          echo "ready=false" >> "$GITHUB_OUTPUT"
          exit 1
