#!/bin/bash

# Script to run MCP Inspector tests for Kafka Schema Registry MCP Server
# Tests against released Docker images

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
DOCKER_VERSION="${DOCKER_VERSION:-stable}"
SKIP_ENV_SETUP="${SKIP_ENV_SETUP:-false}"
CLEANUP_AFTER="${CLEANUP_AFTER:-true}"

# Function to print colored output
print_status() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

# Function to check if Schema Registry is running
check_schema_registry() {
    local port=$1
    local max_attempts=30
    local attempt=0
    
    print_status "Checking Schema Registry on port $port..."
    while [ $attempt -lt $max_attempts ]; do
        if curl -s "http://localhost:$port" > /dev/null 2>&1; then
            print_status "Schema Registry is ready on port $port"
            return 0
        fi
        attempt=$((attempt + 1))
        sleep 2
    done
    
    print_error "Schema Registry failed to start on port $port"
    return 1
}

# Function to start test environment
start_test_environment() {
    local mode=${1:-multi}  # multi | single
    if [ "$SKIP_ENV_SETUP" = "true" ]; then
        print_warning "Skipping environment setup (SKIP_ENV_SETUP=true)"
        return 0
    fi
    
    print_status "Starting test environment..."
    cd "$PROJECT_ROOT/tests"
    
    if [ -f "./start_test_environment.sh" ]; then
        if [[ "$mode" == "single" || "$mode" == "dev" ]]; then
            ./start_test_environment.sh dev
            # Wait for DEV registry only
            check_schema_registry 38081
        else
            ./start_test_environment.sh multi
            # Wait for registries defined in tests/docker-compose.yml
            # DEV registry
            check_schema_registry 38081
            # PROD registry
            check_schema_registry 38082
        fi
    else
        print_error "Test environment setup script not found!"
        exit 1
    fi
}

# Function to stop test environment
stop_test_environment() {
    if [ "$CLEANUP_AFTER" = "false" ]; then
        print_warning "Keeping test environment running (CLEANUP_AFTER=false)"
        return 0
    fi
    
    print_status "Stopping test environment..."
    cd "$PROJECT_ROOT/tests"
    
    if [ -f "./stop_test_environment.sh" ]; then
        ./stop_test_environment.sh clean
    fi
}

# Function to run inspector tests
run_inspector_tests() {
    local config_file=$1
    local test_name=$2
    
    print_status "Running Inspector test: $test_name"
    print_status "Using Docker image: aywengo/kafka-schema-reg-mcp:$DOCKER_VERSION"
    
    cd "$SCRIPT_DIR"
    
    # Create a temp config file and ensure readable permissions
    local temp_config
    temp_config="$SCRIPT_DIR/config/.temp.inspector-config.json"

    trap 'rm -f "$temp_config"' EXIT
    # Update config file to use the specified Docker version
    sed "s/:stable/:$DOCKER_VERSION/g" "$config_file" > "$temp_config"
    chmod 644 "$temp_config"

    print_status "Generated temp config: $temp_config"

    # Validate jq availability
    if ! command -v jq >/dev/null 2>&1; then
        print_error "jq is required to parse Inspector config. Please install jq."
        exit 1
    fi

    # Extract server config (first entry)
    local server_key
    server_key=$(jq -r '.mcpServers | keys[0]' "$temp_config")
    if [ -z "$server_key" ] || [ "$server_key" = "null" ]; then
        print_error "Invalid Inspector config: no mcpServers entry found"
        exit 1
    fi

    local server_command
    server_command=$(jq -r ".mcpServers[\"$server_key\"].command" "$temp_config")
    if [ -z "$server_command" ] || [ "$server_command" = "null" ]; then
        print_error "Invalid Inspector config: missing command"
        exit 1
    fi

    # Build args array from JSON
    local -a raw_args
    while IFS=$'\n' read -r line; do
        raw_args+=("$line")
    done < <(jq -r ".mcpServers[\"$server_key\"].args[]" "$temp_config")

    # Guard: args must contain at least the image as the last token
    local raw_len=${#raw_args[@]}
    if [ "$raw_len" -lt 1 ]; then
        print_error "Invalid Inspector config: args array is empty"
        exit 1
    fi

    # Separate image (last arg) from options
    local image_arg_idx=$((raw_len - 1))
    local image_arg="${raw_args[$image_arg_idx]}"

    # Filter out any placeholder env (-e KEY) from raw args before the image
    local -a base_opts
    local idx=0
    local limit=$image_arg_idx
    while [ $idx -lt $limit ]; do
        if [ "${raw_args[$idx]}" = "-e" ]; then
            # skip "-e" and following key token
            idx=$((idx + 2))
            continue
        fi
        base_opts+=("${raw_args[$idx]}")
        idx=$((idx + 1))
    done

    # Ensure we connect to the compose network so the container can reach registries by service name
    local -a docker_network_opts
    local has_network=false
    for opt in "${base_opts[@]}"; do
        if [ "$opt" = "--network" ]; then
            has_network=true
            break
        fi
    done
    if [ "$has_network" = false ]; then
        docker_network_opts=("--network" "kafka-test-network")
    fi

    # Build env pairs (-e KEY=VALUE) and map URLs to compose service names
    local -a env_pairs
    local env_len
    env_len=$(jq -r ".mcpServers[\"$server_key\"].env | length" "$temp_config")
    if [ "$env_len" != "0" ]; then
        while IFS=$'\t' read -r key value; do
            local final_value="$value"
            case "$key" in
                SCHEMA_REGISTRY_URL|SCHEMA_REGISTRY_URL_1)
                    final_value="http://schema-registry-dev:8081"
                    ;;
                SCHEMA_REGISTRY_URL_2)
                    final_value="http://schema-registry-prod:8082"
                    ;;
            esac
            env_pairs+=("-e" "${key}=${final_value}")
        done < <(jq -r ".mcpServers[\"$server_key\"].env | to_entries[] | [.key, (.value|tostring)] | @tsv" "$temp_config")
    fi

    # Compose final args: options + network + env pairs + image
    local -a final_args
    final_args=("${base_opts[@]}" "${docker_network_opts[@]}" "${env_pairs[@]}" "$image_arg")

    print_status "Launching Inspector with server: $server_command ${final_args[*]}"
    npx @mcpjam/inspector "$server_command" "${final_args[@]}"
}

# Main execution
main() {
    print_status "Starting MCP Inspector tests for Kafka Schema Registry MCP"
    print_status "Docker version: $DOCKER_VERSION"

    # Desired config name (maps to config/inspector-config-<name>.json)
    local selected_name="${1:-stable}"
    local config_path="$SCRIPT_DIR/config/inspector-config-${selected_name}.json"

    # Validate config exists
    if [ ! -f "$config_path" ]; then
        print_error "Config file not found: $config_path"
        print_warning "Available configs:"
        ls -1 "$SCRIPT_DIR/config" | sed 's/^/  - /'
        exit 1
    fi

    # Decide environment mode based on name
    local env_mode="single"
    if echo "$selected_name" | grep -qi "multi"; then
        env_mode="multi"
    fi

    # Change to inspector-tests directory
    cd "$SCRIPT_DIR"
    
    # Install dependencies if needed
    if [ ! -d "node_modules" ]; then
        print_status "Installing npm dependencies..."
        npm install
    fi
    
    # Start test environment based on mode
    start_test_environment "$env_mode"

    # Run the selected test
    run_inspector_tests "$config_path" "$selected_name"

    # Stop test environment
    stop_test_environment
    
    print_status "Inspector tests completed!"
}

# Run main function
main "$@"
