# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow.Template
# INGROUP: MokoStandards.CI
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/joomla/ci-joomla.yml
# VERSION: 04.05.13
# BRIEF: CI workflow for Joomla extensions — lint, validate, test
# NOTE: Deployed to .github/workflows/ci-joomla.yml in governed Joomla extension repos.

name: Joomla Extension CI

on:
  push:
    branches:
      - main
      - dev/**
      - rc/**
      - version/**
  pull_request:
    branches:
      - main
      - dev/**
      - rc/**
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
  lint-and-validate:
    name: Lint & Validate
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Setup PHP
        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0
        with:
          php-version: '8.2'
          extensions: mbstring, xml, zip, gd, curl, json, simplexml
          tools: composer:v2
          coverage: none

      - name: Clone MokoStandards
        env:
          GH_TOKEN: ${{ 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

      - name: Install dependencies
        env:
          COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
        run: |
          if [ -f "composer.json" ]; then
            composer install \
              --no-interaction \
              --prefer-dist \
              --optimize-autoloader
          else
            echo "No composer.json found — skipping dependency install"
          fi

      - name: PHP syntax check
        run: |
          ERRORS=0
          for DIR in src/ htdocs/; do
            if [ -d "$DIR" ]; then
              FOUND=1
              while IFS= read -r -d '' FILE; do
                OUTPUT=$(php -l "$FILE" 2>&1)
                if echo "$OUTPUT" | grep -q "Parse error"; then
                  echo "::error file=${FILE}::${OUTPUT}"
                  ERRORS=$((ERRORS + 1))
                fi
              done < <(find "$DIR" -name "*.php" -print0)
            fi
          done
          echo "### PHP Syntax Check" >> $GITHUB_STEP_SUMMARY
          if [ "${ERRORS}" -gt 0 ]; then
            echo "**${ERRORS} syntax error(s) found.**" >> $GITHUB_STEP_SUMMARY
            exit 1
          else
            echo "All PHP files passed syntax check." >> $GITHUB_STEP_SUMMARY
          fi

      - name: XML manifest validation
        run: |
          echo "### XML Manifest Validation" >> $GITHUB_STEP_SUMMARY
          ERRORS=0

          # Find the extension manifest (XML with <extension tag)
          MANIFEST=""
          for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
            if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
              MANIFEST="$XML_FILE"
              break
            fi
          done

          if [ -z "$MANIFEST" ]; then
            echo "No Joomla extension manifest found (XML file with \`<extension\` tag)." >> $GITHUB_STEP_SUMMARY
            ERRORS=$((ERRORS + 1))
          else
            echo "Manifest found: \`${MANIFEST}\`" >> $GITHUB_STEP_SUMMARY

            # Validate well-formed XML
            php -r "
              \$xml = @simplexml_load_file('$MANIFEST');
              if (\$xml === false) {
                echo 'INVALID';
                exit(1);
              }
              echo 'VALID';
            " > /tmp/xml_result 2>&1
            XML_RESULT=$(cat /tmp/xml_result)
            if [ "$XML_RESULT" != "VALID" ]; then
              echo "Manifest is not well-formed XML." >> $GITHUB_STEP_SUMMARY
              ERRORS=$((ERRORS + 1))
            else
              echo "Manifest is well-formed XML." >> $GITHUB_STEP_SUMMARY
            fi

            # Check required tags: name, version, author, namespace (Joomla 5+)
            for TAG in name version author namespace; do
              if ! grep -q "<${TAG}>" "$MANIFEST" 2>/dev/null; then
                echo "Missing required tag: \`<${TAG}>\`" >> $GITHUB_STEP_SUMMARY
                ERRORS=$((ERRORS + 1))
              else
                echo "Found required tag: \`<${TAG}>\`" >> $GITHUB_STEP_SUMMARY
              fi
            done
          fi

          if [ "${ERRORS}" -gt 0 ]; then
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "**${ERRORS} manifest issue(s) found.**" >> $GITHUB_STEP_SUMMARY
            exit 1
          else
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "**Manifest validation passed.**" >> $GITHUB_STEP_SUMMARY
          fi

      - name: Check language files referenced in manifest
        run: |
          echo "### Language File Check" >> $GITHUB_STEP_SUMMARY
          ERRORS=0

          MANIFEST=""
          for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
            if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
              MANIFEST="$XML_FILE"
              break
            fi
          done

          if [ -n "$MANIFEST" ]; then
            # Extract language file references from manifest
            LANG_FILES=$(grep -oP 'language\s+tag="[^"]*"[^>]*>\K[^<]+' "$MANIFEST" 2>/dev/null || true)
            if [ -z "$LANG_FILES" ]; then
              echo "No language file references found in manifest — skipping." >> $GITHUB_STEP_SUMMARY
            else
              while IFS= read -r LANG_FILE; do
                LANG_FILE=$(echo "$LANG_FILE" | xargs)
                if [ -z "$LANG_FILE" ]; then
                  continue
                fi
                # Check in common locations
                FOUND=0
                for BASE in "." "src" "htdocs"; do
                  if [ -f "${BASE}/${LANG_FILE}" ]; then
                    FOUND=1
                    break
                  fi
                done
                if [ "$FOUND" -eq 0 ]; then
                  echo "Missing language file: \`${LANG_FILE}\`" >> $GITHUB_STEP_SUMMARY
                  ERRORS=$((ERRORS + 1))
                else
                  echo "Language file present: \`${LANG_FILE}\`" >> $GITHUB_STEP_SUMMARY
                fi
              done <<< "$LANG_FILES"
            fi
          else
            echo "No manifest found — skipping language check." >> $GITHUB_STEP_SUMMARY
          fi

          if [ "${ERRORS}" -gt 0 ]; then
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "**${ERRORS} missing language file(s).**" >> $GITHUB_STEP_SUMMARY
            exit 1
          else
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "**Language file check passed.**" >> $GITHUB_STEP_SUMMARY
          fi

      - name: Check index.html files in directories
        run: |
          echo "### Index.html Check" >> $GITHUB_STEP_SUMMARY
          MISSING=0
          CHECKED=0

          for DIR in src/ htdocs/; do
            if [ -d "$DIR" ]; then
              while IFS= read -r -d '' SUBDIR; do
                CHECKED=$((CHECKED + 1))
                if [ ! -f "${SUBDIR}/index.html" ]; then
                  echo "Missing index.html in: \`${SUBDIR}\`" >> $GITHUB_STEP_SUMMARY
                  MISSING=$((MISSING + 1))
                fi
              done < <(find "$DIR" -type d -print0)
            fi
          done

          if [ "${CHECKED}" -eq 0 ]; then
            echo "No src/ or htdocs/ directories found — skipping." >> $GITHUB_STEP_SUMMARY
          elif [ "${MISSING}" -gt 0 ]; then
            echo "" >> $GITHUB_STEP_SUMMARY
            echo "**${MISSING} director(ies) missing index.html out of ${CHECKED} checked.**" >> $GITHUB_STEP_SUMMARY
            exit 1
          else
            echo "All ${CHECKED} directories contain index.html." >> $GITHUB_STEP_SUMMARY
          fi

  release-readiness:
    name: Release Readiness Check
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request' && github.base_ref == 'main'

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Validate release readiness
        run: |
          echo "## Release Readiness" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          ERRORS=0

          # Extract version from README.md
          README_VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1)
          if [ -z "$README_VERSION" ]; then
            echo "No VERSION found in README.md FILE INFORMATION block." >> $GITHUB_STEP_SUMMARY
            ERRORS=$((ERRORS + 1))
          else
            echo "README version: \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY
          fi

          # Find the extension manifest
          MANIFEST=""
          for XML_FILE in $(find . -maxdepth 2 -name "*.xml" -not -path "./.git/*" -not -path "./vendor/*"); do
            if grep -q "<extension" "$XML_FILE" 2>/dev/null; then
              MANIFEST="$XML_FILE"
              break
            fi
          done

          if [ -z "$MANIFEST" ]; then
            echo "No Joomla extension manifest found." >> $GITHUB_STEP_SUMMARY
            ERRORS=$((ERRORS + 1))
          else
            echo "Manifest: \`${MANIFEST}\`" >> $GITHUB_STEP_SUMMARY

            # Check <version> matches README VERSION
            MANIFEST_VERSION=$(grep -oP '<version>\K[^<]+' "$MANIFEST" | head -1)
            if [ -z "$MANIFEST_VERSION" ]; then
              echo "No \`<version>\` tag in manifest." >> $GITHUB_STEP_SUMMARY
              ERRORS=$((ERRORS + 1))
            elif [ -n "$README_VERSION" ] && [ "$MANIFEST_VERSION" != "$README_VERSION" ]; then
              echo "Manifest version \`${MANIFEST_VERSION}\` does not match README \`${README_VERSION}\`." >> $GITHUB_STEP_SUMMARY
              ERRORS=$((ERRORS + 1))
            else
              echo "Manifest version: \`${MANIFEST_VERSION}\`" >> $GITHUB_STEP_SUMMARY
            fi

            # Check extension type, element, client attributes
            EXT_TYPE=$(grep -oP '<extension[^>]*\btype="\K[^"]+' "$MANIFEST" | head -1)
            if [ -z "$EXT_TYPE" ]; then
              echo "Missing \`type\` attribute on \`<extension>\` tag." >> $GITHUB_STEP_SUMMARY
              ERRORS=$((ERRORS + 1))
            else
              echo "Extension type: \`${EXT_TYPE}\`" >> $GITHUB_STEP_SUMMARY
            fi

            # Element check (component/module/plugin name)
            HAS_ELEMENT=$(grep -cP '<(element|name)>' "$MANIFEST" 2>/dev/null || echo "0")
            if [ "$HAS_ELEMENT" -eq 0 ]; then
              echo "Missing \`<element>\` or \`<name>\` in manifest." >> $GITHUB_STEP_SUMMARY
              ERRORS=$((ERRORS + 1))
            fi

            # Client attribute for site/admin modules and plugins
            if echo "$EXT_TYPE" | grep -qP "^(module|plugin)$"; then
              HAS_CLIENT=$(grep -cP '<extension[^>]*\bclient=' "$MANIFEST" 2>/dev/null || echo "0")
              if [ "$HAS_CLIENT" -eq 0 ]; then
                echo "Missing \`client\` attribute for ${EXT_TYPE} extension." >> $GITHUB_STEP_SUMMARY
                ERRORS=$((ERRORS + 1))
              fi
            fi
          fi

          # Check updates.xml exists
          if [ -f "updates.xml" ] || [ -f "updates.xml" ]; then
            echo "Update XML present." >> $GITHUB_STEP_SUMMARY
          else
            echo "No updates.xml found." >> $GITHUB_STEP_SUMMARY
            ERRORS=$((ERRORS + 1))
          fi

          # Check CHANGELOG.md exists
          if [ -f "CHANGELOG.md" ]; then
            echo "CHANGELOG.md present." >> $GITHUB_STEP_SUMMARY
          else
            echo "No CHANGELOG.md found." >> $GITHUB_STEP_SUMMARY
            ERRORS=$((ERRORS + 1))
          fi

          echo "" >> $GITHUB_STEP_SUMMARY
          if [ $ERRORS -gt 0 ]; then
            echo "**${ERRORS} issue(s) must be resolved before release.**" >> $GITHUB_STEP_SUMMARY
            exit 1
          else
            echo "**Extension is ready for release.**" >> $GITHUB_STEP_SUMMARY
          fi

  test:
    name: Tests (PHP ${{ matrix.php }})
    runs-on: ubuntu-latest
    needs: lint-and-validate

    strategy:
      fail-fast: false
      matrix:
        php: ['8.2', '8.3']

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Setup PHP ${{ matrix.php }}
        uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.31.0
        with:
          php-version: ${{ matrix.php }}
          extensions: mbstring, xml, zip, gd, curl, json, simplexml
          tools: composer:v2
          coverage: none

      - name: Install dependencies
        env:
          COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
        run: |
          if [ -f "composer.json" ]; then
            composer install \
              --no-interaction \
              --prefer-dist \
              --optimize-autoloader
          else
            echo "No composer.json found — skipping dependency install"
          fi

      - name: Run tests
        run: |
          echo "### Test Results (PHP ${{ matrix.php }})" >> $GITHUB_STEP_SUMMARY
          if [ -f "phpunit.xml" ] || [ -f "phpunit.xml.dist" ]; then
            vendor/bin/phpunit --testdox 2>&1 | tee /tmp/test-output.log
            EXIT=${PIPESTATUS[0]}
            if [ $EXIT -eq 0 ]; then
              echo "All tests passed." >> $GITHUB_STEP_SUMMARY
            else
              echo "Test failures detected — see log." >> $GITHUB_STEP_SUMMARY
              echo '```' >> $GITHUB_STEP_SUMMARY
              cat /tmp/test-output.log >> $GITHUB_STEP_SUMMARY
              echo '```' >> $GITHUB_STEP_SUMMARY
            fi
            exit $EXIT
          else
            echo "No phpunit.xml found — skipping tests." >> $GITHUB_STEP_SUMMARY
          fi
