name: Scheduled Updates (Firmware, Hardware, Translations)

on:
  schedule:
    - cron: '0 */4 * * *' # Run every 4 hours (was hourly — reduced to cut cascade CI cost)
  workflow_dispatch:       # Allow manual triggering

jobs:
  update_assets:
    runs-on: ubuntu-24.04
    if: github.repository == 'meshtastic/Meshtastic-Android'
    permissions:
      contents: write      # To commit files and push branches
      pull-requests: write # To create pull requests

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          token: ${{ secrets.CROWDIN_GITHUB_TOKEN }}

      - name: Update firmware releases list
        id: firmware
        run: |
          firmware_file_path="app/src/main/assets/firmware_releases.json"
          temp_firmware_file="/tmp/new_firmware_releases.json"

          echo "Fetching latest firmware releases..."
          http_code=$(curl -s -o "$temp_firmware_file" -w '%{http_code}' https://api.meshtastic.org/github/firmware/list || true)
          http_code="${http_code:-0}"

          if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "::warning::Firmware API returned HTTP $http_code. Skipping firmware update."
            echo "status=error" >> "$GITHUB_OUTPUT"
            echo "detail=HTTP $http_code from firmware API" >> "$GITHUB_OUTPUT"
          elif ! jq empty "$temp_firmware_file" 2>/dev/null; then
            echo "::warning::Firmware API returned invalid JSON data. Skipping firmware update."
            echo "status=error" >> "$GITHUB_OUTPUT"
            echo "detail=Invalid JSON response from firmware API" >> "$GITHUB_OUTPUT"
          else
            if [ ! -f "$firmware_file_path" ] || ! jq --sort-keys . "$temp_firmware_file" | diff -q - <(jq --sort-keys . "$firmware_file_path"); then
              echo "Changes detected in firmware list or local file missing. Updating $firmware_file_path."
              cp "$temp_firmware_file" "$firmware_file_path"
              echo "status=updated" >> "$GITHUB_OUTPUT"
            else
              echo "No changes detected in firmware list."
              echo "status=unchanged" >> "$GITHUB_OUTPUT"
            fi
          fi

      - name: Update hardware list
        id: hardware
        run: |
          hardware_file_path="app/src/main/assets/device_hardware.json"
          temp_hardware_file="/tmp/new_device_hardware.json"

          echo "Fetching latest device hardware data..."
          http_code=$(curl -s -o "$temp_hardware_file" -w '%{http_code}' https://api.meshtastic.org/resource/deviceHardware || true)
          http_code="${http_code:-0}"

          if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "::warning::Hardware API returned HTTP $http_code. Skipping hardware update."
            echo "status=error" >> "$GITHUB_OUTPUT"
            echo "detail=HTTP $http_code from hardware API" >> "$GITHUB_OUTPUT"
          elif ! jq empty "$temp_hardware_file" 2>/dev/null; then
            echo "::warning::Hardware API returned invalid JSON data. Skipping hardware update."
            echo "status=error" >> "$GITHUB_OUTPUT"
            echo "detail=Invalid JSON response from hardware API" >> "$GITHUB_OUTPUT"
          else
            if [ ! -f "$hardware_file_path" ] || ! jq --sort-keys . "$temp_hardware_file" | diff -q - <(jq --sort-keys . "$hardware_file_path"); then
              echo "Changes detected in hardware list or local file missing. Updating $hardware_file_path."
              cp "$temp_hardware_file" "$hardware_file_path"
              echo "status=updated" >> "$GITHUB_OUTPUT"
            else
              echo "No changes detected in hardware list."
              echo "status=unchanged" >> "$GITHUB_OUTPUT"
            fi
          fi

      - name: Sync with Crowdin
        uses: crowdin/github-action@v2
        with:
          base_url: 'https://meshtastic.crowdin.com/api/v2'
          config: 'crowdin.yml'
          crowdin_branch_name: 'main'
          upload_sources: true
          upload_sources_args: '--preserve-hierarchy'
          upload_translations: false
          download_translations: true
          download_translations_args: '--preserve-hierarchy'
          create_pull_request: false
          commit_message: 'chore(l10n): New Crowdin Translations from scheduled update'
          push_translations: false
          push_sources: false
          localization_branch_name: ${{ github.ref_name }}
        env:
          GITHUB_TOKEN: ${{ secrets.CROWDIN_GITHUB_TOKEN }}
          CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
          CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

      - name: Fix file permissions
        run: sudo chown -R $USER:$USER .

      - name: Gradle Setup
        uses: ./.github/actions/gradle-setup
        with:
          gradle_encryption_key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
          cache_read_only: 'false'

      - name: Update Graphs
        run: ./gradlew graphUpdate
        continue-on-error: true


      - name: Build PR body
        id: pr_body
        run: |
          firmware_status="${{ steps.firmware.outputs.status }}"
          firmware_detail="${{ steps.firmware.outputs.detail }}"
          hardware_status="${{ steps.hardware.outputs.status }}"
          hardware_detail="${{ steps.hardware.outputs.detail }}"

          body="This PR includes automated updates from the scheduled workflow:"
          body+=$'\n'

          # Firmware status
          case "$firmware_status" in
            updated)   body+=$'\n'"- ✅ \`firmware_releases.json\` updated from the Meshtastic API." ;;
            unchanged) body+=$'\n'"- ✔️ \`firmware_releases.json\` checked — no changes detected." ;;
            error)     body+=$'\n'"- ⚠️ \`firmware_releases.json\` skipped — ${firmware_detail}." ;;
            *)         body+=$'\n'"- ❓ \`firmware_releases.json\` — unknown status." ;;
          esac

          # Hardware status
          case "$hardware_status" in
            updated)   body+=$'\n'"- ✅ \`device_hardware.json\` updated from the Meshtastic API." ;;
            unchanged) body+=$'\n'"- ✔️ \`device_hardware.json\` checked — no changes detected." ;;
            error)     body+=$'\n'"- ⚠️ \`device_hardware.json\` skipped — ${hardware_detail}." ;;
            *)         body+=$'\n'"- ❓ \`device_hardware.json\` — unknown status." ;;
          esac

          # Crowdin & graphs (always attempted)
          body+=$'\n'"- Source strings were uploaded to Crowdin."
          body+=$'\n'"- Latest translations were downloaded from Crowdin (if available)."
          body+=$'\n'"- Updated module dependency graphs in README.md files (if changed)."
          body+=$'\n'
          body+=$'\n'"Please review the changes."

          # Write multi-line body to output
          {
            echo "content<<PREOF"
            echo "$body"
            echo "PREOF"
          } >> "$GITHUB_OUTPUT"

      - name: Create Pull Request if changes occurred
        uses: peter-evans/create-pull-request@v8
        with:
          token: ${{ secrets.CROWDIN_GITHUB_TOKEN }}
          commit-message: |
            chore: Scheduled updates (Firmware, Hardware, Translations, Graphs)

            Automated updates for:
            - Firmware releases list
            - Device hardware list
            - Crowdin source string uploads
            - Crowdin translation downloads
            - Module dependency graphs
          title: 'chore: Scheduled updates (Firmware, Hardware, Translations, Graphs)'
          body: ${{ steps.pr_body.outputs.content }}
          branch: 'scheduled-updates'
          base: 'main'
          delete-branch: true
          add-paths: |
            app/src/main/assets/firmware_releases.json
            app/src/main/assets/device_hardware.json
            fastlane/metadata/android/**
            **/strings.xml
            **/README.md
          labels: |
            automation
            l10n
            firmware
            hardware

  check-workflow-status:
    name: Check Workflow Status
    runs-on: ubuntu-24.04-arm
    permissions: {}
    needs:
        - update_assets
    if: always()
    steps:
      - name: Check Workflow Status
        if: "contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')"
        run: |
          echo "One of the dependent jobs failed or was cancelled. Failing the workflow."
          exit 1
