name: CI/CD

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

permissions:
  contents: write
  pull-requests: write

jobs:
  setup:
    runs-on: ubuntu-latest
    outputs:
      flutter-version: ${{ steps.read.outputs.version }}
    steps:
      - uses: actions/checkout@v4
        with:
          sparse-checkout: .flutter-version
          sparse-checkout-cone-mode: false
      - id: read
        run: echo "version=$(cat .flutter-version | tr -d '[:space:]')" >> "$GITHUB_OUTPUT"

  lint:
    needs: setup
    runs-on: ubuntu-latest

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

      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: ${{ needs.setup.outputs.flutter-version }}
          cache: true

      - name: Cache pub dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.pub-cache
          key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
          restore-keys: pub-${{ runner.os }}-

      - name: Install dependencies
        run: flutter pub get

      - name: Verify formatting
        run: dart format --output=none --set-exit-if-changed .

      - name: Analyze project source
        run: flutter analyze --no-fatal-infos

  test:
    needs: setup
    runs-on: ubuntu-latest

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

      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: ${{ needs.setup.outputs.flutter-version }}
          cache: true

      - name: Cache pub dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.pub-cache
          key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
          restore-keys: pub-${{ runner.os }}-

      - name: Install dependencies
        run: flutter pub get

      - name: Run tests
        run: flutter test --coverage
      - name: Upload coverage
        uses: codecov/codecov-action@v4
        with:
          files: coverage/lcov.info
          fail_ci_if_error: false

  release-please:
    needs: [lint, test]
    if: github.event_name == 'push' && github.ref == 'refs/heads/master'
    uses: chenasraf/workflows/.github/workflows/release-please-fastlane-changelog.yml@master
    with:
      release-type: dart
      fastlane-changelog-dirs: |
        fastlane/metadata/android/en-US/changelogs
        fastlane/metadata/ios/en-US/changelogs

  build-android:
    needs: [setup, release-please]
    if: ${{ needs.release-please.outputs.release_created }}
    runs-on: ubuntu-latest

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

      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '17'
          cache: 'gradle'

      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: ${{ needs.setup.outputs.flutter-version }}
          cache: true

      - name: Cache pub dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.pub-cache
          key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
          restore-keys: pub-${{ runner.os }}-

      - name: Install dependencies
        run: flutter pub get

      - name: Remove JNI build-id for reproducible builds
        run: sed -i -e 's/-Wl,/-Wl,--build-id=none,/' $PUB_CACHE/hosted/pub.dev/jni-*/src/CMakeLists.txt

      - name: Decode keystore
        run: echo ${{ secrets.ANDROID_KEYSTORE_BASE64 }} | base64 -d > android/app/upload-keystore.jks

      - name: Create key.properties
        run: |
          cat > android/key.properties <<EOF
          storePassword=${{ secrets.ANDROID_STORE_PASSWORD }}
          keyPassword=${{ secrets.ANDROID_KEY_PASSWORD }}
          keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}
          storeFile=upload-keystore.jks
          EOF

      - name: Print signing key SHA-256
        run: |
          keytool -list -v -keystore android/app/upload-keystore.jks \
            -alias ${{ secrets.ANDROID_KEY_ALIAS }} \
            -storepass ${{ secrets.ANDROID_STORE_PASSWORD }} \
            2>/dev/null | grep "SHA256:" | awk '{print $2}'

      - name: Build split APKs
        run: flutter build apk --release --split-per-abi

      - name: Strip dependency metadata from APKs
        run: |
          pip install apksigtool
          APK_DIR=build/app/outputs/flutter-apk
          for apk in $APK_DIR/app-*-release.apk; do
            python3 -m apksigtool remove-signing-block --block-id 0x504b4453 "$apk"
          done

      - name: Build App Bundle
        run: flutter build appbundle --release --obfuscate --split-debug-info=build/debug-info-aab
      - name: Rename artifacts
        run: |
          VERSION=${{ needs.release-please.outputs.version }}
          APK_DIR=build/app/outputs/flutter-apk
          mv ${APK_DIR}/app-armeabi-v7a-release.apk ${APK_DIR}/pantry-${VERSION}-armeabi-v7a.apk
          mv ${APK_DIR}/app-arm64-v8a-release.apk ${APK_DIR}/pantry-${VERSION}-arm64-v8a.apk
          mv ${APK_DIR}/app-x86_64-release.apk ${APK_DIR}/pantry-${VERSION}-x86_64.apk
          mv build/app/outputs/bundle/release/app-release.aab build/app/outputs/bundle/release/pantry-${VERSION}.aab

      - name: Upload APKs to release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.release-please.outputs.tag_name }}
          files: |
            build/app/outputs/flutter-apk/pantry-${{ needs.release-please.outputs.version }}-armeabi-v7a.apk
            build/app/outputs/flutter-apk/pantry-${{ needs.release-please.outputs.version }}-arm64-v8a.apk
            build/app/outputs/flutter-apk/pantry-${{ needs.release-please.outputs.version }}-x86_64.apk

      - name: Upload App Bundle to release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.release-please.outputs.tag_name }}
          files: |
            build/app/outputs/bundle/release/pantry-${{ needs.release-please.outputs.version }}.aab

  build-ios:
    needs: [setup, release-please]
    if: false # TEMPORARILY DISABLED — was: ${{ needs.release-please.outputs.release_created }}
    runs-on: macos-latest

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

      - name: Setup Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: ${{ needs.setup.outputs.flutter-version }}
          cache: true

      - name: Cache pub dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.pub-cache
          key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
          restore-keys: pub-${{ runner.os }}-

      - name: Cache CocoaPods
        uses: actions/cache@v4
        with:
          path: |
            ios/Pods
            ~/.cocoapods
          key: pods-${{ runner.os }}-${{ hashFiles('ios/Podfile') }}
          restore-keys: pods-${{ runner.os }}-

      - name: Install dependencies
        run: flutter pub get

      - name: Build iOS (no codesign)
        run: flutter build ios --release --no-codesign --obfuscate --split-debug-info=build/debug-info-ios
      - name: Create unsigned IPA
        run: |
          mkdir -p build/ios/ipa
          cd build/ios/iphoneos
          mkdir -p Payload
          cp -r Runner.app Payload/
          zip -r ../ipa/pantry-${{ needs.release-please.outputs.version }}-unsigned.ipa Payload

      - name: Upload IPA to release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.release-please.outputs.tag_name }}
          files: |
            build/ios/ipa/pantry-${{ needs.release-please.outputs.version }}-unsigned.ipa

  post-release-comment:
    needs: [release-please, build-android]
    if: ${{ needs.release-please.outputs.release_created }}
    runs-on: ubuntu-latest

    steps:
      - name: Comment on release PR with asset links
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          TAG="${{ needs.release-please.outputs.tag_name }}"
          VERSION="${{ needs.release-please.outputs.version }}"
          REPO="${{ github.repository }}"

          ASSETS=$(gh release view "$TAG" --repo "$REPO" --json assets --jq '.assets[].name')

          ROWS=""
          for ASSET in $ASSETS; do
            URL="https://github.com/${REPO}/releases/download/${TAG}/${ASSET}"
            ROWS="${ROWS}| ${ASSET} | [Download](${URL}) |
          "
          done

          BODY="## Release Assets — ${TAG}

          | File | Link |
          |------|------|
          ${ROWS}"

          PR_NUMBER=$(gh pr list --state merged --json number,title --repo "$REPO" \
            --jq "[.[] | select(.title == \"chore(master): release ${VERSION}\")] | .[0].number")

          if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ]; then
            echo "No release PR found, skipping comment"
            exit 0
          fi

          echo "Found release PR #${PR_NUMBER}"
          gh pr comment "$PR_NUMBER" --repo "$REPO" --body "$BODY"
