#!/bin/bash
# =============================================================================
# Smart Module Test Runner (Pre-push)
# =============================================================================
# This script detects which modules have changed and runs their tests.
# Runs tests for modules with changes in commits being pushed.
#
# Supported modules:
# - backend: pytest tests/
# - frontend: npm test
# - executor: pytest tests/
# - executor_manager: pytest tests/
# - shared: pytest tests/
# - knowledge_engine: pytest tests/
# - knowledge_runtime: pytest tests/
# =============================================================================

set -e

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

# Get the range of commits being pushed
# For pre-push, we need to detect changes differently
get_changed_files() {
    # Try to get files from commits being pushed
    # First, check if we have stdin from pre-push hook
    if [ -t 0 ]; then
        # No stdin, use HEAD comparison
        git diff --name-only HEAD~1 HEAD 2>/dev/null || git diff --name-only HEAD 2>/dev/null || true
    else
        # Read from pre-push hook stdin
        while read local_ref local_sha remote_ref remote_sha; do
            if [ "$remote_sha" = "0000000000000000000000000000000000000000" ]; then
                # New branch
                git diff --name-only origin/main...$local_sha 2>/dev/null || git diff --name-only HEAD 2>/dev/null || true
            else
                git diff --name-only $remote_sha...$local_sha 2>/dev/null || true
            fi
        done
    fi
}

CHANGED_FILES=$(get_changed_files)

if [ -z "$CHANGED_FILES" ]; then
    echo -e "${GREEN}✅ No changed files to test${NC}"
    exit 0
fi

# Track test results
TESTS_RUN=0
TESTS_PASSED=0
TESTS_FAILED=0
TEST_RESULTS=()

# Function to run tests for a module
run_module_tests() {
    local module=$1
    local test_cmd=$2
    local working_dir=$3

    if [ ! -d "$working_dir" ]; then
        return 0
    fi

    echo -e "${BLUE}🧪 Running tests for $module...${NC}"

    # Check if tests directory exists
    if [ "$module" = "frontend" ]; then
        if [ ! -f "$working_dir/package.json" ]; then
            echo -e "${YELLOW}   ⚠️ No package.json found, skipping${NC}"
            return 0
        fi
    else
        if [ ! -d "$working_dir/tests" ]; then
            echo -e "${YELLOW}   ⚠️ No tests directory found, skipping${NC}"
            return 0
        fi
    fi

    TESTS_RUN=$((TESTS_RUN + 1))

    # Run tests
    cd "$working_dir"
    if eval "$test_cmd" 2>&1; then
        TESTS_PASSED=$((TESTS_PASSED + 1))
        TEST_RESULTS+=("  ✅ $module: PASSED")
        echo -e "${GREEN}   ✅ $module tests passed${NC}"
    else
        TESTS_FAILED=$((TESTS_FAILED + 1))
        TEST_RESULTS+=("  ❌ $module: FAILED")
        echo -e "${RED}   ❌ $module tests failed${NC}"
    fi
    cd - > /dev/null
}

# Project root
PROJECT_ROOT=$(git rev-parse --show-toplevel)

echo ""
echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE}🧪 Running Module Tests (Pre-push)${NC}"
echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}"
echo ""

# Check each module for changes and run tests
# Check each module for changes and run tests
# Backend (use parallel testing with -n 4 for faster execution)
BACKEND_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^backend/.*\.py$" || true)
if [ -n "$BACKEND_CHANGES" ]; then
    run_module_tests "backend" "uv run pytest tests/ -x -q --tb=short -n 4 2>/dev/null" "$PROJECT_ROOT/backend"
fi

# Frontend
FRONTEND_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^frontend/.*\.(ts|tsx|js|jsx)$" || true)
if [ -n "$FRONTEND_CHANGES" ]; then
    run_module_tests "frontend" "npm test -- --passWithNoTests --watchAll=false 2>/dev/null" "$PROJECT_ROOT/frontend"
fi

# Executor
EXECUTOR_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^executor/.*\.py$" || true)
if [ -n "$EXECUTOR_CHANGES" ]; then
    run_module_tests "executor" "uv run pytest tests/ -x -q --tb=short 2>/dev/null" "$PROJECT_ROOT/executor"
fi

# Executor Manager
EXECUTOR_MANAGER_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^executor_manager/.*\.py$" || true)
if [ -n "$EXECUTOR_MANAGER_CHANGES" ]; then
    run_module_tests "executor_manager" "uv run pytest tests/ -x -q --tb=short 2>/dev/null" "$PROJECT_ROOT/executor_manager"
fi

# Shared
SHARED_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^shared/.*\.py$" || true)
if [ -n "$SHARED_CHANGES" ]; then
    run_module_tests "shared" "uv run pytest tests/ -x -q --tb=short 2>/dev/null" "$PROJECT_ROOT/shared"
fi

# Knowledge Engine
KNOWLEDGE_ENGINE_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^knowledge_engine/" || true)
if [ -n "$KNOWLEDGE_ENGINE_CHANGES" ]; then
    run_module_tests "knowledge_engine" "uv run --group dev pytest tests/ -x -q --tb=short 2>/dev/null" "$PROJECT_ROOT/knowledge_engine"
fi

# Knowledge Runtime
KNOWLEDGE_RUNTIME_CHANGES=$(echo "$CHANGED_FILES" | grep -E "^knowledge_runtime/" || true)
if [ -n "$KNOWLEDGE_RUNTIME_CHANGES" ]; then
    run_module_tests "knowledge_runtime" "uv run --group dev pytest tests/ -x -q --tb=short 2>/dev/null" "$PROJECT_ROOT/knowledge_runtime"
fi
# Summary
echo ""
echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE}📊 Test Summary${NC}"
echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}"

if [ $TESTS_RUN -eq 0 ]; then
    echo -e "${GREEN}   No tests needed for changed files${NC}"
else
    for result in "${TEST_RESULTS[@]}"; do
        echo -e "$result"
    done
    echo ""
    echo -e "   Total: $TESTS_RUN | Passed: ${GREEN}$TESTS_PASSED${NC} | Failed: ${RED}$TESTS_FAILED${NC}"
fi

echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}"
echo ""

# Exit with failure if any tests failed (but allow --no-verify to skip)
if [ $TESTS_FAILED -gt 0 ]; then
    echo -e "${YELLOW}⚠️ Some tests failed. Use 'git push --no-verify' to skip.${NC}"
    exit 0  # Changed to 0 to not block, just warn
fi

exit 0
