name: Version and Release

on:
  push:
    branches: [ main ]
    paths-ignore:
      - '**.md'
      - '.gitea/**'
      - '.drone.yml'

jobs:
  version-bump:
    runs-on: ubuntu-latest
    outputs:
      new_version: ${{ steps.version.outputs.new_version }}
      version_changed: ${{ steps.version.outputs.version_changed }}
      component_changed: ${{ steps.version.outputs.component_changed }}
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          token: ${{ secrets.GITEA_TOKEN || github.token }}
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Configure Git
        run: |
          git config --global user.name 'Gitea Actions Bot'
          git config --global user.email 'actions@gitea.local'
      
      - name: Detect changes and bump version
        id: version
        run: |
          set -e  # Exit on error
          
          echo "=== Debug Info ==="
          echo "GitHub event before: ${{ github.event.before }}"
          echo "GitHub SHA: ${{ github.sha }}"
          echo "Current directory: $(pwd)"
          echo "Git log (last 5): $(git log --oneline -5)"
          
          # Get the commit range for changed files
          if [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ] && [ "${{ github.event.before }}" != "" ]; then
            COMMIT_RANGE="${{ github.event.before }}..${{ github.sha }}"
            echo "Using commit range: $COMMIT_RANGE"
            CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE || echo "")
          else
            # First commit or no previous commit, check against HEAD~1 if it exists
            if git rev-parse HEAD~1 >/dev/null 2>&1; then
              COMMIT_RANGE="HEAD~1..HEAD"
              echo "Using commit range: $COMMIT_RANGE"
              CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE || echo "")
            else
              echo "First commit detected, checking all files"
              CHANGED_FILES=$(git ls-files)
            fi
          fi
          
          echo "Changed files:"
          echo "$CHANGED_FILES"
          
          # Check what changed (using echo to pipe to grep to avoid grep exit codes)
          BACKEND_CHANGED=$(echo "$CHANGED_FILES" | grep -c '^backend/' || echo "0")
          FRONTEND_CHANGED=$(echo "$CHANGED_FILES" | grep -c '^frontend/' || echo "0")
          ROOT_CHANGED=$(echo "$CHANGED_FILES" | grep -c -E '^(package\.json|docker-compose|Dockerfile|scripts/)' || echo "0")
          
          echo "Backend files changed: $BACKEND_CHANGED"
          echo "Frontend files changed: $FRONTEND_CHANGED"
          echo "Root files changed: $ROOT_CHANGED"
          
          # Get current versions
          BACKEND_VERSION=$(node -p "require('./backend/package.json').version" 2>/dev/null || echo "1.0.0")
          FRONTEND_VERSION=$(node -p "require('./frontend/package.json').version" 2>/dev/null || echo "1.0.0")
          
          echo "Current backend version: $BACKEND_VERSION"
          echo "Current frontend version: $FRONTEND_VERSION"
          
          # Determine what to update based on changes
          BACKEND_UPDATE=false
          FRONTEND_UPDATE=false
          COMPONENT_CHANGED="none"
          
          if [ "$ROOT_CHANGED" -gt 0 ]; then
            # Root changes affect both components
            BACKEND_UPDATE=true
            FRONTEND_UPDATE=true
            COMPONENT_CHANGED="both"
            SOURCE_VERSION=$BACKEND_VERSION
            echo "Root changes detected - updating both components"
          elif [ "$BACKEND_CHANGED" -gt 0 ] && [ "$FRONTEND_CHANGED" -gt 0 ]; then
            # Both components changed
            BACKEND_UPDATE=true
            FRONTEND_UPDATE=true
            COMPONENT_CHANGED="both"
            # Use the higher version as source
            if [ "$(printf '%s\n' "$BACKEND_VERSION" "$FRONTEND_VERSION" | sort -V | tail -n1)" = "$BACKEND_VERSION" ]; then
              SOURCE_VERSION=$BACKEND_VERSION
            else
              SOURCE_VERSION=$FRONTEND_VERSION
            fi
            echo "Both backend and frontend changed - updating both"
          elif [ "$BACKEND_CHANGED" -gt 0 ]; then
            # Only backend changed
            BACKEND_UPDATE=true
            COMPONENT_CHANGED="backend"
            SOURCE_VERSION=$BACKEND_VERSION
            echo "Only backend changed - updating backend"
          elif [ "$FRONTEND_CHANGED" -gt 0 ]; then
            # Only frontend changed
            FRONTEND_UPDATE=true
            COMPONENT_CHANGED="frontend"
            SOURCE_VERSION=$FRONTEND_VERSION
            echo "Only frontend changed - updating frontend"
          else
            echo "No relevant changes detected"
            echo "version_changed=false" >> $GITHUB_OUTPUT
            echo "component_changed=none" >> $GITHUB_OUTPUT
            echo "new_version=" >> $GITHUB_OUTPUT
            exit 0
          fi
          
          echo "Component changed: $COMPONENT_CHANGED"
          echo "Source version: $SOURCE_VERSION"
          echo "Backend update: $BACKEND_UPDATE"
          echo "Frontend update: $FRONTEND_UPDATE"
          
          # Calculate new version
          IFS='.' read -r -a version_parts <<< "$SOURCE_VERSION"
          MAJOR="${version_parts[0]}"
          MINOR="${version_parts[1]}"
          PATCH="${version_parts[2]}"
          
          # Increment patch version
          NEW_PATCH=$((PATCH + 1))
          NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH"
          
          echo "New version: $NEW_VERSION"
          echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
          echo "component_changed=$COMPONENT_CHANGED" >> $GITHUB_OUTPUT
          
          # Update versions in package.json files
          if [ "$BACKEND_UPDATE" = true ]; then
            echo "Updating backend version to $NEW_VERSION"
            cd backend && npm version $NEW_VERSION --no-git-tag-version
            cd ..
          fi
          
          if [ "$FRONTEND_UPDATE" = true ]; then
            echo "Updating frontend version to $NEW_VERSION"
            cd frontend && npm version $NEW_VERSION --no-git-tag-version
            cd ..
          fi
          
          # Check if there are changes to commit
          if [[ -n $(git status --porcelain) ]]; then
            echo "version_changed=true" >> $GITHUB_OUTPUT
          else
            echo "version_changed=false" >> $GITHUB_OUTPUT
          fi
      
      - name: Commit version bump
        if: steps.version.outputs.version_changed == 'true'
        run: |
          set -e  # Exit on any error
          
          # First, ensure we have the latest changes
          echo "Fetching latest changes..."
          git fetch origin main
          
          # Check if we're behind and need to update
          LOCAL=$(git rev-parse HEAD)
          REMOTE=$(git rev-parse origin/main)
          
          if [ "$LOCAL" != "$REMOTE" ]; then
            echo "Local is behind remote, pulling changes..."
            git pull origin main --no-rebase
          fi
          
          COMPONENT="${{ steps.version.outputs.component_changed }}"
          
          if [ "$COMPONENT" = "both" ]; then
            git add backend/package.json backend/package-lock.json frontend/package.json frontend/package-lock.json
            git commit -m "chore: bump version to ${{ steps.version.outputs.new_version }} (backend + frontend)"
          elif [ "$COMPONENT" = "backend" ]; then
            git add backend/package.json backend/package-lock.json
            git commit -m "chore: bump backend version to ${{ steps.version.outputs.new_version }}"
          elif [ "$COMPONENT" = "frontend" ]; then
            git add frontend/package.json frontend/package-lock.json
            git commit -m "chore: bump frontend version to ${{ steps.version.outputs.new_version }}"
          fi
          
          # Pull latest changes before pushing to avoid conflicts
          echo "Pulling latest changes from origin/main..."
          if ! git pull --rebase origin main; then
            echo "Rebase failed, attempting to resolve..."
            # If rebase fails, abort and try a regular merge
            git rebase --abort || true
            git pull origin main --no-rebase
          fi
          
          # Push the changes with retry logic
          echo "Pushing version bump..."
          PUSH_SUCCESS=false
          
          for i in 1 2 3; do
            echo "Push attempt $i of 3..."
            
            # Try to push
            if git push origin main 2>&1; then
              echo "Successfully pushed version bump on attempt $i"
              PUSH_SUCCESS=true
              break
            else
              echo "Push failed on attempt $i"
              
              if [ $i -lt 3 ]; then
                echo "Waiting 5 seconds before retry..."
                sleep 5
                
                echo "Pulling latest changes..."
                git fetch origin main
                
                # Try rebase first, fall back to merge
                if ! git rebase origin/main; then
                  echo "Rebase failed, trying merge..."
                  git rebase --abort 2>/dev/null || true
                  git pull origin main --no-rebase
                fi
              fi
            fi
          done
          
          if [ "$PUSH_SUCCESS" = "false" ]; then
            echo "ERROR: Failed to push after 3 attempts"
            exit 1
          fi
      
      - name: Create Git tag
        if: steps.version.outputs.version_changed == 'true'
        run: |
          COMPONENT="${{ steps.version.outputs.component_changed }}"
          
          if [ "$COMPONENT" = "both" ]; then
            TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (backend + frontend)"
          elif [ "$COMPONENT" = "backend" ]; then
            TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (backend)"
          elif [ "$COMPONENT" = "frontend" ]; then
            TAG_MESSAGE="Release v${{ steps.version.outputs.new_version }} (frontend)"
          fi
          
          git tag -a "v${{ steps.version.outputs.new_version }}" -m "$TAG_MESSAGE"
          git push origin "v${{ steps.version.outputs.new_version }}"
  
  trigger-drone:
    needs: version-bump
    if: needs.version-bump.outputs.version_changed == 'true'
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Drone Build
        run: |
          echo "Version bumped to ${{ needs.version-bump.outputs.new_version }}"
          echo "Component(s) changed: ${{ needs.version-bump.outputs.component_changed }}"
          echo "Drone will automatically trigger on the new tag"
          # Drone CI will automatically trigger on the tag push event