#!/usr/bin/env bash

# GoodMem Installer Test Runner
# Usage: ./run_tests.sh [options]
#
# This script runs the bats test suite for the GoodMem installer.
# It handles bats installation if needed and provides various test execution modes.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TESTS_DIR="$SCRIPT_DIR/tests"

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

# Print colored output
print_color() {
    local color="$1"
    shift
    echo -e "${color}$*${NC}"
}

# Check if bats is installed
check_bats() {
    if ! command -v bats >/dev/null 2>&1; then
        print_color "$RED" "❌ bats-core is not installed!"
        echo
        print_color "$YELLOW" "Install options:"
        echo "  Ubuntu/Debian: sudo apt-get install bats"
        echo "  macOS:         brew install bats-core"
        echo "  From source:   git clone https://github.com/bats-core/bats-core.git && cd bats-core && sudo ./install.sh /usr/local"
        echo
        return 1
    fi
    
    local version
    version=$(bats --version | head -n1)
    print_color "$GREEN" "✅ Found $version"
    return 0
}

# Show usage information
show_help() {
    echo "GoodMem Installer Test Runner"
    echo
    echo "Usage: $0 [OPTIONS]"
    echo
    echo "Options:"
    echo "  -h, --help              Show this help message"
    echo "  -v, --verbose           Run tests with verbose output"
    echo "  -f, --filter PATTERN    Run only tests matching pattern"
    echo "  -j, --jobs N            Run tests in parallel (N jobs)"
    echo "  -u, --unit              Run only unit tests (default)"
    echo "  -i, --integration       Run only integration tests"
    echo "  -a, --all               Run all tests (unit + integration)"
    echo "  --list                  List all available tests"
    echo
    echo "Examples:"
    echo "  $0                      # Run all unit tests"
    echo "  $0 -v                   # Run with verbose output"
    echo "  $0 -f dsn              # Run tests containing 'dsn'"
    echo "  $0 -j 4                 # Run tests in parallel"
    echo "  $0 -a                   # Run all tests including integration"
    echo "  $0 --list               # Show all available tests"
}

# List all available tests
list_tests() {
    print_color "$BLUE" "📋 Available tests:"
    echo
    print_color "$YELLOW" "Unit tests:"
    for test_file in "$TESTS_DIR"/*.bats; do
        if [[ -f "$test_file" ]]; then
            local name
            name=$(basename "$test_file" .bats)
            echo "  • $name"
        fi
    done
    
    echo
    print_color "$YELLOW" "Integration tests:"
    for test_file in "$TESTS_DIR"/integration/*.bats; do
        if [[ -f "$test_file" ]]; then
            local name
            name=$(basename "$test_file" .bats)
            echo "  • integration/$name"
        fi
    done
}

# Run unit tests
run_unit_tests() {
    local args=("$@")
    
    print_color "$BLUE" "🧪 Running unit tests..."
    cd "$TESTS_DIR"
    
    # Find all .bats files in the tests directory (excluding integration subdir)
    local test_files=()
    for file in *.bats; do
        if [[ -f "$file" ]]; then
            test_files+=("$file")
        fi
    done
    
    if [[ ${#test_files[@]} -eq 0 ]]; then
        print_color "$YELLOW" "⚠️  No unit test files found"
        return 0
    fi
    
    bats "${args[@]}" "${test_files[@]}"
}

# Run integration tests
run_integration_tests() {
    local args=("$@")
    
    print_color "$BLUE" "🔧 Running integration tests..."
    cd "$TESTS_DIR"
    
    # Find all .bats files in the integration directory
    local test_files=()
    for file in integration/*.bats; do
        if [[ -f "$file" ]]; then
            test_files+=("$file")
        fi
    done
    
    if [[ ${#test_files[@]} -eq 0 ]]; then
        print_color "$YELLOW" "⚠️  No integration test files found"
        return 0
    fi
    
    bats "${args[@]}" "${test_files[@]}"
}

# Run all tests
run_all_tests() {
    local args=("$@")
    
    print_color "$BLUE" "🚀 Running all tests..."
    cd "$TESTS_DIR"
    
    # Find all .bats files recursively
    local test_files=()
    while IFS= read -r -d '' file; do
        test_files+=("$file")
    done < <(find . -name "*.bats" -print0)
    
    if [[ ${#test_files[@]} -eq 0 ]]; then
        print_color "$YELLOW" "⚠️  No test files found"
        return 0
    fi
    
    bats "${args[@]}" "${test_files[@]}"
}

# Main execution
main() {
    local test_mode="unit"
    local verbose=false
    local filter=""
    local jobs=""
    local bats_args=()
    
    # Parse command line arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -v|--verbose)
                verbose=true
                bats_args+=("-t")
                shift
                ;;
            -f|--filter)
                if [[ -n "${2:-}" ]]; then
                    filter="$2"
                    bats_args+=("-f" "$filter")
                    shift 2
                else
                    print_color "$RED" "Error: --filter requires a pattern"
                    exit 1
                fi
                ;;
            -j|--jobs)
                if [[ -n "${2:-}" ]] && [[ "$2" =~ ^[0-9]+$ ]]; then
                    jobs="$2"
                    bats_args+=("-j" "$jobs")
                    shift 2
                else
                    print_color "$RED" "Error: --jobs requires a number"
                    exit 1
                fi
                ;;
            -u|--unit)
                test_mode="unit"
                shift
                ;;
            -i|--integration)
                test_mode="integration"
                shift
                ;;
            -a|--all)
                test_mode="all"
                shift
                ;;
            --list)
                list_tests
                exit 0
                ;;
            *)
                print_color "$RED" "Unknown option: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # Check if bats is available
    if ! check_bats; then
        exit 1
    fi
    
    echo
    
    # Check if tests directory exists
    if [[ ! -d "$TESTS_DIR" ]]; then
        print_color "$RED" "❌ Tests directory not found: $TESTS_DIR"
        exit 1
    fi
    
    # Run tests based on mode
    case "$test_mode" in
        unit)
            run_unit_tests "${bats_args[@]}"
            ;;
        integration)
            run_integration_tests "${bats_args[@]}"
            ;;
        all)
            run_all_tests "${bats_args[@]}"
            ;;
    esac
    
    local exit_code=$?
    
    echo
    if [[ $exit_code -eq 0 ]]; then
        print_color "$GREEN" "✅ All tests passed!"
    else
        print_color "$RED" "❌ Some tests failed!"
    fi
    
    exit $exit_code
}

# Only run main if script is executed directly (not sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi