# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow
# INGROUP: MokoStandards.Joomla
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/joomla/update-server.yml.template
# VERSION: 04.06.00
# BRIEF: Update Joomla update server XML feed with stable/rc/dev entries
#
# Writes updates.xml with multiple <update> entries:
#   - <tag>stable</tag>     on push to main (from auto-release)
#   - <tag>rc</tag>         on push to rc/**
#   - <tag>development</tag> on push to dev/**
#
# Joomla filters by user's "Minimum Stability" setting.

name: Update Joomla Update Server XML Feed

on:
  push:
    branches:
      - main
      - version/*
    paths:
      - 'src/**'
      - 'htdocs/**'
  workflow_dispatch:
    inputs:
      stability:
        description: 'Stability tag'
        required: true
        default: 'development'
        type: choice
        options:
          - development
          - alpha
          - beta
          - rc
          - stable

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

permissions:
  contents: write

jobs:
  update-xml:
    name: Update updates.xml
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          token: ${{ secrets.GH_TOKEN || github.token }}
          fetch-depth: 0

      - name: Setup MokoStandards tools
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
          COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
        run: |
          git clone --depth 1 --branch version/04 --quiet \
            "https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
            /tmp/mokostandards 2>/dev/null || true
          if [ -d "/tmp/mokostandards" ] && [ -f "/tmp/mokostandards/composer.json" ]; then
            cd /tmp/mokostandards && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
          fi

      - name: Generate updates.xml entry
        run: |
          BRANCH="${{ github.ref_name }}"
          REPO="${{ github.repository }}"
          VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null || echo "0.0.0")

          # Auto-bump patch on alpha/beta/rc branches (not dev — dev bumps manually)
          if [[ "$BRANCH" != dev/* ]]; then
            git config --local user.email "github-actions[bot]@users.noreply.github.com"
            git config --local user.name "github-actions[bot]"
            BUMPED=$(php /tmp/mokostandards/api/cli/version_bump.php --path . 2>/dev/null || true)
            if [ -n "$BUMPED" ]; then
              VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
              git add -A
              git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
                --author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>" 2>/dev/null || true
              git push 2>/dev/null || true
            fi
          fi

          # Determine stability from branch or input
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            STABILITY="${{ inputs.stability }}"
          elif [[ "$BRANCH" == rc/* ]]; then
            STABILITY="rc"
          elif [[ "$BRANCH" == beta/* ]]; then
            STABILITY="beta"
          elif [[ "$BRANCH" == alpha/* ]]; then
            STABILITY="alpha"
          elif [[ "$BRANCH" == dev/* ]]; then
            STABILITY="development"
          else
            STABILITY="stable"
          fi

          # Parse manifest
          MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
          if [ -z "$MANIFEST" ]; then
            echo "No Joomla manifest found — skipping"
            exit 0
          fi

          EXT_NAME=$(grep -oP '<name>\K[^<]+' "$MANIFEST" 2>/dev/null | head -1 || echo "${{ github.event.repository.name }}")
          EXT_TYPE=$(grep -oP '<extension[^>]+type="\K[^"]+' "$MANIFEST" 2>/dev/null || echo "component")
          EXT_ELEMENT=$(grep -oP '<element>\K[^<]+' "$MANIFEST" 2>/dev/null | head -1 || basename "$MANIFEST" .xml)
          EXT_CLIENT=$(grep -oP '<extension[^>]+client="\K[^"]+' "$MANIFEST" 2>/dev/null || echo "")
          EXT_FOLDER=$(grep -oP '<extension[^>]+group="\K[^"]+' "$MANIFEST" 2>/dev/null || echo "")
          TARGET_PLATFORM=$(grep -oP '<targetplatform[^/]*/>' "$MANIFEST" 2>/dev/null | head -1 || echo "")
          PHP_MINIMUM=$(grep -oP '<php_minimum>\K[^<]+' "$MANIFEST" 2>/dev/null | head -1 || echo "")

          [ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(basename "$MANIFEST" .xml)
          [ -z "$TARGET_PLATFORM" ] && TARGET_PLATFORM=$(printf '<targetplatform name="joomla" version="5.*" %s>' "/")

          CLIENT_TAG=""
          [ -n "$EXT_CLIENT" ] && CLIENT_TAG="<client>${EXT_CLIENT}</client>"
          [ -z "$CLIENT_TAG" ] && ([ "$EXT_TYPE" = "module" ] || [ "$EXT_TYPE" = "plugin" ]) && CLIENT_TAG="<client>site</client>"

          FOLDER_TAG=""
          [ -n "$EXT_FOLDER" ] && [ "$EXT_TYPE" = "plugin" ] && FOLDER_TAG="<folder>${EXT_FOLDER}</folder>"

          PHP_TAG=""
          [ -n "$PHP_MINIMUM" ] && PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"

          # Version suffix for non-stable
          DISPLAY_VERSION="$VERSION"
          case "$STABILITY" in
            development) DISPLAY_VERSION="${VERSION}-dev" ;;
            alpha)       DISPLAY_VERSION="${VERSION}-alpha" ;;
            beta)        DISPLAY_VERSION="${VERSION}-beta" ;;
            rc)          DISPLAY_VERSION="${VERSION}-rc" ;;
          esac

          MAJOR=$(echo "$VERSION" | awk -F. '{print $1}')

          # Each stability level has its own release tag
          case "$STABILITY" in
            development) RELEASE_TAG="development" ;;
            alpha)       RELEASE_TAG="alpha" ;;
            beta)        RELEASE_TAG="beta" ;;
            rc)          RELEASE_TAG="release-candidate" ;;
            *)           RELEASE_TAG="v${MAJOR}" ;;
          esac

          PACKAGE_NAME="${EXT_ELEMENT}-${DISPLAY_VERSION}.zip"
          DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}"
          INFO_URL="https://github.com/${REPO}"

          # ── Build install-ready ZIP ─────────────────────────────────
          SOURCE_DIR="src"
          [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
          if [ -d "$SOURCE_DIR" ]; then
            cd "$SOURCE_DIR"
            zip -r "/tmp/${PACKAGE_NAME}" . -x '.ftpignore' 'sftp-config*' '*.ppk' '*.pem' '*.key' '.env*'
            cd ..

            SHA256=$(sha256sum "/tmp/${PACKAGE_NAME}" | cut -d' ' -f1)

            # Ensure draft release exists for this major
            gh release view "$RELEASE_TAG" --json tagName > /dev/null 2>&1 || \
              gh release create "$RELEASE_TAG" --title "${RELEASE_TAG} (${DISPLAY_VERSION})" --notes "${STABILITY} release" --prerelease --target main 2>/dev/null || true

            # Upload ZIP to the major release
            gh release upload "$RELEASE_TAG" "/tmp/${PACKAGE_NAME}" --clobber 2>/dev/null || true

            echo "Package: ${PACKAGE_NAME} (SHA: ${SHA256})" >> $GITHUB_STEP_SUMMARY
          else
            SHA256=""
          fi

          # ── Build the new entry ───────────────────────────────────────
          NEW_ENTRY=""
          NEW_ENTRY="${NEW_ENTRY}  <update>\n"
          NEW_ENTRY="${NEW_ENTRY}    <name>${EXT_NAME}</name>\n"
          NEW_ENTRY="${NEW_ENTRY}    <description>${EXT_NAME} (${STABILITY})</description>\n"
          NEW_ENTRY="${NEW_ENTRY}    <element>${EXT_ELEMENT}</element>\n"
          NEW_ENTRY="${NEW_ENTRY}    <type>${EXT_TYPE}</type>\n"
          NEW_ENTRY="${NEW_ENTRY}    <version>${DISPLAY_VERSION}</version>\n"
          [ -n "$CLIENT_TAG" ] && NEW_ENTRY="${NEW_ENTRY}    ${CLIENT_TAG}\n"
          [ -n "$FOLDER_TAG" ] && NEW_ENTRY="${NEW_ENTRY}    ${FOLDER_TAG}\n"
          NEW_ENTRY="${NEW_ENTRY}    <tags>\n"
          NEW_ENTRY="${NEW_ENTRY}      <tag>${STABILITY}</tag>\n"
          NEW_ENTRY="${NEW_ENTRY}    </tags>\n"
          NEW_ENTRY="${NEW_ENTRY}    <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>\n"
          NEW_ENTRY="${NEW_ENTRY}    <downloads>\n"
          NEW_ENTRY="${NEW_ENTRY}      <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>\n"
          NEW_ENTRY="${NEW_ENTRY}    </downloads>\n"
          [ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY}    <sha256>sha256:${SHA256}</sha256>\n"
          NEW_ENTRY="${NEW_ENTRY}    ${TARGET_PLATFORM}\n"
          [ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY}    ${PHP_TAG}\n"
          NEW_ENTRY="${NEW_ENTRY}    <maintainer>Moko Consulting</maintainer>\n"
          NEW_ENTRY="${NEW_ENTRY}    <maintainerurl>https://mokoconsulting.tech</maintainerurl>\n"
          NEW_ENTRY="${NEW_ENTRY}  </update>"

          # ── Write new entry to temp file ───────────────────────────────
          printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml

          # ── Merge into updates.xml ─────────────────────────────────────
          if [ ! -f "updates.xml" ]; then
            printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>' > updates.xml
            printf '%s\n' '<updates>' >> updates.xml
            cat /tmp/new_entry.xml >> updates.xml
            printf '\n%s\n' '</updates>' >> updates.xml
          else
            # Remove existing entry for this stability, insert new one
            printf 'import re\nstability = "%s"\n' "${STABILITY}" > /tmp/merge_xml.py
            printf 'with open("updates.xml") as f: content = f.read()\n' >> /tmp/merge_xml.py
            printf 'with open("/tmp/new_entry.xml") as f: new_entry = f.read()\n' >> /tmp/merge_xml.py
            printf 'pattern = r"  <update>.*?<tag>" + re.escape(stability) + r"</tag>.*?</update>\\n?"\n' >> /tmp/merge_xml.py
            printf 'content = re.sub(pattern, "", content, flags=re.DOTALL)\n' >> /tmp/merge_xml.py
            printf 'content = content.replace("</updates>", new_entry + "\\n</updates>")\n' >> /tmp/merge_xml.py
            printf 'content = re.sub(r"\\n{3,}", "\\n\\n", content)\n' >> /tmp/merge_xml.py
            printf 'with open("updates.xml", "w") as f: f.write(content)\n' >> /tmp/merge_xml.py
            python3 /tmp/merge_xml.py 2>/dev/null || {
              # Fallback: rebuild keeping other stability entries
              {
                printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>'
                printf '%s\n' '<updates>'
                for TAG in stable rc development; do
                  [ "$TAG" = "${STABILITY}" ] && continue
                  if grep -q "<tag>${TAG}</tag>" updates.xml 2>/dev/null; then
                    sed -n "/<update>/,/<\/update>/{ /<tag>${TAG}<\/tag>/p; }" updates.xml
                  fi
                done
                cat /tmp/new_entry.xml
                printf '\n%s\n' '</updates>'
              } > /tmp/updates_new.xml
              mv /tmp/updates_new.xml updates.xml
            }
          fi

          # Commit
          git config --local user.email "github-actions[bot]@users.noreply.github.com"
          git config --local user.name "github-actions[bot]"
          git add updates.xml
          git diff --cached --quiet || {
            git commit -m "chore: update updates.xml (${STABILITY}: ${DISPLAY_VERSION}) [skip ci]" \
              --author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
            git push
          }

      - name: SFTP deploy to dev server
        if: contains(github.ref, 'dev/')
        env:
          DEV_HOST: ${{ vars.DEV_FTP_HOST }}
          DEV_PATH: ${{ vars.DEV_FTP_PATH }}
          DEV_SUFFIX: ${{ vars.DEV_FTP_SUFFIX }}
          DEV_USER: ${{ vars.DEV_FTP_USERNAME }}
          DEV_PORT: ${{ vars.DEV_FTP_PORT }}
          DEV_KEY: ${{ secrets.DEV_FTP_KEY }}
          DEV_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
          GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
        run: |
          # ── Permission check: admin or maintain role required ──────
          ACTOR="${{ github.actor }}"
          REPO="${{ github.repository }}"
          PERMISSION=$(gh api "repos/${REPO}/collaborators/${ACTOR}/permission" \
            --jq '.permission' 2>/dev/null || \
            gh api "repos/${REPO}/collaborators/${ACTOR}" \
            --jq '.role' 2>/dev/null || echo "read")
          case "$PERMISSION" in
            admin|maintain|write) ;;
            *)
              echo "Deploy denied: ${ACTOR} has '${PERMISSION}' — requires admin, maintain, or write"
              exit 0
              ;;
          esac

          [ -z "$DEV_HOST" ] || [ -z "$DEV_PATH" ] && { echo "DEV FTP not configured — skipping SFTP"; exit 0; }

          SOURCE_DIR="src"
          [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
          [ ! -d "$SOURCE_DIR" ] && exit 0

          PORT="${DEV_PORT:-22}"
          REMOTE="${DEV_PATH%/}"
          [ -n "$DEV_SUFFIX" ] && REMOTE="${REMOTE}/${DEV_SUFFIX#/}"

          printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
            "$DEV_HOST" "$PORT" "$DEV_USER" "$REMOTE" > /tmp/sftp-config.json
          if [ -n "$DEV_KEY" ]; then
            echo "$DEV_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
            printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
          else
            printf ',"password":"%s"}' "$DEV_PASS" >> /tmp/sftp-config.json
          fi

          PLATFORM=$(php /tmp/mokostandards/api/cli/platform_detect.php --path . 2>/dev/null || true)
          if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards/api/deploy/deploy-joomla.php" ]; then
            php /tmp/mokostandards/api/deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
          elif [ -f "/tmp/mokostandards/api/deploy/deploy-sftp.php" ]; then
            php /tmp/mokostandards/api/deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
          fi
          rm -f /tmp/deploy_key /tmp/sftp-config.json
          echo "SFTP deploy to dev complete" >> $GITHUB_STEP_SUMMARY

      - name: Summary
        if: always()
        run: |
          echo "## Joomla Update Server" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
          echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
          echo "| Stability | \`${STABILITY}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Version | \`${DISPLAY_VERSION}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Element | \`${EXT_ELEMENT}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Download | [ZIP](${DOWNLOAD_URL}) |" >> $GITHUB_STEP_SUMMARY
