#!/bin/bash
# Wrapper script to automate the release process for chroma-mcp-server

# Exit immediately if a command exits with a non-zero status.
set -e

# --- Configuration ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
PACKAGE_NAME="chroma-mcp-server"
PYPI_URL="https://pypi.org/pypi"
TESTPYPI_URL="https://test.pypi.org/pypi"
PYPROJECT_PATH="${PROJECT_ROOT}/pyproject.toml"

# --- Dependency Check ---
if ! command -v curl &> /dev/null; then
    echo "❌ ERROR: curl is required but not found. Please install curl." >&2
    exit 1
fi
if ! command -v jq &> /dev/null; then
    echo "❌ ERROR: jq is required but not found. Please install jq (e.g., brew install jq)." >&2
    exit 1
fi
if ! command -v sed &> /dev/null; then
    echo "❌ ERROR: sed is required but not found." >&2
    exit 1
fi
if ! command -v grep &> /dev/null; then
    echo "❌ ERROR: grep is required but not found." >&2
    exit 1
fi

# --- Argument Parsing ---
VERSION=""
SKIP_TESTPYPI=false
TEST_ONLY=false
YES_FLAG=false
UPDATE_TARGET="prod" # Default

# Flags to track if options were set via command line
VERSION_SET=false
SKIP_TESTPYPI_SET=false
TEST_ONLY_SET=false
UPDATE_TARGET_SET=false

usage() {
    echo "Usage: $0 [-h] [-y] [--skip-testpypi] [--test-only] [--update-target <prod|test>] [--version VERSION]"
    echo ""
    echo "Automates the release process: TestPyPI build & test -> Prod PyPI build & publish -> Update Cursor Config."
    echo ""
    echo "Options:"
    echo "  -h, --help           Show this help message and exit."
    echo "  -y, --yes            Automatically answer yes to confirmation prompts (non-interactive)."
    echo "  --skip-testpypi      Skip the TestPyPI build and local install test steps."
    echo "  --test-only          Only perform the TestPyPI build and local install test, then exit."
    echo "  --update-target <prod|test>  Install version from prod (PyPI) or test (TestPyPI) for Cursor use (default: prod)."
    echo "  --version VERSION    Specify the version number to release directly."
    echo ""
    echo "If --version is not provided in interactive mode, you will be prompted."
    exit 0
}

# --- Helper Functions ---
check_if_version_exists() {
    local pkg_name="$1"
    local version_to_check="$2"
    local index_url="$3"
    local index_name="$4"

    echo "  Checking if version $version_to_check exists on $index_name..."
    # Use curl to get package info, jq to check if version exists in releases
    if curl -s "$index_url/$pkg_name/$version_to_check/json" | jq -e '(.info.version == "'"$version_to_check"'")' > /dev/null; then
        echo "  ❌ ERROR: Version $version_to_check already exists on $index_name!" >&2
        return 1 # Indicate failure (version exists)
    else
        # Check if the overall package fetch failed (e.g., 404), indicating version likely doesn't exist
        if ! curl -s -f "$index_url/$pkg_name/json" > /dev/null; then
             echo "  Package $pkg_name not found on $index_name (or network error). Assuming version $version_to_check does not exist."
             return 0 # Indicate success (version likely doesn't exist)
        fi
        echo "  Version $version_to_check does not appear to exist on $index_name. Proceeding."
        return 0 # Indicate success (version does not exist)
    fi
}

get_current_version() {
    if [ ! -f "$PYPROJECT_PATH" ]; then
        echo "❌ ERROR: pyproject.toml not found at $PYPROJECT_PATH" >&2
        return 1
    fi
    # Extract version using grep -E and the user's corrected sed -E command
    current_ver=$(grep -E '^version\s*=\s*\".+\"' "$PYPROJECT_PATH" | sed -E 's/^version[\ ]*=[\ ]*\"([0-9.]+)\"$/\1/')
    if [ -z "$current_ver" ]; then
        echo "❌ ERROR: Could not extract current version from $PYPROJECT_PATH using grep/sed." >&2
        return 1
    fi
    echo "$current_ver"
    return 0
}

suggest_next_patch_version() {
    local current_version="$1"
    # Basic suggestion: increments the last number after the last dot
    local prefix=$(echo "$current_version" | sed -E 's/\.[0-9]+$//')
    local patch=$(echo "$current_version" | sed -E 's/^.*\.(.*)/\1/')
    # Check if patch is purely numeric
    if [[ "$patch" =~ ^[0-9]+$ ]]; then
        local next_patch=$((patch + 1))
        echo "${prefix}.${next_patch}"
    else
        # Cannot auto-increment non-numeric patch (e.g., pre-releases)
        echo "$current_version" # Suggest current as fallback
    fi
}

is_version_greater() {
    local ver1="$1" # New version
    local ver2="$2" # Old version
    # Returns 0 if ver1 > ver2, 1 otherwise
    if [ "$ver1" == "$ver2" ]; then
        return 1 # Not greater if equal
    fi
    # Use sort -V: If the sorted list's last element is ver1, then ver1 > ver2
    if [ "$(printf '%s\n' "$ver1" "$ver2" | sort -V | tail -n 1)" == "$ver1" ]; then
        return 0 # ver1 is greater
    else
        return 1 # ver1 is not greater
    fi
}

validate_version_format() {
    local ver="$1"
    # Basic X.Y.Z format check, allows for suffixes like -alpha, .rc1 etc.
    if ! [[ "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+([a-zA-Z0-9.-]*)?$ ]]; then
        echo "  ⚠️ Warning: Version format '$ver' seems unusual. Expected X.Y.Z or similar."
        # Allow proceeding but warn
    fi
    return 0
}

# --- Main Script Logic ---

# Change to the project root directory to ensure paths are correct
cd "$PROJECT_ROOT"
echo "ℹ️ Changed working directory to project root: $PROJECT_ROOT"

# CHANGELOG.md Reminder
echo "🔔 REMINDER: Before proceeding with the release, ensure you have:"
echo "   1. Verified all tests are passing with adequate coverage"
echo "   2. Updated CHANGELOG.md with all notable changes in this version"
echo "   3. Update of version number in pyproject.toml will be done automatically"
echo ""

# Argument parsing loop
while [[ $# -gt 0 ]]; do
    key="$1"
    case $key in
        -h|--help)
            usage
            ;;
        -y|--yes)
            YES_FLAG=true
            shift # past argument
            ;;
        --skip-testpypi)
            SKIP_TESTPYPI=true
            SKIP_TESTPYPI_SET=true # Track that it was set
            shift # past argument
            ;;
        --test-only)
            TEST_ONLY=true
            TEST_ONLY_SET=true # Track that it was set
            shift # past argument
            ;;
        --update-target)
            if [[ "$2" == "prod" || "$2" == "test" ]]; then
                UPDATE_TARGET="$2"
                UPDATE_TARGET_SET=true # Track that it was set
                shift # past argument
                shift # past value
            else
                echo "❌ ERROR: --update-target must be 'prod' or 'test'" >&2
                usage
            fi
            ;;
        --version)
            if [ -n "$2" ]; then
                VERSION="$2"
                VERSION_SET=true # Track that it was set
                shift # past argument
                shift # past value
            else
                echo "❌ ERROR: --version requires an argument." >&2
                usage
            fi
            ;;
        *)    # unknown option
            echo "❌ ERROR: Unknown option: $1" >&2
            usage
            ;;
    esac
done

# --- Interactive Prompts (if not -y and flags not set) ---
if [ "$YES_FLAG" = false ]; then
    echo "🔧 Entering interactive configuration mode (options not set via flags)..."
    
    # Prompt for Update Target
    if [ "$UPDATE_TARGET_SET" = false ]; then
        read -p "  Update target for local UVX installation? (prod/test) [prod]: " target_choice
        UPDATE_TARGET=${target_choice:-$UPDATE_TARGET} # Default to prod if empty
        if [[ "$UPDATE_TARGET" != "prod" && "$UPDATE_TARGET" != "test" ]]; then
            echo "  ❌ ERROR: Invalid target. Please enter 'prod' or 'test'." >&2
            exit 1
        fi
        echo "  Using update target: $UPDATE_TARGET"
    fi

    # Prompt for Test-Only (only if target is test)
    if [ "$TEST_ONLY_SET" = false ] && [ "$UPDATE_TARGET" = "test" ]; then
        read -p "  Run TestPyPI phase ONLY (--test-only)? (y/n) [n]: " test_only_choice
        if [[ ${test_only_choice:-\"n\"} =~ ^[Yy]$ ]]; then
            TEST_ONLY=true
        else
            TEST_ONLY=false
        fi
        echo "  Run TestPyPI only: $TEST_ONLY"
    fi

    # Prompt for Skip-TestPyPI (only if target is prod)
    if [ "$SKIP_TESTPYPI_SET" = false ] && [ "$UPDATE_TARGET" = "prod" ]; then
        read -p "  Skip TestPyPI build/test phase (--skip-testpypi)? (y/n) [n]: " skip_testpypi_choice
        if [[ ${skip_testpypi_choice:-\"n\"} =~ ^[Yy]$ ]]; then
            SKIP_TESTPYPI=true
        else
            SKIP_TESTPYPI=false
        fi
        echo "  Skip TestPyPI phase: $SKIP_TESTPYPI"
    fi

    # Prompt for Version (if not set via flag)
    if [ "$VERSION_SET" = false ]; then
        CURRENT_VERSION=$(get_current_version)
        if [ $? -ne 0 ]; then exit 1; fi
        SUGGESTED_VERSION=$(suggest_next_patch_version "$CURRENT_VERSION")
        echo "  Current version in pyproject.toml: $CURRENT_VERSION"

        while true; do
            read -p "  Enter the new version number (suggested: $SUGGESTED_VERSION): " entered_version
            if [ -z "$entered_version" ]; then
                entered_version="$SUGGESTED_VERSION"
                echo "  Using suggested version: $entered_version"
            fi
            validate_version_format "$entered_version"
            if is_version_greater "$entered_version" "$CURRENT_VERSION"; then
                 read -p "  Confirm release version $entered_version? (y/n) " -n 1 -r
                 echo
                 if [[ $REPLY =~ ^[Yy]$ ]]; then
                     VERSION="$entered_version"
                     break
                 else
                     echo "  Version not confirmed. Please try again."
                 fi
            else
                echo "  ❌ ERROR: New version '$entered_version' must be greater than current version '$CURRENT_VERSION'." >&2
            fi
        done
    fi
fi

# --- Version Validation (if provided via flag) ---
if [ "$VERSION_SET" = true ]; then
    validate_version_format "$VERSION"
    # Add check against current version if needed, though less critical if flag is used explicitly
    # CURRENT_VERSION=$(get_current_version)
    # if ! is_version_greater "$VERSION" "$CURRENT_VERSION"; then 
    #    echo "❌ ERROR: Specified version $VERSION is not greater than current version $CURRENT_VERSION." >&2
    #    exit 1
    # fi
fi

# Final check: Ensure VERSION is determined
if [ -z "$VERSION" ]; then
    echo "❌ ERROR: Release version could not be determined." >&2
    exit 1
fi

echo ""
echo "🚀 Starting Release Process for Version: $VERSION"
echo "--------------------------------------------------"
echo "Configuration:"
echo "  Skip TestPyPI Build/Test: $SKIP_TESTPYPI"
echo "  TestPyPI Only:            $TEST_ONLY"
echo "  Update Target for Cursor: $UPDATE_TARGET"
echo "  Non-interactive:          $YES_FLAG"
echo "--------------------------------------------------"

# Confirmation prompt
if [ "$YES_FLAG" = false ]; then
    read -p "Proceed with this release plan? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Release cancelled by user."
        exit 1
    fi
fi

# --- TestPyPI Phase ---
if [ "$SKIP_TESTPYPI" = false ]; then
    echo ""
    echo "📦 Phase 1: Building and Publishing to TestPyPI..."
    
    # Check if version already exists on TestPyPI BEFORE publishing
    check_if_version_exists "$PACKAGE_NAME" "$VERSION" "$TESTPYPI_URL" "TestPyPI"
    if [ $? -ne 0 ]; then exit 1; fi # Exit if version exists

    # Call publish script (which updates pyproject.toml)
    echo "  Calling publish.sh to build and publish to TestPyPI..."
    "${SCRIPT_DIR}/publish.sh" -t -y -v "$VERSION"
    if [ $? -ne 0 ]; then echo "❌ ERROR: Failed to publish to TestPyPI."; exit 1; fi
    echo "✅ Successfully published to TestPyPI."

    echo ""
    echo "🔧 Phase 2: Testing Local Installation..."
    "${SCRIPT_DIR}/test_uvx_install.sh"
    if [ $? -ne 0 ]; then echo "❌ ERROR: Local installation test failed."; exit 1; fi
    echo "✅ Local installation test successful."

    if [ "$TEST_ONLY" = true ]; then
        echo ""
        echo "✅ TestPyPI phase complete (--test-only specified). Exiting."
        exit 0
    fi
else
    echo "⏩ Skipping TestPyPI build and test phases."
fi

# --- Production Phase ---
echo ""
echo "📦 Phase 3: Building and Publishing to Production PyPI..."

# Check if version already exists on Production PyPI BEFORE publishing
check_if_version_exists "$PACKAGE_NAME" "$VERSION" "$PYPI_URL" "Production PyPI"
if [ $? -ne 0 ]; then exit 1; fi # Exit if version exists

# Extra confirmation for production unless -y is set
if [ "$YES_FLAG" = false ]; then
    read -p "🚨 REALLY publish version $VERSION to Production PyPI? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "Production release cancelled by user."
        exit 1
    fi
fi

# Call publish script (which updates pyproject.toml again if needed, harmless)
"${SCRIPT_DIR}/publish.sh" -p -y -v "$VERSION"
if [ $? -ne 0 ]; then echo "❌ ERROR: Failed to publish to Production PyPI."; exit 1; fi
echo "✅ Successfully published to Production PyPI."

# --- Update Phase ---
echo ""
echo "🔧 Phase 4: Installing Release Version for Local UVX (Target: $UPDATE_TARGET)..."

INSTALL_ARGS=""
STRATEGY_ARG=""
PACKAGE_SPEC="$PACKAGE_NAME@$VERSION"

if [ "$UPDATE_TARGET" == "test" ]; then
    echo "  Installing version $VERSION from TestPyPI for local uvx command..."
    INSTALL_ARGS="--default-index $TESTPYPI_URL --index $PYPI_URL"
    STRATEGY_ARG="--index-strategy unsafe-best-match"
else
    echo "  Installing version $VERSION from PyPI for local uvx command..."
    # INSTALL_ARGS="--refresh --default-index $PYPI_URL" # Explicitly use PyPI
    INSTALL_ARGS="--refresh" # Avoid using default-index for pypi as this does not work
fi

install_command="uvx ${INSTALL_ARGS} ${STRATEGY_ARG} ${PACKAGE_SPEC}"
echo "  Running: $install_command"
eval $install_command # Use eval to handle args correctly

if [ $? -ne 0 ]; then echo "❌ ERROR: Failed to install $UPDATE_TARGET version $VERSION locally via uvx."; exit 1; fi
echo "  ✅ $UPDATE_TARGET version $VERSION installed for local uvx command."

echo "  Refreshing local UVX cache (may not be necessary with direct install)..."
if command -v uvx &> /dev/null; then
    # Refresh might still help ensure internal links are updated
    uvx --refresh $PACKAGE_NAME --version 
    echo "  ✅ UVX cache refreshed (or attempted)."
else
     echo "  ⚠️ UVX command not found, skipping cache refresh."
fi

echo ""
echo "🎉 Release process for $VERSION completed successfully!"
echo "ℹ️ Remember to commit and push the updated pyproject.toml and potentially tag the release in Git."
echo "ℹ️ Restart Cursor or the MCP Server if needed to pick up the new version."

exit 0 