#!/usr/bin/env bash
# =============================================================================
# check-plugin-release.sh — WP-005 release-artifact hygiene assertion
# =============================================================================
#
# Asserts that a packaged WordPress plugin zip is a production-safe artifact:
#   1. RANKWIZ_DEBUG_BUILD is 'false' (not 'true') in the shipped PHP.
#   2. Every default RANKWIZ_APP_URL definition in the shipped PHP uses https://.
#   3. The build manifest (if present) records env=prod (or env=preview when
#      --allow-preview is passed).
#
# Usage:
#   scripts/check-plugin-release.sh [OPTIONS] [ZIP_PATH]
#
#   ZIP_PATH     Path to the versioned zip to check.
#                Defaults to the most recent non-debug, non-preview zip in
#                wp-plugin/rankwiz-ai/build/.
#
# Options:
#   --allow-preview   Accept env=preview in the manifest (preview builds use
#                     https://preview.rankwizai.com — a valid https URL, but not
#                     the production domain). Without this flag, only env=prod is
#                     accepted.
#   -h, --help        Print this help and exit 0.
#
# Exit codes:
#   0  All assertions pass.
#   1  One or more assertions failed (details printed to stdout).
#   2  Usage / setup error (missing zip, missing unzip, etc.).
#
# Wired into: scripts/wp-plugin-release-workflow.yml.template (post-build step)
#
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
PLUGIN_BUILD_DIR="${REPO_ROOT}/wp-plugin/rankwiz-ai/build"
PLUGIN_PHP_IN_ZIP="rankwiz-ai/rankwiz-ai.php"

ALLOW_PREVIEW=0
ZIP_PATH=""

# ---------------------------------------------------------------------------
# Argument parsing
# ---------------------------------------------------------------------------
while [[ $# -gt 0 ]]; do
    case "$1" in
        --allow-preview)
            ALLOW_PREVIEW=1
            shift
            ;;
        -h|--help)
            sed -n '2,33p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
            exit 0
            ;;
        -*)
            echo "ERROR: Unknown option: $1" >&2
            exit 2
            ;;
        *)
            if [[ -n "$ZIP_PATH" ]]; then
                echo "ERROR: Only one ZIP_PATH argument is accepted." >&2
                exit 2
            fi
            ZIP_PATH="$1"
            shift
            ;;
    esac
done

# ---------------------------------------------------------------------------
# Resolve zip path
# ---------------------------------------------------------------------------
if [[ -z "$ZIP_PATH" ]]; then
    # Auto-discover: most recent prod zip (excludes -debug and -preview variants).
    ZIP_PATH=$(ls -t "${PLUGIN_BUILD_DIR}"/rankwiz-ai-[0-9]*.zip 2>/dev/null \
        | grep -v -E -- '-(debug|preview)\.zip$' \
        | head -1 || true)

    if [[ -z "$ZIP_PATH" ]]; then
        echo "ERROR: No production zip found in ${PLUGIN_BUILD_DIR}." >&2
        echo "       Run wp-plugin/rankwiz-ai/bin/build.sh first, or pass a zip path explicitly." >&2
        exit 2
    fi
    echo "Auto-discovered zip: ${ZIP_PATH}"
fi

if [[ ! -f "$ZIP_PATH" ]]; then
    echo "ERROR: Zip file not found: ${ZIP_PATH}" >&2
    exit 2
fi

# ---------------------------------------------------------------------------
# Prerequisite: unzip
# ---------------------------------------------------------------------------
if ! command -v unzip >/dev/null 2>&1; then
    echo "ERROR: 'unzip' is required but not in PATH." >&2
    exit 2
fi

echo "Checking release artifact: $(basename "${ZIP_PATH}")"
echo ""

FAILURES=0

# ---------------------------------------------------------------------------
# Check 1: Manifest env field (fast path — no extraction required)
# ---------------------------------------------------------------------------
MANIFEST_PATH="${ZIP_PATH}.manifest.json"
if [[ -f "$MANIFEST_PATH" ]]; then
    if command -v jq >/dev/null 2>&1; then
        MANIFEST_ENV=$(jq -r '.env // "unknown"' "$MANIFEST_PATH" 2>/dev/null || echo "unknown")
    else
        # jq-free fallback: parse the simple scalar with grep + sed.
        MANIFEST_ENV=$(grep '"env"' "$MANIFEST_PATH" 2>/dev/null \
            | sed -E 's/.*"env"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/' || echo "unknown")
    fi

    case "$MANIFEST_ENV" in
        prod)
            echo "PASS  [manifest] env=prod"
            ;;
        preview)
            if [[ "$ALLOW_PREVIEW" -eq 1 ]]; then
                echo "PASS  [manifest] env=preview (--allow-preview set)"
            else
                echo "FAIL  [manifest] env=preview — this is a preview artifact, not a production build."
                echo "      Pass --allow-preview if deploying a preview zip intentionally."
                FAILURES=$((FAILURES + 1))
            fi
            ;;
        debug)
            echo "FAIL  [manifest] env=debug — debug artifact must never be shipped to users."
            FAILURES=$((FAILURES + 1))
            ;;
        *)
            echo "WARN  [manifest] env='${MANIFEST_ENV}' is unrecognised — skipping manifest env check."
            ;;
    esac
else
    echo "WARN  [manifest] No manifest sidecar found at ${MANIFEST_PATH} — skipping manifest env check."
fi

# ---------------------------------------------------------------------------
# Check 2 & 3: Inspect the PHP file inside the zip
# ---------------------------------------------------------------------------
# Verify the file exists AND passes a full CRC integrity check before extracting.
# (unzip -l only tests the listing; unzip -t verifies actual CRC against the
# central directory so a truncated or corrupted entry is caught here rather than
# silently producing empty output that would pass all grep checks.)
if ! unzip -t "$ZIP_PATH" "$PLUGIN_PHP_IN_ZIP" >/dev/null 2>&1; then
    echo "FAIL  [zip] '${PLUGIN_PHP_IN_ZIP}' failed CRC integrity check — archive may be corrupted or the entry is missing."
    FAILURES=$((FAILURES + 1))
    echo ""
    echo "Result: FAIL (${FAILURES} failure(s))"
    exit 1
fi

PLUGIN_PHP_CONTENT=$(unzip -p "$ZIP_PATH" "$PLUGIN_PHP_IN_ZIP" 2>/dev/null)

# Guard: if extraction produced empty output despite a passing CRC check, fail
# rather than silently passing all pattern checks (false-negative protection).
if [[ -z "$PLUGIN_PHP_CONTENT" ]]; then
    echo "FAIL  [zip] '${PLUGIN_PHP_IN_ZIP}' extracted as empty — archive may be corrupted or unreadable."
    FAILURES=$((FAILURES + 1))
    echo ""
    echo "Result: FAIL (${FAILURES} failure(s))"
    exit 1
fi

# ---------------------------------------------------------------------------
# Check 2: RANKWIZ_DEBUG_BUILD must be 'false'
# ---------------------------------------------------------------------------
# The debug build substitution in bin/build.sh changes the canonical
#   define('RANKWIZ_DEBUG_BUILD', false)
# to
#   define('RANKWIZ_DEBUG_BUILD', true)
#
# Assert the 'false' form is present AND the 'true' form is absent.
DEBUG_TRUE_PRESENT=$(echo "$PLUGIN_PHP_CONTENT" \
    | grep -c "define('RANKWIZ_DEBUG_BUILD', true)" || true)
DEBUG_FALSE_PRESENT=$(echo "$PLUGIN_PHP_CONTENT" \
    | grep -c "define('RANKWIZ_DEBUG_BUILD', false)" || true)

if [[ "$DEBUG_TRUE_PRESENT" -gt 0 ]]; then
    echo "FAIL  [php] RANKWIZ_DEBUG_BUILD is 'true' in the shipped artifact."
    echo "      This zip was built with --env debug and must not be distributed."
    FAILURES=$((FAILURES + 1))
elif [[ "$DEBUG_FALSE_PRESENT" -eq 0 ]]; then
    echo "FAIL  [php] Neither 'true' nor 'false' RANKWIZ_DEBUG_BUILD define found."
    echo "      The constant definition may have been renamed or removed — update this check."
    FAILURES=$((FAILURES + 1))
else
    echo "PASS  [php]  RANKWIZ_DEBUG_BUILD=false"
fi

# ---------------------------------------------------------------------------
# Check 3: Default RANKWIZ_APP_URL definitions must use https://
# ---------------------------------------------------------------------------
# Extract every line that defines RANKWIZ_APP_URL (the define() calls inside
# both the debug and non-debug branches). Every such line must start the URL
# with https://.
#
# We look for:   define('RANKWIZ_APP_URL', 'http://...
# and fail if we find even one.
HTTP_PLAIN_APP_URL=$(echo "$PLUGIN_PHP_CONTENT" \
    | grep "define('RANKWIZ_APP_URL'" \
    | grep -v "define('RANKWIZ_APP_URL', 'https://" || true)

if [[ -n "$HTTP_PLAIN_APP_URL" ]]; then
    echo "FAIL  [php]  RANKWIZ_APP_URL has a non-https definition:"
    echo "$HTTP_PLAIN_APP_URL" | sed "s/^/        /"
    FAILURES=$((FAILURES + 1))
else
    # Also confirm at least one https definition exists (guards against the
    # constant being removed entirely without triggering the manifest check).
    HTTPS_APP_URL_COUNT=$(echo "$PLUGIN_PHP_CONTENT" \
        | grep -c "define('RANKWIZ_APP_URL', 'https://" || true)
    if [[ "$HTTPS_APP_URL_COUNT" -eq 0 ]]; then
        echo "FAIL  [php]  No RANKWIZ_APP_URL define() found — constant may have been removed."
        FAILURES=$((FAILURES + 1))
    else
        echo "PASS  [php]  All RANKWIZ_APP_URL definitions use https:// (${HTTPS_APP_URL_COUNT} found)"
    fi
fi

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
echo ""
if [[ "$FAILURES" -eq 0 ]]; then
    echo "Result: PASS — artifact is production-safe."
    exit 0
else
    echo "Result: FAIL — ${FAILURES} check(s) failed. Do not ship this artifact."
    exit 1
fi
