name: Sync upstream

on:
  schedule:
    - cron: "0 3 * * *"
  workflow_dispatch:
    inputs:
      target_commit:
        description: 'Commit hash (leave blank to use latest commit)'
        required: false
        type: string

permissions:
  contents: write

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      - name: Add upstream
        run: |
          git remote add upstream https://github.com/shuaiplus/NodeWarden.git || true
          git fetch upstream --tags

      - name: Resolve target commit
        id: resolve
        run: |
          TRIGGER="${{ github.event_name }}"
          MANUAL_INPUT="${{ github.event.inputs.target_commit }}"

          if [ "$TRIGGER" = "schedule" ]; then
            # Auto mode: resolve latest upstream release tag
            LATEST_TAG=$(curl -s https://api.github.com/repos/shuaiplus/NodeWarden/releases/latest | jq -r .tag_name)
            if [ "$LATEST_TAG" = "null" ] || [ -z "$LATEST_TAG" ]; then
              echo "No release found in upstream."
              exit 1
            fi
            TARGET_SHA=$(git rev-list -n 1 "$LATEST_TAG" 2>/dev/null)
            if [ -z "$TARGET_SHA" ]; then
              echo "Tag '$LATEST_TAG' not found after fetch."
              exit 1
            fi
            echo "mode=auto" >> $GITHUB_OUTPUT
            echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
            echo "target_sha=$TARGET_SHA" >> $GITHUB_OUTPUT
            echo "Auto mode — latest release: $LATEST_TAG ($TARGET_SHA)"

          elif [ -n "$MANUAL_INPUT" ]; then
            # Manual mode: use provided commit hash or tag
            TARGET_SHA=$(git rev-parse "$MANUAL_INPUT" 2>/dev/null)
            if [ -z "$TARGET_SHA" ]; then
              echo "Cannot resolve '$MANUAL_INPUT' to a commit."
              exit 1
            fi
            echo "mode=manual" >> $GITHUB_OUTPUT
            echo "target_sha=$TARGET_SHA" >> $GITHUB_OUTPUT
            echo "Manual mode — target: $MANUAL_INPUT ($TARGET_SHA)"

          else
            # Manual mode, blank input: use latest commit on upstream/main
            TARGET_SHA=$(git rev-parse upstream/main)
            echo "mode=manual" >> $GITHUB_OUTPUT
            echo "target_sha=$TARGET_SHA" >> $GITHUB_OUTPUT
            echo "Manual mode — latest commit: $TARGET_SHA"
          fi

      - name: Check if update is needed
        id: check
        run: |
          TARGET_SHA="${{ steps.resolve.outputs.target_sha }}"
          MODE="${{ steps.resolve.outputs.mode }}"

          if [ "$MODE" = "manual" ]; then
            # Manual: skip only if HEAD is exactly this commit
            CURRENT_SHA=$(git rev-parse HEAD)
            if [ "$CURRENT_SHA" = "$TARGET_SHA" ]; then
              echo "Already at $TARGET_SHA — skipping."
              echo "needs_update=false" >> $GITHUB_OUTPUT
            else
              echo "Switching to $TARGET_SHA"
              echo "needs_update=true" >> $GITHUB_OUTPUT
            fi
          else
            # Auto: skip if target is already in ancestry
            if git merge-base --is-ancestor "$TARGET_SHA" HEAD 2>/dev/null; then
              echo "Already up to date with $TARGET_SHA — skipping."
              echo "needs_update=false" >> $GITHUB_OUTPUT
            else
              echo "Update needed — target: $TARGET_SHA"
              echo "needs_update=true" >> $GITHUB_OUTPUT
            fi
          fi

      - name: Apply update
        if: steps.check.outputs.needs_update == 'true'
        run: |
          TARGET_SHA="${{ steps.resolve.outputs.target_sha }}"
          MODE="${{ steps.resolve.outputs.mode }}"
          git checkout main
          if [ "$MODE" = "manual" ]; then
            # Hard reset allows both upgrade and rollback
            git reset --hard "$TARGET_SHA"
          else
            git merge "$TARGET_SHA" --no-edit
          fi

      - name: Restore workflow file
        if: steps.check.outputs.needs_update == 'true'
        run: |
          # Always keep our own workflow file, never let upstream overwrite it
          git checkout HEAD@{1} -- .github/workflows/sync-upstream.yml 2>/dev/null || true
          if ! git diff --cached --quiet; then
            git commit -m "chore: restore sync-upstream workflow after sync"
          fi

      - name: Push
        if: steps.check.outputs.needs_update == 'true'
        run: |
          if [ "${{ steps.resolve.outputs.mode }}" = "manual" ]; then
            git push origin main --force
          else
            git push origin main
          fi

      - name: Summary
        run: |
          if [ "${{ steps.check.outputs.needs_update }}" = "true" ]; then
            echo "### Synced successfully" >> $GITHUB_STEP_SUMMARY
            echo "- **Mode:** ${{ steps.resolve.outputs.mode }}" >> $GITHUB_STEP_SUMMARY
            echo "- **Tag:** ${{ steps.resolve.outputs.latest_tag || 'N/A (manual)' }}" >> $GITHUB_STEP_SUMMARY
            echo "- **Commit:** \`${{ steps.resolve.outputs.target_sha }}\`" >> $GITHUB_STEP_SUMMARY
          else
            echo "### Nothing to update" >> $GITHUB_STEP_SUMMARY
          fi
