#!/usr/bin/env bash

set -euo pipefail

# Source common functions
SCRIPT_DIR=$(cd $(dirname $0);pwd)
source "${SCRIPT_DIR}/common.sh"

COMMON_FEATURES="openssl-vendored testexport failpoints"
CARGO_FLAGS="--features \"${COMMON_FEATURES}\""

setup_unit_test_environment() {
    log "Setting up environment for unit tests..."
    
    export RUST_BACKTRACE=1
    
    ensure_dirs

    # Start MinIO if not already running
    if python3 -c "import socket; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.settimeout(1); result = s.connect_ex(('127.0.0.1', ${DEFAULT_MINIO_PORT})); exit(0 if result == 0 else 1)" >/dev/null 2>&1; then
        log "Port ${DEFAULT_MINIO_PORT} is already in use. Skipping MinIO start."
    else
        # Start MinIO for tests that need it
        if ! start_minio; then
            log_error "Failed to start MinIO"
            exit 1
        fi
        # Kill MinIO on exit
        trap 'cleanup_unit_tests $?' ERR
        trap 'cleanup_unit_tests' EXIT INT TERM
    fi
    
    log "Unit test environment setup completed"
}

# Cleanup function specific to unit tests
cleanup_unit_tests() {
    local exit_code=${1:-0}
    local pid_file="${TEST_OUTPUT_DIR}/minio.pid"

    log "Cleaning up unit test services..."
    
    if [ -f "$pid_file" ]; then
        local pid=$(cat "$pid_file")
        if [ -n "$pid" ]; then
            log "Stopping MinIO (PID: $pid)..."
            kill -9 "$pid" 2>/dev/null || true
        fi
        # Remove the PID file after killing
        rm -f "$pid_file"
    else
        log "No MinIO PID file found. Skipping MinIO cleanup (assuming external service)."
    fi

    log "Unit test cleanup completed"
    return $exit_code
}

# Run unit tests with proper configuration
run_unit_tests() {
    log "Running unit tests..."
    
    cd "${PROJECT_ROOT}"
    
    local failed_tests=()
    local total_test_groups=0
    local passed_test_groups=0
    
    local test_commands=(
        "cargo test -p tici_shard -p tici_import -p tici_common -p tici_grpc"
        "cargo test -p tici-search-lib -p storage_backend"
        "cargo test ${CARGO_FLAGS} -- meta::reader::shard_cache::manager --test-threads 1"
        "cargo test ${CARGO_FLAGS} -- --skip status_server --skip meta::reader::shard_cache::manager"
        "MALLOC_CONF=\"prof:true,prof_active:false\" cargo test ${CARGO_FLAGS} -- status_server --test-threads 1"
    )
    
    local test_names=(
        "sub-packages (shard, import, common, grpc)"
        "sub-package (searchlib, storage_backend)"
        "tici (shard_cache - single thread)"
        "tici (main logic - excluded special cases)"
        "tici (status_server - jemalloc prof)"
    )
    
    # Run each test group
    for i in "${!test_commands[@]}"; do
        ((total_test_groups++))
        local test_name="${test_names[$i]}"
        local test_cmd="${test_commands[$i]}"
        
        log ""
        log "==================== Test Group $total_test_groups: $test_name ===================="
        log "Running: $test_cmd"
        
        if eval "$test_cmd"; then
            log "✓ Test group '$test_name' passed"
            ((passed_test_groups++))
        else
            log_error "✗ Test group '$test_name' failed"
            failed_tests+=("$test_name")
        fi
    done
    
    # Report results
    log ""
    log "==================== Unit Test Results ===================="
    log "Total test groups: $total_test_groups"
    log "Passed test groups: $passed_test_groups"
    log "Failed test groups: $((total_test_groups - passed_test_groups))"
    
    if [ ${#failed_tests[@]} -gt 0 ]; then
        log_error "Failed test groups:"
        for test in "${failed_tests[@]}"; do
            log_error "  - $test"
        done
        return 1
    else
        log "All unit tests passed! 🎉"
        return 0
    fi
}

# Display unit test information
show_unit_test_info() {
    log "Unit Test Environment Information:"
    log "  Project root: ${PROJECT_ROOT}"
    log "  Test output: ${TEST_OUTPUT_DIR}"
    log "  MinIO endpoint: 127.0.0.1:${DEFAULT_MINIO_PORT}"
    log "  Features: ${COMMON_FEATURES}"
    log ""
}

# Main unit test execution
main() {
    log "Starting unit test execution..."
    
    setup_unit_test_environment
    show_unit_test_info
    
    if run_unit_tests; then
        log "All unit tests completed successfully! 🎉"
        exit 0
    else
        log_error "Some unit tests failed"
        exit 1
    fi
}

case "${1:-}" in
    --help|-h)
        echo "Usage: $0 [options]"
        exit 0
        ;;
    "")
        main
        ;;
    *)
        log_error "Unknown option: $1"
        exit 1
        ;;
esac
