# 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: Gitea.Workflow
# INGROUP: MokoOnyx.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx
# PATH: /.gitea/workflows/release.yml
# VERSION: 01.00.00
# BRIEF: Joomla release — build ZIP, publish to Gitea, mirror to GitHub

name: Create Release

on:
  push:
    tags:
      - '[0-9][0-9].[0-9][0-9].[0-9][0-9]'
  workflow_dispatch:
    inputs:
      version:
        description: 'Release version (e.g., 01.00.00)'
        required: true
        type: string
      prerelease:
        description: 'Mark as pre-release'
        required: false
        type: boolean
        default: false
      stability:
        description: 'Stability tag (development, alpha, beta, rc, stable)'
        required: false
        type: string
        default: 'development'

permissions:
  contents: write

env:
  GITEA_URL: https://git.mokoconsulting.tech
  GITEA_ORG: MokoConsulting
  GITEA_REPO: MokoOnyx
  EXT_ELEMENT: mokoonyx

jobs:
  build:
    name: Build Release Package
    runs-on: release

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup PHP
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
          php -v
          composer --version

      - name: Get version and stability
        id: meta
        run: |
          if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
            VERSION="${{ inputs.version }}"
            STABILITY="${{ inputs.stability }}"
            PRERELEASE="${{ inputs.prerelease }}"
          else
            VERSION=${GITHUB_REF#refs/tags/}
            STABILITY="stable"
            PRERELEASE="false"
          fi

          # Derive suffix and tag from stability
          case "$STABILITY" in
            development) SUFFIX="-dev";   TAG_NAME="development" ;;
            alpha)       SUFFIX="-alpha"; TAG_NAME="alpha" ;;
            beta)        SUFFIX="-beta";  TAG_NAME="beta" ;;
            rc)          SUFFIX="-rc";    TAG_NAME="release-candidate" ;;
            stable)      SUFFIX="";       TAG_NAME="stable" ;;
            *)           SUFFIX="-dev";   TAG_NAME="development" ;;
          esac

          ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"

          echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
          echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
          echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
          echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
          echo "tag_name=${TAG_NAME}" >> "$GITHUB_OUTPUT"
          echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
          echo "Building: ${ZIP_NAME} (${STABILITY})"

      - name: Auto-bump patch version
        id: bump
        env:
          GA_TOKEN: ${{ secrets.GA_TOKEN }}
          INPUT_VERSION: ${{ steps.meta.outputs.version }}
          INPUT_STABILITY: ${{ steps.meta.outputs.stability }}
          INPUT_SUFFIX: ${{ steps.meta.outputs.suffix }}
        run: |
          BRANCH="${{ github.ref_name }}"
          GITEA_API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"

          # Read current version from README.md
          CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
          if [ -z "$CURRENT" ]; then
            echo "No VERSION in README.md — using input version"
            echo "version=${INPUT_VERSION}" >> "$GITHUB_OUTPUT"
            echo "zip_name=${EXT_ELEMENT}-${INPUT_VERSION}${INPUT_SUFFIX}.zip" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          # Bump patch: XX.YY.ZZ → XX.YY.(ZZ+1)
          MAJOR=$(echo "$CURRENT" | cut -d. -f1)
          MINOR=$(echo "$CURRENT" | cut -d. -f2)
          PATCH=$(echo "$CURRENT" | cut -d. -f3)
          NEW_PATCH=$(printf "%02d" $((10#$PATCH + 1)))
          NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"

          echo "Bumping: ${CURRENT} → ${NEW_VERSION}"

          # Update README.md
          sed -i "s/VERSION:[[:space:]]*${CURRENT}/VERSION: ${NEW_VERSION}/" README.md

          # Update templateDetails.xml / manifest
          MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
          if [ -n "$MANIFEST" ]; then
            sed -i "s|<version>${CURRENT}</version>|<version>${NEW_VERSION}</version>|" "$MANIFEST"
          fi

          # Update only the matching stability channel in updates.xml
          if [ -f "updates.xml" ]; then
            export PY_OLD="$CURRENT" PY_NEW="$NEW_VERSION" PY_STABILITY="$INPUT_STABILITY"
            python3 << 'PYEOF'
          import re, os
          old = os.environ["PY_OLD"]
          new = os.environ["PY_NEW"]
          stability = os.environ["PY_STABILITY"]
          with open("updates.xml") as f:
              content = f.read()
          pattern = r"(<update>(?:(?!</update>).)*?<tag>" + re.escape(stability) + r"</tag>.*?</update>)"
          match = re.search(pattern, content, re.DOTALL)
          if match:
              block = match.group(1)
              updated = block.replace(old, new)
              content = content.replace(block, updated)
          with open("updates.xml", "w") as f:
              f.write(content)
          print(f"Updated {stability} channel: {old} -> {new}")
          PYEOF
          fi

          # Commit bump to current branch
          git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
          git config --local user.name "gitea-actions[bot]"
          git remote set-url origin "https://jmiller:${GA_TOKEN}@git.mokoconsulting.tech/${{ github.repository }}.git"
          git add -A
          git diff --cached --quiet || {
            git commit -m "chore(version): bump ${CURRENT} → ${NEW_VERSION} [skip ci]" \
              --author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
            git push
          }

          # For stable releases from dev: merge dev → main via Gitea API
          if [ "$INPUT_STABILITY" = "stable" ] && [ "$BRANCH" != "main" ]; then
            echo "Merging ${BRANCH} → main via Gitea API..."
            curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
              -H "Content-Type: application/json" \
              "${GITEA_API}/merges" \
              -d "$(jq -n \
                --arg base "main" \
                --arg head "${BRANCH}" \
                --arg msg "chore(release): merge ${BRANCH} for stable ${NEW_VERSION} [skip ci]" \
                '{base: $base, head: $head, merge_message_field: $msg}'
              )" > /dev/null 2>&1 || echo "Merge API call failed — may need manual merge"
          fi

          echo "version=${NEW_VERSION}" >> "$GITHUB_OUTPUT"
          echo "zip_name=${EXT_ELEMENT}-${NEW_VERSION}${INPUT_SUFFIX}.zip" >> "$GITHUB_OUTPUT"

      - name: Install dependencies
        env:
          COMPOSER_AUTH: '{"http-basic":{"git.mokoconsulting.tech":{"username":"token","password":"${{ secrets.GA_TOKEN }}"}}}'
        run: |
          if [ -f "composer.json" ]; then
            composer install --no-dev --optimize-autoloader --no-interaction
          fi

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Minify CSS and JS
        run: |
          npm ci --ignore-scripts
          node scripts/minify.js

      - name: Create package
        run: |
          mkdir -p build/package
          rsync -av \
            --exclude='sftp-config*' \
            --exclude='.ftpignore' \
            --exclude='*.ppk' \
            --exclude='*.pem' \
            --exclude='*.key' \
            --exclude='.env*' \
            --exclude='*.local' \
            src/ build/package/

      - name: Build ZIP
        id: zip
        run: |
          ZIP_NAME="${{ steps.bump.outputs.zip_name }}"
          cd build/package
          zip -r "../${ZIP_NAME}" .
          cd ..

          SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
          SIZE=$(stat -c%s "${ZIP_NAME}")

          echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
          echo "size=${SIZE}" >> "$GITHUB_OUTPUT"
          echo "SHA-256: ${SHA256}"
          echo "Size: ${SIZE} bytes"

      # ── Gitea Release (PRIMARY) ──────────────────────────────────────
      - name: "Gitea: Delete existing release"
        run: |
          TAG="${{ steps.meta.outputs.tag_name }}"
          TOKEN="${{ secrets.GA_TOKEN }}"
          API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"

          # Find and delete existing release by tag (may not exist — ignore 404)
          RELEASE_ID=$(curl -s -H "Authorization: token ${TOKEN}" \
            "${API}/releases/tags/${TAG}" 2>/dev/null | jq -r '.id // empty')

          if [ -n "$RELEASE_ID" ]; then
            curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
              "${API}/releases/${RELEASE_ID}" || true
            echo "Deleted existing release id=${RELEASE_ID}"
          fi

          # Delete existing tag
          curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
            "${API}/tags/${TAG}" 2>/dev/null || true

      - name: "Gitea: Create release"
        id: gitea_release
        run: |
          TAG="${{ steps.meta.outputs.tag_name }}"
          VERSION="${{ steps.bump.outputs.version }}"
          STABILITY="${{ steps.meta.outputs.stability }}"
          PRERELEASE="${{ steps.meta.outputs.prerelease }}"
          SHA256="${{ steps.zip.outputs.sha256 }}"
          TOKEN="${{ secrets.GA_TOKEN }}"
          API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"

          # Build release body
          BODY="## ${EXT_ELEMENT} ${VERSION} (${STABILITY})

          ### SHA-256
          \`${SHA256}\`"

          # Extract changelog if available
          if [ -f "CHANGELOG.md" ]; then
            NOTES=$(awk "/## \[${VERSION}\]/,/## \[/{if(/## \[${VERSION}\]/)next;if(/## \[/)exit;print}" CHANGELOG.md)
            if [ -n "$NOTES" ]; then
              BODY="## ${EXT_ELEMENT} ${VERSION} (${STABILITY})

          ${NOTES}

          ### SHA-256
          \`${SHA256}\`"
            fi
          fi

          IS_PRE="true"
          if [ "$STABILITY" = "stable" ]; then
            IS_PRE="false"
          fi

          RESULT=$(curl -sf -X POST -H "Authorization: token ${TOKEN}" \
            -H "Content-Type: application/json" \
            "${API}/releases" \
            -d "$(jq -n \
              --arg tag "$TAG" \
              --arg target "${{ github.ref_name }}" \
              --arg name "${EXT_ELEMENT} ${VERSION} ${STABILITY^}" \
              --arg body "$BODY" \
              --argjson pre "$IS_PRE" \
              '{tag_name: $tag, target_commitish: $target, name: $name, body: $body, prerelease: $pre}'
            )")

          RELEASE_ID=$(echo "$RESULT" | jq -r '.id')
          echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
          echo "Gitea release created: id=${RELEASE_ID}, tag=${TAG}"

      - name: "Gitea: Upload ZIP"
        run: |
          RELEASE_ID="${{ steps.gitea_release.outputs.release_id }}"
          ZIP_NAME="${{ steps.bump.outputs.zip_name }}"
          TOKEN="${{ secrets.GA_TOKEN }}"
          API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"

          curl -sf -X POST \
            -H "Authorization: token ${TOKEN}" \
            -H "Content-Type: application/octet-stream" \
            "${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
            --data-binary "@build/${ZIP_NAME}"

          echo "Uploaded ${ZIP_NAME} to Gitea release ${RELEASE_ID}"

      # ── GitHub Mirror (BACKUP) ───────────────────────────────────────
      - name: "GitHub: Mirror release (stable/rc only)"
        if: ${{ steps.meta.outputs.stability == 'stable' || steps.meta.outputs.stability == 'rc' }}
        continue-on-error: true
        run: |
          TAG="${{ steps.meta.outputs.tag_name }}"
          VERSION="${{ steps.bump.outputs.version }}"
          STABILITY="${{ steps.meta.outputs.stability }}"
          ZIP_NAME="${{ steps.bump.outputs.zip_name }}"
          SHA256="${{ steps.zip.outputs.sha256 }}"
          TOKEN="${{ secrets.GH_TOKEN }}"
          GH_REPO="mokoconsulting-tech/${GITEA_REPO}"
          GH_API="https://api.github.com/repos/${GH_REPO}"

          IS_PRE="true"
          [ "$STABILITY" = "stable" ] && IS_PRE="false"

          # Delete existing release by tag
          EXISTING=$(curl -sf -H "Authorization: token ${TOKEN}" \
            "${GH_API}/releases/tags/${TAG}" 2>/dev/null | jq -r '.id // empty')
          if [ -n "$EXISTING" ]; then
            curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
              "${GH_API}/releases/${EXISTING}" || true
          fi

          # Delete tag
          curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
            "${GH_API}/git/refs/tags/${TAG}" 2>/dev/null || true

          # Create release
          RELEASE_ID=$(curl -sf -X POST -H "Authorization: token ${TOKEN}" \
            -H "Content-Type: application/json" \
            "${GH_API}/releases" \
            -d "$(jq -n \
              --arg tag "$TAG" \
              --arg target "${{ github.sha }}" \
              --arg name "${EXT_ELEMENT} ${VERSION} ${STABILITY^} (mirror)" \
              --arg body "Mirror of Gitea release. SHA-256: \`${SHA256}\`" \
              --argjson pre "$IS_PRE" \
              '{tag_name: $tag, target_commitish: $target, name: $name, body: $body, prerelease: $pre, draft: false}'
            )" | jq -r '.id')

          # Upload ZIP
          if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "null" ]; then
            curl -sf -X POST \
              -H "Authorization: token ${TOKEN}" \
              -H "Content-Type: application/octet-stream" \
              "https://uploads.github.com/repos/${GH_REPO}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
              --data-binary "@build/${ZIP_NAME}"
            echo "GitHub mirror: uploaded ${ZIP_NAME}"
          fi

      # ── Update updates.xml ──────────────────────────────────────────
      - name: "Update updates.xml for this channel"
        run: |
          STABILITY="${{ steps.meta.outputs.stability }}"
          VERSION="${{ steps.bump.outputs.version }}"
          SHA256="${{ steps.zip.outputs.sha256 }}"
          ZIP_NAME="${{ steps.bump.outputs.zip_name }}"
          TAG="${{ steps.meta.outputs.tag_name }}"
          DATE=$(date +%Y-%m-%d)

          if [ ! -f "updates.xml" ] || [ -z "$SHA256" ]; then
            echo "No updates.xml or no SHA — skipping"
            exit 0
          fi

          export PY_STABILITY="$STABILITY" PY_VERSION="$VERSION" PY_SHA256="$SHA256" \
                 PY_ZIP_NAME="$ZIP_NAME" PY_TAG="$TAG" PY_DATE="$DATE" \
                 PY_GITEA_ORG="$GITEA_ORG" PY_GITEA_REPO="$GITEA_REPO"
          python3 << 'PYEOF'
          import re, os

          stability  = os.environ["PY_STABILITY"]
          version    = os.environ["PY_VERSION"]
          sha256     = os.environ["PY_SHA256"]
          zip_name   = os.environ["PY_ZIP_NAME"]
          tag        = os.environ["PY_TAG"]
          date       = os.environ["PY_DATE"]
          gitea_org  = os.environ["PY_GITEA_ORG"]
          gitea_repo = os.environ["PY_GITEA_REPO"]

          # Map stability to the <tag> value in updates.xml
          tag_map = {
              "development": "development",
              "alpha": "alpha",
              "beta": "beta",
              "rc": "rc",
              "stable": "stable",
          }
          xml_tag = tag_map.get(stability, "development")

          with open("updates.xml", "r") as f:
              content = f.read()

          # Build regex to find the specific <update> block for this stability tag
          # Use negative lookahead to avoid matching across multiple <update> blocks
          block_pattern = r"(<update>(?:(?!</update>).)*?<tag>" + re.escape(xml_tag) + r"</tag>.*?</update>)"
          match = re.search(block_pattern, content, re.DOTALL)

          if not match:
              print(f"No <update> block found for <tag>{xml_tag}</tag>")
              exit(0)

          block = match.group(1)
          original_block = block

          # Update version
          block = re.sub(r"<version>[^<]*</version>", f"<version>{version}</version>", block)

          # Update creation date
          block = re.sub(r"<creationDate>[^<]*</creationDate>", f"<creationDate>{date}</creationDate>", block)

          # Update SHA-256
          block = re.sub(r"<sha256>[^<]*</sha256>", f"<sha256>{sha256}</sha256>", block)

          # Update Gitea download URL
          gitea_url = f"https://git.mokoconsulting.tech/{gitea_org}/{gitea_repo}/releases/download/{tag}/{zip_name}"
          block = re.sub(
              r"(<downloadurl[^>]*>)https://git\.mokoconsulting\.tech/[^<]*(</downloadurl>)",
              rf"\g<1>{gitea_url}\g<2>",
              block
          )

          # Update GitHub download URL only for RC and stable (others are Gitea-only)
          if stability in ("rc", "stable"):
              gh_url = f"https://github.com/mokoconsulting-tech/{gitea_repo}/releases/download/{tag}/{zip_name}"
              block = re.sub(
                  r"(<downloadurl[^>]*>)https://github\.com/[^<]*(</downloadurl>)",
                  rf"\g<1>{gh_url}\g<2>",
                  block
              )
          else:
              # Remove any GitHub download URL for dev/alpha/beta
              block = re.sub(
                  r"\n\s*<downloadurl[^>]*>https://github\.com/[^<]*</downloadurl>",
                  "",
                  block
              )

          content = content.replace(original_block, block)

          with open("updates.xml", "w") as f:
              f.write(content)

          print(f"Updated {xml_tag} channel: version={version}, sha={sha256[:16]}..., date={date}")
          PYEOF

      - name: "Commit updates.xml to current branch and main"
        run: |
          if git diff --quiet updates.xml 2>/dev/null; then
            echo "No changes to updates.xml"
            exit 0
          fi

          STABILITY="${{ steps.meta.outputs.stability }}"
          VERSION="${{ steps.bump.outputs.version }}"
          CURRENT_BRANCH="${{ github.ref_name }}"
          TOKEN="${{ secrets.GA_TOKEN }}"

          git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
          git config --local user.name "gitea-actions[bot]"
          git add updates.xml
          git commit -m "chore: update ${STABILITY} SHA-256 for ${VERSION} [skip ci]" \
            --author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"

          # Set push URL with GA_TOKEN for authenticated pushes (branch protection requires jmiller)
          git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"

          # Push to current branch
          git push || true

          # Sync updates.xml to main via direct API
          GA_TOKEN="${{ secrets.GA_TOKEN }}"
          API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"

          FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
            "${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty')

          if [ -n "$FILE_SHA" ]; then
            CONTENT=$(base64 -w0 updates.xml)
            curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
              -H "Content-Type: application/json" \
              "${API}/contents/updates.xml" \
              -d "$(jq -n \
                --arg content "$CONTENT" \
                --arg sha "$FILE_SHA" \
                --arg msg "chore: sync updates.xml ${STABILITY} ${VERSION} [skip ci]" \
                --arg branch "main" \
                '{content: $content, sha: $sha, message: $msg, branch: $branch}'
              )" > /dev/null 2>&1 \
              && echo "updates.xml synced to main" \
              || echo "WARNING: failed to sync updates.xml to main"
          fi

      - name: Summary
        run: |
          VERSION="${{ steps.bump.outputs.version }}"
          STABILITY="${{ steps.meta.outputs.stability }}"
          ZIP_NAME="${{ steps.bump.outputs.zip_name }}"
          SHA256="${{ steps.zip.outputs.sha256 }}"
          TAG="${{ steps.meta.outputs.tag_name }}"

          echo "### Release Created" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
          echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
          echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Stability | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
          echo "| Tag | \`${TAG}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| SHA-256 | \`${SHA256}\` |" >> $GITHUB_STEP_SUMMARY
          echo "| Gitea | [Release](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${TAG}) |" >> $GITHUB_STEP_SUMMARY
