name: Templates

on:
  push:
    branches:
      - main
    paths:
      - 'templates/**'
      - 'tools/template.sh'
      - '.github/workflows/template.yml'
  workflow_dispatch:

permissions:
  contents: write

jobs:
  discover:
    runs-on: ubuntu-latest
    outputs:
      templates: ${{ steps.set-templates.outputs.templates }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - id: set-templates
        run: |
          ALL_TEMPLATES=$(ls -d templates/*/ | grep -v "_base" | xargs -n 1 basename)

          # On workflow_dispatch, sync all templates
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            TEMPLATES=$(echo "$ALL_TEMPLATES" | jq -R -s -c 'split("\n") | map(select(. != ""))')
            echo "templates=$TEMPLATES" >> $GITHUB_OUTPUT
            exit 0
          fi

          CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})

          # If _base, tools/template.sh, or the workflow itself changed, sync all templates
          if echo "$CHANGED_FILES" | grep -qE '^(templates/_base/|tools/template\.sh|\.github/workflows/template\.yml)'; then
            TEMPLATES=$(echo "$ALL_TEMPLATES" | jq -R -s -c 'split("\n") | map(select(. != ""))')
          else
            # Only sync templates whose files changed
            CHANGED_TEMPLATES=$(echo "$CHANGED_FILES" | grep '^templates/' | cut -d'/' -f2 | sort -u | grep -v '_base')
            TEMPLATES=$(comm -12 <(echo "$ALL_TEMPLATES" | sort) <(echo "$CHANGED_TEMPLATES" | sort) | jq -R -s -c 'split("\n") | map(select(. != ""))')
          fi

          echo "templates=$TEMPLATES" >> $GITHUB_OUTPUT

  check:
    needs: discover
    runs-on: ubuntu-latest
    if: needs.discover.outputs.templates != '[]'
    strategy:
      matrix:
        template: ${{ fromJson(needs.discover.outputs.templates) }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Zig
        uses: mlugg/setup-zig@v2
        with:
          version: 0.15.2

      - name: Update ziex dependency to current commit
        run: |
          cd templates/_base
          zig fetch --save "git+https://github.com/ziex-dev/ziex#${{ github.sha }}"
          # If this template tracks its own build.zig.zon, update it too
          if git ls-files --error-unmatch "templates/${{ matrix.template }}/build.zig.zon" 2>/dev/null; then
            cd "$OLDPWD/templates/${{ matrix.template }}"
            zig fetch --save "git+https://github.com/ziex-dev/ziex#${{ github.sha }}"
          fi

      - name: Populate template
        run: bash ./tools/template.sh populate ${{ matrix.template }}

      - name: Build template
        run: |
          cd templates/${{ matrix.template }}
          zig build

  sync:
    needs: [discover, check]
    runs-on: ubuntu-latest
    if: needs.discover.outputs.templates != '[]'
    strategy:
      matrix:
        template: ${{ fromJson(needs.discover.outputs.templates) }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      - name: Setup Zig
        uses: mlugg/setup-zig@v2
        with:
          version: 0.15.2

      - name: Update ziex dependency to current commit
        run: |
          cd templates/_base
          zig fetch --save "git+https://github.com/ziex-dev/ziex#${{ github.sha }}"
          # If this template tracks its own build.zig.zon, update it too
          if git ls-files --error-unmatch "templates/${{ matrix.template }}/build.zig.zon" 2>/dev/null; then
            cd "$OLDPWD/templates/${{ matrix.template }}"
            zig fetch --save "git+https://github.com/ziex-dev/ziex#${{ github.sha }}"
          fi

      - name: Populate and Sync
        env:
          GITHUB_TOKEN: ${{ secrets.SYNC_TOKEN || secrets.GITHUB_TOKEN }}
        run: |
          OWNER=$(echo $GITHUB_REPOSITORY | cut -d'/' -f1)
          REPO_NAME="template-${{ matrix.template }}"
          TEMP_DIR=$(mktemp -d)

          echo "Syncing ${{ matrix.template }} to $REPO_NAME"

          # Run the populate tool locally
          # Note: The populate tool overwrites ignored files in the templates/ dir with base versions.
          bash ./tools/template.sh populate ${{ matrix.template }}

          # Copy everything from the populated template directory to the temp dir
          # Using -a to preserve permissions and -L if there are symlinks
          cp -a templates/${{ matrix.template }}/. "$TEMP_DIR/"

          # Copy common files from root if they don't exist in template
          [ ! -f "$TEMP_DIR/LICENSE" ] && [ -f LICENSE ] && cp LICENSE "$TEMP_DIR/"

          cd "$TEMP_DIR"

          # Initialize new repo for force push
          git init -b main
          git add .
          git commit -m "sync: latest changes from ziex-dev/ziex@${GITHUB_SHA::7}"

          # Push to the target repository
          REMOTE_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/$OWNER/$REPO_NAME.git"
          git remote add origin "$REMOTE_URL"
          git push -u origin main --force
