#!/usr/bin/env bash
#
# RankWizAI WordPress Plugin — Version Bump Helper
#
# Synchronizes the plugin version across the three places it appears:
#   1. CHANGELOG.md      — adds a new '## [X.Y.Z] - YYYY-MM-DD' stanza on top
#   2. rankwiz-ai.php    — 'Version:' header + RANKWIZ_VERSION constant
#   3. readme.txt        — 'Stable tag:' line
#
# The script does NOT auto-fill changelog entries — it inserts a stanza
# placeholder for the human/AI to fill in before running bin/build.sh. After
# every edit it post-verifies the change actually landed; silent no-ops are
# treated as errors so the operator never sees "Bumped to X.Y.Z." while the
# files are unchanged.
#
# By default the script refuses to run on a dirty working tree to avoid
# entangling a version bump with unrelated edits — pass --force to override.
#
# Usage:
#   ./bin/bump-version.sh 1.1.0
#   ./bin/bump-version.sh 1.1.0 --notes "Added X. Fixed Y."
#   ./bin/bump-version.sh 1.1.0 --force
#
set -euo pipefail

NEW_VERSION=""
NOTES=""
FORCE=0

while [[ $# -gt 0 ]]; do
    case $1 in
        --notes) NOTES="$2"; shift 2 ;;
        --force) FORCE=1; shift ;;
        -h|--help)
            sed -n '2,24p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
            exit 0
            ;;
        -*)
            echo "Unknown option: $1" >&2
            exit 1
            ;;
        *)
            if [ -z "$NEW_VERSION" ]; then
                NEW_VERSION="$1"
                shift
            else
                echo "Unexpected argument: $1" >&2
                exit 1
            fi
            ;;
    esac
done

if [ -z "$NEW_VERSION" ]; then
    echo "Usage: $0 <new-version> [--notes \"Free-form release notes\"] [--force]" >&2
    exit 1
fi

if ! [[ "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "ERROR: Version must be semver (X.Y.Z), got '$NEW_VERSION'." >&2
    exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PLUGIN_NAME="rankwiz-ai"

CHANGELOG="${PLUGIN_DIR}/CHANGELOG.md"
PLUGIN_FILE="${PLUGIN_DIR}/${PLUGIN_NAME}.php"
README_FILE="${PLUGIN_DIR}/readme.txt"

# Refuse to bump on a dirty tree unless --force was passed. A version bump
# entangled with unrelated edits is hard to revert cleanly.
if [ "$FORCE" -ne 1 ] && command -v git >/dev/null 2>&1; then
    if git -C "$PLUGIN_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
        DIRTY=$(git -C "$PLUGIN_DIR" status --porcelain -- \
            "$CHANGELOG" "$PLUGIN_FILE" "$README_FILE" 2>/dev/null || true)
        if [ -n "$DIRTY" ]; then
            echo "ERROR: working tree has uncommitted changes to one of:" >&2
            echo "  CHANGELOG.md, rankwiz-ai.php, readme.txt" >&2
            echo "  Commit or stash them first, or pass --force to override." >&2
            exit 1
        fi
    fi
fi

TODAY=$(date +%Y-%m-%d)

if grep -q "^## \[${NEW_VERSION}\]" "$CHANGELOG"; then
    echo "ERROR: CHANGELOG.md already has a stanza for ${NEW_VERSION}." >&2
    exit 1
fi

NOTES_BODY="${NOTES:-_Add release notes here before building._}"

# 1. CHANGELOG.md — insert a new stanza above the latest one. If the file has
# no existing version stanza yet (fresh changelog), inject after the first
# non-heading paragraph instead. Either way we verify the stanza is present
# before declaring success.
TMP=$(mktemp)
awk -v ver="$NEW_VERSION" -v date="$TODAY" -v notes="$NOTES_BODY" '
    BEGIN { inserted = 0 }
    /^## \[[0-9]+\.[0-9]+\.[0-9]+\]/ && !inserted {
        printf "## [%s] - %s\n\n%s\n\n", ver, date, notes
        inserted = 1
    }
    { print }
    END {
        if (!inserted) {
            # No prior version stanza — append at the end.
            printf "\n## [%s] - %s\n\n%s\n", ver, date, notes
        }
    }
' "$CHANGELOG" > "$TMP"
mv "$TMP" "$CHANGELOG"

if ! grep -q "^## \[${NEW_VERSION}\]" "$CHANGELOG"; then
    echo "ERROR: failed to insert ${NEW_VERSION} stanza into CHANGELOG.md." >&2
    exit 1
fi

# 2. rankwiz-ai.php — header + constant. Use a temp file with sed-from-stdin
# instead of -i.bak to avoid leaving .bak files behind on crash.
TMP=$(mktemp)
sed -E \
    -e "s/^([[:space:]]*\*[[:space:]]*Version:[[:space:]]*)[0-9]+\.[0-9]+\.[0-9]+/\1${NEW_VERSION}/" \
    -e "s/(define\('RANKWIZ_VERSION',[[:space:]]*')[0-9]+\.[0-9]+\.[0-9]+('\);)/\1${NEW_VERSION}\2/" \
    "$PLUGIN_FILE" > "$TMP"
mv "$TMP" "$PLUGIN_FILE"

if ! grep -qE "^[[:space:]]*\*[[:space:]]*Version:[[:space:]]+${NEW_VERSION}\b" "$PLUGIN_FILE"; then
    echo "ERROR: failed to update Version: header in rankwiz-ai.php." >&2
    exit 1
fi
if ! grep -qE "RANKWIZ_VERSION',[[:space:]]*'${NEW_VERSION}'" "$PLUGIN_FILE"; then
    echo "ERROR: failed to update RANKWIZ_VERSION constant in rankwiz-ai.php." >&2
    exit 1
fi

# 3. readme.txt — Stable tag + changelog stanza.
#
# WPBUILD-004: the source readme.txt changelog must stay in sync with CHANGELOG.md.
# bump-version.sh now:
#   (a) updates the Stable tag line, AND
#   (b) regenerates the == Changelog == section from CHANGELOG.md so the source
#       file is never stale (previously only build.sh regenerated the changelog
#       into the STAGED copy; the committed source was perpetually behind).
#
# The regeneration converts the Markdown ## [X.Y.Z] / ### sections to WordPress
# readme.txt "= X.Y.Z =" / plain-text bullet format.
TMP=$(mktemp)

# (a) Update Stable tag.
sed -E "s/^Stable tag:[[:space:]]*[0-9]+\.[0-9]+\.[0-9]+/Stable tag: ${NEW_VERSION}/" \
    "$README_FILE" > "$TMP"
mv "$TMP" "$README_FILE"

if ! grep -qE "^Stable tag:[[:space:]]+${NEW_VERSION}\b" "$README_FILE"; then
    echo "ERROR: failed to update Stable tag in readme.txt." >&2
    exit 1
fi

# (b) Regenerate == Changelog == section from CHANGELOG.md.
# Strategy: replace everything from "== Changelog ==" to EOF with a fresh
# block generated from CHANGELOG.md. Uses awk to parse ## [X.Y.Z] stanzas
# into WordPress "= X.Y.Z =" blocks with bullet-prefixed body lines.
CHANGELOG_BLOCK=$(awk '
    /^## \[[0-9]+\.[0-9]+\.[0-9]+\]/ {
        # Extract version from "## [X.Y.Z] - YYYY-MM-DD"
        match($0, /\[([0-9]+\.[0-9]+\.[0-9]+)\]/, arr)
        if (in_block) printf "\n"
        printf "= %s =\n", arr[1]
        in_block = 1
        next
    }
    in_block && /^### / {
        # Section headers (### Added, ### Fixed, etc.) — skip, merge bullets
        next
    }
    in_block && /^- / {
        # Markdown bullets → WP readme bullets (strip leading "- ")
        sub(/^- /, "")
        # Trim backtick formatting (keep text)
        gsub(/`/, "")
        printf "* %s\n", $0
        next
    }
    in_block && /^$/ {
        # Blank lines between stanzas become a separator
        blank_count++
        if (blank_count == 2) {
            printf "\n"
            blank_count = 0
        }
        next
    }
    in_block && /^[^#]/ && !/^$/ {
        # Non-bullet prose lines (old changelog style) — include as-is
        gsub(/`/, "")
        printf "* %s\n", $0
        next
    }
' "$CHANGELOG")

# Replace the readme.txt changelog section with the regenerated block.
TMP=$(mktemp)
awk -v changelog="$CHANGELOG_BLOCK" '
    /^== Changelog ==/ {
        print "== Changelog =="
        print ""
        print changelog
        skip = 1
        next
    }
    skip { next }
    { print }
' "$README_FILE" > "$TMP"
mv "$TMP" "$README_FILE"

if ! grep -q "^= ${NEW_VERSION} =" "$README_FILE"; then
    echo "WARNING: changelog section for ${NEW_VERSION} not found in regenerated readme.txt." >&2
    echo "  Check that CHANGELOG.md has a '## [${NEW_VERSION}]' stanza with at least one bullet." >&2
fi

echo "Bumped to ${NEW_VERSION}."
echo "Edit CHANGELOG.md to expand release notes, then run:"
echo "  ./bin/build.sh"
