name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  lint-php:
    name: PHP Syntax Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: pdo_sqlite, curl, mbstring

      - name: Check PHP syntax
        run: |
          find api/ -name '*.php' -exec php -l {} \;

  lint-js:
    name: JavaScript Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Check JS syntax
        run: |
          node -c assets/js/app.js

  docker-build:
    name: Docker Build Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Build Docker image
        run: |
          set -e
          for attempt in 1 2 3; do
            echo "Docker build attempt $attempt/3..."
            if docker build -t evershelf-test .; then
              exit 0
            fi
            echo "Attempt $attempt failed — retrying in 20s..."
            sleep 20
          done
          echo "Docker build failed after 3 attempts"
          exit 1

      - name: Test container starts
        run: |
          docker run -d --name test-evershelf -p 8080:80 evershelf-test
          sleep 5
          curl -f http://localhost:8080/ || exit 1
          docker stop test-evershelf

  validate-translations:
    name: Validate Translation Files
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Validate JSON syntax
        run: |
          for f in translations/*.json; do
            echo "Checking $f..."
            python3 -c "import json; json.load(open('$f'))" || exit 1
          done
          echo "All translation files valid."

      - name: Check translation completeness
        run: |
          python3 -c "
          import json, sys
          base = json.load(open('translations/it.json'))
          base_keys = set(base.keys())
          ok = True
          import glob
          for f in glob.glob('translations/*.json'):
              if 'it.json' in f:
                  continue
              lang = json.load(open(f))
              lang_keys = set(lang.keys())
              missing = base_keys - lang_keys
              if missing:
                  print(f'{f}: {len(missing)} missing keys')
                  for k in sorted(missing)[:10]:
                      print(f'  - {k}')
                  if len(missing) > 10:
                      print(f'  ... and {len(missing)-10} more')
              else:
                  print(f'{f}: complete ✓')
          "

  # ── Auto-merge develop → main ────────────────────────────────────────────
  # Runs automatically after ALL checks pass on develop.
  # You never need to merge manually again — just push to develop.
  auto-merge-to-main:
    name: Auto-merge develop → main
    needs: [lint-php, lint-js, docker-build, validate-translations]
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout (full history)
        uses: actions/checkout@v6
        with:
          fetch-depth: 0
          # Always use the built-in GITHUB_TOKEN for checkout (read-only fetch).
          # WORKFLOW_PAT is only needed for the push step below.
          token: ${{ github.token }}

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

      - name: Merge develop → main
        run: |
          # ── ROOT CAUSE FIX ──────────────────────────────────────────────────
          # actions/checkout writes an http.extraheader (AUTHORIZATION: basic …)
          # that silently overrides any credentials embedded in git remote URLs.
          # We must clear it BEFORE setting the remote URL with WORKFLOW_PAT,
          # otherwise GITHUB_TOKEN is always used for the push and workflow-file
          # changes are rejected.
          # ────────────────────────────────────────────────────────────────────
          git config --local --unset-all http."https://github.com/".extraheader 2>/dev/null || true

          LAST=$(git log --oneline -1 origin/develop)
          git checkout main
          git pull --ff-only origin main
          git merge --no-ff origin/develop \
            -m "chore: auto-merge develop → main

          Triggered by: $LAST"

          # ── PUSH STRATEGY ───────────────────────────────────────────────────
          # Priority 1: WORKFLOW_PAT (classic PAT, repo+workflow scopes)
          #   → can push workflow file changes; set as a repo secret.
          # Priority 2: GITHUB_TOKEN fallback
          #   → cannot push workflow files; strip them from the merge commit.
          # ────────────────────────────────────────────────────────────────────
          PUSH_TOKEN="${{ secrets.WORKFLOW_PAT }}"
          if [ -z "$PUSH_TOKEN" ]; then
            WF=$(git diff --name-only origin/main -- .github/workflows/ 2>/dev/null || echo "")
            if [ -n "$WF" ]; then
              echo "::warning::WORKFLOW_PAT not set — stripping workflow changes from merge commit:"
              echo "$WF"
              git checkout origin/main -- .github/workflows/
              git diff --cached --quiet || git commit --amend --no-edit
            fi
            PUSH_TOKEN="${{ github.token }}"
          fi

          git remote set-url origin "https://x-access-token:${PUSH_TOKEN}@github.com/${{ github.repository }}.git"
          git push origin main

  # ── Auto-create GitHub Release on main ───────────────────────────────────
  # Runs after auto-merge succeeds. Reads version from index.html,
  # creates a release tag vX.Y.Z if it doesn't exist yet.
  # This powers the in-app update badge for self-hosted users.
  create-release:
    name: Create GitHub Release
    needs: [auto-merge-to-main]
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout main
        uses: actions/checkout@v6
        with:
          ref: main
          fetch-depth: 0
          token: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract version from index.html
        id: version
        run: |
          VER=$(grep -oP 'header-version">v\K[\d.]+' index.html | head -1)
          echo "version=v${VER}" >> $GITHUB_OUTPUT
          echo "Detected version: v${VER}"

      - name: Check if tag already exists
        id: tag_check
        run: |
          if git ls-remote --tags origin "refs/tags/${{ steps.version.outputs.version }}" | grep -q .; then
            echo "exists=true" >> $GITHUB_OUTPUT
          else
            echo "exists=false" >> $GITHUB_OUTPUT
          fi

      - name: Read CHANGELOG entry for this version
        id: changelog
        if: steps.tag_check.outputs.exists == 'false'
        run: |
          VER="${{ steps.version.outputs.version }}"
          # Extract the section for this version from CHANGELOG.md
          BODY=$(awk "/^## \[?${VER#v}\]?|^## ${VER}/,/^## [0-9]/" CHANGELOG.md | head -50 | tail -n +1 | grep -v "^## [0-9]" || true)
          if [ -z "$BODY" ]; then
            BODY="See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details."
          fi
          # Multiline output
          echo "body<<EOF" >> $GITHUB_OUTPUT
          echo "$BODY" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Create release
        if: steps.tag_check.outputs.exists == 'false'
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ steps.version.outputs.version }}
          name: "EverShelf ${{ steps.version.outputs.version }}"
          body: ${{ steps.changelog.outputs.body }}
          target_commitish: main
          make_latest: true
