# CI/CDパイプライン サンプル — 非同期バッチ処理テストパターン
#
# フロー:
#   1. テストA実行 → ボタンクリックでバッチ処理を開始、Job IDを取得
#   2. バッチ完了待ち → ステータスAPIをポーリングして完了を検知
#   3. テストB実行 → Job IDを渡してDB検証テストを実行

name: Async Batch Test Pipeline

on:
  workflow_dispatch:
  schedule:
    - cron: '0 1 * * *'   # 毎日 01:00 UTC に実行

env:
  MABL_API_KEY: ${{ secrets.MABL_API_KEY }}
  APP_BASE_URL: ${{ vars.APP_BASE_URL }}
  # バッチステータスを返すAPIのベースURL（実際のアプリに合わせて変更）
  BATCH_STATUS_API: ${{ vars.BATCH_STATUS_API_URL }}

jobs:

  # -----------------------------------------------------------------------
  # Job 1: テストA — バッチ処理をトリガーして Job ID を取得
  # -----------------------------------------------------------------------
  run-test-a:
    name: "テストA: バッチ処理のトリガー"
    runs-on: ubuntu-latest
    outputs:
      job_id: ${{ steps.extract-job-id.outputs.job_id }}

    steps:
      - name: mabl テストAを実行
        id: run-mabl-test-a
        run: |
          # mabl Run API でテストAを実行（環境変数でAPP_URLを渡す）
          RESPONSE=$(curl -s -X POST \
            -H "Authorization: Basic $(echo -n "key:${MABL_API_KEY}" | base64)" \
            -H "Content-Type: application/json" \
            -d '{
              "plan_labels": ["test-a", "batch-trigger"],
              "environment_id": "${{ vars.MABL_ENVIRONMENT_ID }}",
              "properties": {
                "app_base_url": "${{ env.APP_BASE_URL }}"
              }
            }' \
            "https://api.mabl.com/execution/runplan")

          echo "API Response: ${RESPONSE}"

          RUN_ID=$(echo "${RESPONSE}" | jq -r '.run_id // empty')
          if [ -z "${RUN_ID}" ]; then
            echo "Error: Failed to start mabl test run"
            exit 1
          fi
          echo "run_id=${RUN_ID}" >> $GITHUB_OUTPUT

      - name: テストAの完了を待機
        id: wait-test-a
        run: |
          RUN_ID="${{ steps.run-mabl-test-a.outputs.run_id }}"
          MAX_WAIT=300   # 最大5分
          INTERVAL=10
          ELAPSED=0

          while [ $ELAPSED -lt $MAX_WAIT ]; do
            STATUS=$(curl -s \
              -H "Authorization: Basic $(echo -n "key:${MABL_API_KEY}" | base64)" \
              "https://api.mabl.com/execution/run/${RUN_ID}/result" \
              | jq -r '.status // "running"')

            echo "テストA ステータス: ${STATUS} (${ELAPSED}s 経過)"

            if [ "${STATUS}" = "succeeded" ]; then
              echo "テストA 完了"
              break
            elif [ "${STATUS}" = "failed" ] || [ "${STATUS}" = "terminated" ]; then
              echo "テストA 失敗: status=${STATUS}"
              exit 1
            fi

            sleep $INTERVAL
            ELAPSED=$((ELAPSED + INTERVAL))
          done

          if [ $ELAPSED -ge $MAX_WAIT ]; then
            echo "Error: テストAがタイムアウトしました"
            exit 1
          fi

      - name: テストAの出力から Job ID を抽出
        id: extract-job-id
        run: |
          # mabl の出力変数または画面から取得した Job ID
          # ここでは mabl のカスタム出力変数 "batchJobId" を参照する例を示します
          # 詳細: https://help.mabl.com/docs/using-variables-in-tests
          RUN_ID="${{ steps.run-mabl-test-a.outputs.run_id }}"

          JOB_ID=$(curl -s \
            -H "Authorization: Basic $(echo -n "key:${MABL_API_KEY}" | base64)" \
            "https://api.mabl.com/execution/run/${RUN_ID}/variables" \
            | jq -r '.output_variables.batchJobId // empty')

          if [ -z "${JOB_ID}" ]; then
            echo "Warning: Job ID が取得できませんでした。デフォルト値を使用します"
            JOB_ID="BATCH-$(date +%Y%m%d)-001"
          fi

          echo "Job ID: ${JOB_ID}"
          echo "job_id=${JOB_ID}" >> $GITHUB_OUTPUT

  # -----------------------------------------------------------------------
  # Job 2: バッチ完了待ち — ステータスAPIをポーリング
  # -----------------------------------------------------------------------
  wait-for-batch:
    name: "バッチ処理完了待ち"
    runs-on: ubuntu-latest
    needs: run-test-a
    outputs:
      job_id: ${{ needs.run-test-a.outputs.job_id }}

    steps:
      - name: バッチ処理ステータスをポーリング
        run: |
          JOB_ID="${{ needs.run-test-a.outputs.job_id }}"
          MAX_WAIT=900   # 最大15分
          INTERVAL=30    # 30秒ごとに確認
          ELAPSED=0

          echo "バッチ処理の完了を待機中... Job ID: ${JOB_ID}"

          while [ $ELAPSED -lt $MAX_WAIT ]; do
            # ステータスAPIを呼び出してバッチの状態を取得
            # 実際のAPIエンドポイントに合わせてURLとレスポンス構造を変更してください
            RESPONSE=$(curl -s \
              -H "Authorization: Bearer ${{ secrets.APP_API_TOKEN }}" \
              "${BATCH_STATUS_API}/status?jobId=${JOB_ID}")

            STATUS=$(echo "${RESPONSE}" | jq -r '.status // "unknown"')
            PROGRESS=$(echo "${RESPONSE}" | jq -r '.progress // 0')

            echo "[$(date '+%H:%M:%S')] ステータス: ${STATUS}, 進捗: ${PROGRESS}% (${ELAPSED}s 経過)"

            case "${STATUS}" in
              "done" | "completed" | "succeeded")
                echo "バッチ処理完了!"
                RECORDS=$(echo "${RESPONSE}" | jq -r '.recordsProcessed // "unknown"')
                echo "処理件数: ${RECORDS}"
                exit 0
                ;;
              "error" | "failed")
                echo "バッチ処理エラー: $(echo "${RESPONSE}" | jq -r '.message // "不明なエラー"')"
                exit 1
                ;;
              "processing" | "running" | "pending")
                # 処理中 — 待機を継続
                ;;
              *)
                echo "Warning: 不明なステータス '${STATUS}'"
                ;;
            esac

            sleep $INTERVAL
            ELAPSED=$((ELAPSED + INTERVAL))
          done

          echo "Error: バッチ処理がタイムアウトしました (${MAX_WAIT}s)"
          exit 1

  # -----------------------------------------------------------------------
  # Job 3: テストB — バッチ結果をmablで検証
  # -----------------------------------------------------------------------
  run-test-b:
    name: "テストB: バッチ処理結果の検証"
    runs-on: ubuntu-latest
    needs: wait-for-batch

    steps:
      - name: mabl テストBを実行
        id: run-mabl-test-b
        run: |
          JOB_ID="${{ needs.wait-for-batch.outputs.job_id }}"
          echo "テストBを実行します (Job ID: ${JOB_ID})"

          # Job ID をデプロイメント変数としてテストBに渡す
          RESPONSE=$(curl -s -X POST \
            -H "Authorization: Basic $(echo -n "key:${MABL_API_KEY}" | base64)" \
            -H "Content-Type: application/json" \
            -d "{
              \"plan_labels\": [\"test-b\", \"batch-verify\"],
              \"environment_id\": \"${{ vars.MABL_ENVIRONMENT_ID }}\",
              \"properties\": {
                \"app_base_url\": \"${{ env.APP_BASE_URL }}\",
                \"batch_job_id\": \"${JOB_ID}\"
              }
            }" \
            "https://api.mabl.com/execution/runplan")

          echo "API Response: ${RESPONSE}"

          RUN_ID=$(echo "${RESPONSE}" | jq -r '.run_id // empty')
          if [ -z "${RUN_ID}" ]; then
            echo "Error: テストBの開始に失敗しました"
            exit 1
          fi
          echo "run_id=${RUN_ID}" >> $GITHUB_OUTPUT

      - name: テストBの完了を待機
        run: |
          RUN_ID="${{ steps.run-mabl-test-b.outputs.run_id }}"
          MAX_WAIT=300
          INTERVAL=10
          ELAPSED=0

          while [ $ELAPSED -lt $MAX_WAIT ]; do
            STATUS=$(curl -s \
              -H "Authorization: Basic $(echo -n "key:${MABL_API_KEY}" | base64)" \
              "https://api.mabl.com/execution/run/${RUN_ID}/result" \
              | jq -r '.status // "running"')

            echo "テストB ステータス: ${STATUS} (${ELAPSED}s 経過)"

            if [ "${STATUS}" = "succeeded" ]; then
              echo "テストB 完了 — 全検証チェック合格"
              exit 0
            elif [ "${STATUS}" = "failed" ] || [ "${STATUS}" = "terminated" ]; then
              echo "テストB 失敗: バッチ処理結果の検証に失敗しました"
              exit 1
            fi

            sleep $INTERVAL
            ELAPSED=$((ELAPSED + INTERVAL))
          done

          echo "Error: テストBがタイムアウトしました"
          exit 1

      - name: テスト結果サマリーを出力
        if: always()
        run: |
          JOB_ID="${{ needs.wait-for-batch.outputs.job_id }}"
          echo "========================================"
          echo "  パイプライン実行結果"
          echo "========================================"
          echo "  Job ID    : ${JOB_ID}"
          echo "  テストA   : ${{ needs.run-test-a.result }}"
          echo "  バッチ待ち: ${{ needs.wait-for-batch.result }}"
          echo "  テストB   : ${{ job.status }}"
          echo "========================================"
