#!/bin/bash
# run-tests — BSD test framework entry point
#
# Usage:
#   test/bsd/run-tests --setup           # download images, provision VMs
#   test/bsd/run-tests --freebsd         # run tests on FreeBSD
#   test/bsd/run-tests --openbsd         # run tests on OpenBSD (not yet implemented)
#   test/bsd/run-tests --all             # run on all BSDs
#   test/bsd/run-tests --interactive     # boot FreeBSD, drop to SSH shell
#   test/bsd/run-tests --help            # show this help
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"

# ---------------------------------------------------------------------------
# Help
# ---------------------------------------------------------------------------

show_help() {
    cat <<'HELP'
quotatool BSD test framework

Usage: test/bsd/run-tests <mode> [options]

Modes:
  --setup             Download BSD images, provision VMs, verify deps
  --freebsd           Run all tests on FreeBSD
  --openbsd           Run all tests on OpenBSD
  --all               Run tests on all available BSDs
  --interactive <os>  Boot VM with quota filesystem, SSH in (freebsd|openbsd)
  --help              Show this help

Options:
  --verbose, -v       Show detailed test output (default: summary only)
  --ssh-port PORT     SSH port for VM (default: per-OS)
  --memory MB         VM RAM in MB (default: 2048)

Prerequisites:
  - KVM access (/dev/kvm)
  - QEMU, genisoimage, ssh, curl, xz
  - Run 'test/bsd/check-deps.sh' to verify

Setup (first time):
  test/bsd/run-tests --setup      # downloads images, provisions VMs
  test/bsd/run-tests --all        # run tests on all BSDs

What it does:
  1. Boots BSD VM from provisioned snapshot (~12s)
  2. Copies quotatool source into VM via scp
  3. Builds quotatool inside the VM (./configure && gmake)
  4. Creates UFS filesystem with quotas enabled
  5. Runs all test scripts
  6. Reports results, shuts down VM
HELP
}

# ---------------------------------------------------------------------------
# Parse arguments
# ---------------------------------------------------------------------------

MODE=""
VERBOSE=0
export VM_MEMORY="${VM_MEMORY:-2048}"

while [ $# -gt 0 ]; do
    case "$1" in
        --setup)       MODE="setup" ;;
        --freebsd)     MODE="freebsd" ;;
        --openbsd)     MODE="openbsd" ;;
        --all)         MODE="all" ;;
        --interactive) MODE="interactive"; INTERACTIVE_OS="${2:-}"; [ -n "$INTERACTIVE_OS" ] && shift ;;
        --verbose|-v)  VERBOSE=1 ;;
        --help|-h)     show_help; exit 0 ;;
        --ssh-port)    export VM_SSH_PORT="$2"; shift ;;
        --memory)      VM_MEMORY="$2"; shift ;;
        *)
            echo "Unknown option: $1" >&2
            echo "Run with --help for usage." >&2
            exit 1
            ;;
    esac
    shift
done

if [ -z "$MODE" ]; then
    show_help
    exit 0
fi

# ---------------------------------------------------------------------------
# Setup mode
# ---------------------------------------------------------------------------

do_setup() {
    echo ""
    echo "=== BSD Test Framework Setup ==="
    echo ""

    # Check dependencies first
    "$SCRIPT_DIR/check-deps.sh"
    echo ""

    # FreeBSD
    if [ -f "$SCRIPT_DIR/freebsd/setup.sh" ]; then
        echo "=== FreeBSD Setup ==="
        "$SCRIPT_DIR/freebsd/setup.sh"
    fi

    # OpenBSD (when implemented)
    if [ -f "$SCRIPT_DIR/openbsd/setup.sh" ]; then
        echo ""
        echo "=== OpenBSD Setup ==="
        "$SCRIPT_DIR/openbsd/setup.sh"
    fi

    echo ""
    echo "Setup complete. Run 'test/bsd/run-tests --all' to test."
}

# ---------------------------------------------------------------------------
# Test execution
# ---------------------------------------------------------------------------

run_tests_on() {
    local os="$1"

    source "$SCRIPT_DIR/lib/vm.sh"
    source "$SCRIPT_DIR/lib/fs-setup.sh"

    echo ""
    echo "  $os: booting..."

    if [ "$VERBOSE" -eq 1 ]; then
        # Verbose: show all infrastructure output
        vm_start "$os"
        vm_wait_ssh
    else
        # Quiet: suppress infrastructure noise
        vm_start "$os" >/dev/null 2>&1
        vm_wait_ssh >/dev/null 2>&1
    fi

    # Copy source into VM
    local tarball="/tmp/quotatool-src-$$.tar.gz"
    tar -C "$REPO_DIR" --exclude='.git' --exclude='test/bsd/images' \
        --exclude='test/kernels' --exclude='test/results' \
        --exclude='*.o' --exclude='*.d' \
        -czf "$tarball" .
    vm_copy_to "$tarball" /tmp/quotatool-src.tar.gz 2>/dev/null
    rm -f "$tarball"

    # Build inside VM
    echo "  $os: building..."
    vm_run "
        . /root/.profile 2>/dev/null
        rm -rf /tmp/quotatool
        mkdir -p /tmp/quotatool
        cd /tmp/quotatool
        tar xzf /tmp/quotatool-src.tar.gz
        autoconf
        ./configure --quiet
        gmake -j2 -s
    " >/dev/null 2>&1

    # Create quota filesystem
    echo "  $os: creating quota filesystem..."
    if [ "$VERBOSE" -eq 1 ]; then
        fs_create_ufs /mnt/quota-test 256M
    else
        fs_create_ufs /mnt/quota-test 256M >/dev/null 2>&1
    fi

    # Run tests — capture output
    echo "  $os: running tests..."
    local test_output
    local rc=0
    test_output=$(vm_run "bash /tmp/quotatool/test/bsd/guest-run-all.sh /mnt/quota-test" 2>&1) || rc=$?

    # Cleanup
    if [ "$VERBOSE" -eq 1 ]; then
        fs_teardown /mnt/quota-test
        vm_shutdown
    else
        fs_teardown /mnt/quota-test >/dev/null 2>&1
        vm_shutdown >/dev/null 2>&1
    fi

    # Display results
    if [ "$VERBOSE" -eq 1 ]; then
        echo ""
        echo "$test_output"
    fi

    # Extract and display summary line
    local summary
    summary=$(echo "$test_output" | grep "^TOTAL:")
    local failed
    failed=$(echo "$test_output" | grep "^FAILED:" || true)

    if [ $rc -eq 0 ]; then
        echo "  $os: $summary — PASS"
    else
        echo "  $os: $summary — FAIL"
        if [ -n "$failed" ]; then
            echo "  $os: $failed"
        fi
        # Show full output on failure even without --verbose
        if [ "$VERBOSE" -eq 0 ]; then
            echo ""
            echo "  Full output (re-run with --verbose to always see):"
            echo "$test_output"
        fi
    fi

    return $rc
}

# ---------------------------------------------------------------------------
# Interactive mode
# ---------------------------------------------------------------------------

do_interactive() {
    local os="${1:?Interactive mode requires --freebsd or --openbsd}"

    source "$SCRIPT_DIR/lib/vm.sh"
    source "$SCRIPT_DIR/lib/fs-setup.sh"

    echo ""
    echo "=== Interactive mode: $os ==="
    echo ""

    vm_start "$os"
    vm_wait_ssh

    # Copy and build
    echo "[interactive] Copying and building quotatool..."
    local tarball="/tmp/quotatool-src-$$.tar.gz"
    tar -C "$REPO_DIR" --exclude='.git' --exclude='test/bsd/images' \
        --exclude='test/kernels' --exclude='test/results' \
        --exclude='*.o' --exclude='*.d' \
        -czf "$tarball" .
    vm_copy_to "$tarball" /tmp/quotatool-src.tar.gz
    rm -f "$tarball"

    vm_run "
        . /root/.profile 2>/dev/null
        rm -rf /tmp/quotatool
        mkdir -p /tmp/quotatool
        cd /tmp/quotatool
        tar xzf /tmp/quotatool-src.tar.gz
        autoconf
        ./configure --quiet
        gmake -j2 -s
    "

    # Create quota filesystem
    fs_create_ufs /mnt/quota-test 256M

    local ssh_key="$SCRIPT_DIR/images/test-key"

    echo ""
    echo "========================================"
    echo "  Interactive $os VM ready"
    echo "========================================"
    echo ""
    echo "  quotatool: /tmp/quotatool/quotatool"
    echo "  quota fs:  /mnt/quota-test"
    echo "  test user: testuser (uid 60000)"
    echo ""
    echo "  Connect:   ssh -i $ssh_key -p $VM_SSH_PORT -o StrictHostKeyChecking=no root@localhost"
    echo "  Shutdown:  type 'exit' or 'shutdown -p now' in the SSH session"
    echo ""
    echo "Dropping to SSH shell..."
    echo ""

    # Drop to interactive SSH (no BatchMode, allocate PTY)
    ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
        -i "$ssh_key" -p "$VM_SSH_PORT" -t root@localhost

    echo ""
    echo "[interactive] SSH session ended. Cleaning up..."
    fs_teardown /mnt/quota-test
    vm_shutdown
}

# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

case "$MODE" in
    setup)
        do_setup
        ;;
    freebsd)
        echo ""
        echo "========================================"
        echo "  quotatool BSD tests"
        echo "========================================"
        run_tests_on freebsd
        ;;
    openbsd)
        echo ""
        echo "========================================"
        echo "  quotatool BSD tests"
        echo "========================================"
        run_tests_on openbsd
        ;;
    all)
        echo ""
        echo "========================================"
        echo "  quotatool BSD tests"
        echo "========================================"

        rc=0
        results=""

        if [ -f "$SCRIPT_DIR/images/freebsd-provisioned.qcow2" ]; then
            if run_tests_on freebsd; then
                results="${results}  FreeBSD 14.4:  PASS\n"
            else
                results="${results}  FreeBSD 14.4:  FAIL\n"
                rc=1
            fi
        else
            results="${results}  FreeBSD:       not set up\n"
            rc=1
        fi

        if [ -f "$SCRIPT_DIR/images/openbsd-provisioned.qcow2" ]; then
            if run_tests_on openbsd; then
                results="${results}  OpenBSD 7.8:   PASS\n"
            else
                results="${results}  OpenBSD 7.8:   FAIL\n"
                rc=1
            fi
        else
            results="${results}  OpenBSD:       not set up\n"
        fi

        echo ""
        echo "========================================"
        printf "$results"
        echo "========================================"

        exit $rc
        ;;
    interactive)
        if [ -z "$INTERACTIVE_OS" ] || { [ "$INTERACTIVE_OS" != "freebsd" ] && [ "$INTERACTIVE_OS" != "openbsd" ]; }; then
            echo "Usage: test/bsd/run-tests --interactive <freebsd|openbsd>" >&2
            exit 1
        fi
        do_interactive "$INTERACTIVE_OS"
        ;;
esac
