#!/usr/bin/env bash
set -euo pipefail;

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
export FETCHML_REPO_ROOT="$repo_root"

# Parse arguments
env="dev"
native_mode=false

while [[ $# -gt 0 ]]; do
    case "$1" in
        --native)
            native_mode=true
            shift
            ;;
        dev|prod)
            env="$1"
            shift
            ;;
        --help|-h)
            echo "Usage: $0 [dev|prod] [--native]"
            echo ""
            echo "Options:"
            echo "  dev|prod    Environment to test (default: dev)"
            echo "  --native    Also test native libraries (C++ integration)"
            echo "  --help      Show this help"
            exit 0
            ;;
        *)
            echo "Unknown option: $1" >&2
            echo "Usage: $0 [dev|prod] [--native]" >&2
            exit 2
            ;;
    esac
done

# Native library smoke test (merged from smoke-test-native.sh)
if [[ "$native_mode" == true ]]; then
    echo "=== FetchML Native Libraries Smoke Test ==="
    echo ""

    cd "$repo_root"

    # Build native libraries
    echo "1. Building native libraries..."
    if [[ -d native/build ]]; then
        cd native/build
        cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_ASAN=OFF >/dev/null 2>&1 || true
        make -j4 2>&1 | grep -E "(Built|Error|error)" || true
        cd ../..
        echo "   Native libraries built"
    else
        echo "   ⚠ native/build not found, skipping native build"
    fi
    echo ""

    # Run C++ unit tests
    echo "2. Running C++ smoke tests..."
    local tests_run=0
    for test_bin in ./native/build/test_*; do
        if [[ -x "$test_bin" ]]; then
            local test_name=$(basename "$test_bin")
            echo "   Running $test_name..."
            "$test_bin" 2>/dev/null && echo "     ✓ $test_name passed" || echo "     ⚠ $test_name skipped/failed"
            ((tests_run++))
        fi
    done
    if [[ $tests_run -eq 0 ]]; then
        echo "   ⚠ No C++ tests found"
    else
        echo "   Ran $tests_run C++ test(s)"
    fi
    echo ""

    echo "3. Building Go applications with native libs..."
    go build -tags native_libs -o /dev/null ./cmd/api-server 2>&1 | grep -v "ignoring duplicate" || true
    echo "   api-server builds"
    go build -tags native_libs -o /dev/null ./cmd/worker 2>&1 | grep -v "ignoring duplicate" || true 2>/dev/null || echo "   (worker optional)"
    echo ""
fi

probe_https_health_openssl() {
    host="$1"
    port="$2"
    path="$3"

    req="GET ${path} HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n"
    resp=$(printf "%b" "$req" | openssl s_client -connect "127.0.0.1:${port}" -servername "${host}" -tls1_2 -quiet 2>/dev/null || true)
    printf "%s" "$resp" | tr -d '\r' | head -n 1 | grep -Eq '^HTTP/1\.[01] 200'
}

compose_cmd="docker-compose";
if ! command -v docker-compose >/dev/null 2>&1; then
    compose_cmd="docker compose";
fi

compose_files=()
compose_project_args=("--project-directory" "$repo_root")
api_base=""
prometheus_base=""
stack_name=""
api_wait_seconds=90
prometheus_wait_seconds=90

if [ "$env" = "dev" ]; then
    # Use temp directory for smoke test data to avoid file sharing issues on macOS/Colima
    SMOKE_TEST_DATA_DIR="${SMOKE_TEST_DATA_DIR:-$(mktemp -d /tmp/fetch_ml_smoke.XXXXXX)}"
    echo "Using temp directory: $SMOKE_TEST_DATA_DIR"
    
    mkdir -p \
        "$SMOKE_TEST_DATA_DIR/redis" \
        "$SMOKE_TEST_DATA_DIR/minio" \
        "$SMOKE_TEST_DATA_DIR/prometheus" \
        "$SMOKE_TEST_DATA_DIR/grafana" \
        "$SMOKE_TEST_DATA_DIR/loki" \
        "$SMOKE_TEST_DATA_DIR/logs" \
        "$SMOKE_TEST_DATA_DIR/experiments" \
        "$SMOKE_TEST_DATA_DIR/active" \
        "$SMOKE_TEST_DATA_DIR/workspaces"

    # Copy monitoring config to temp directory (required for promtail)
    cp "$repo_root/monitoring/promtail-config.yml" "$SMOKE_TEST_DATA_DIR/"
    
    # Export for docker-compose to use
    export SMOKE_TEST_DATA_DIR
    
    # Create env file for docker-compose (process substitution doesn't work)
    env_file="$SMOKE_TEST_DATA_DIR/.env"
    echo "SMOKE_TEST_DATA_DIR=$SMOKE_TEST_DATA_DIR" > "$env_file"
    echo "FETCHML_REPO_ROOT=$repo_root" >> "$env_file"
    
    # Update compose project args to include env file
    compose_project_args=("--project-directory" "$repo_root" "--env-file" "$env_file")

    stack_name="dev"
    api_wait_seconds=180
    prometheus_wait_seconds=180
    compose_files=("-f" "$repo_root/deployments/docker-compose.dev.yml")
    api_base="https://localhost:9101"
    if ! curl -skf "$api_base/health" >/dev/null 2>&1; then
        api_base="http://localhost:9101"
    fi
    prometheus_base="http://localhost:9090"
else
    # Use temp directory for prod smoke test too
    SMOKE_TEST_DATA_DIR="${SMOKE_TEST_DATA_DIR:-$(mktemp -d /tmp/fetch_ml_smoke_prod.XXXXXX)}"
    echo "Using temp directory: $SMOKE_TEST_DATA_DIR"
    
    mkdir -p \
        "$SMOKE_TEST_DATA_DIR/caddy/data" \
        "$SMOKE_TEST_DATA_DIR/caddy/config" \
        "$SMOKE_TEST_DATA_DIR/redis" \
        "$SMOKE_TEST_DATA_DIR/logs" \
        "$SMOKE_TEST_DATA_DIR/experiments" \
        "$SMOKE_TEST_DATA_DIR/active"

    # Copy monitoring config to temp directory (required for promtail)
    cp "$repo_root/monitoring/promtail-config.yml" "$SMOKE_TEST_DATA_DIR/"
    
    # Export for docker-compose to use
    export SMOKE_TEST_DATA_DIR
    
    # Create env file for docker-compose (process substitution doesn't work)
    env_file="$SMOKE_TEST_DATA_DIR/.env"
    echo "SMOKE_TEST_DATA_DIR=$SMOKE_TEST_DATA_DIR" > "$env_file"
    echo "FETCHML_REPO_ROOT=$repo_root" >> "$env_file"
    
    # Update compose project args to include env file
    compose_project_args=("--project-directory" "$repo_root" "--env-file" "$env_file")

    stack_name="prod"
    compose_files=("-f" "$repo_root/deployments/docker-compose.prod.smoke.yml")
    api_base="https://localhost:8443"
    export FETCHML_DOMAIN=localhost
    export CADDY_EMAIL=smoke@example.invalid
fi

cleanup() {
    status=$?;
    if [ "$status" -ne 0 ]; then
        $compose_cmd "${compose_project_args[@]}" "${compose_files[@]}" logs --no-color || true;
    fi
    if [ "${KEEP_STACK:-0}" != "1" ]; then
        $compose_cmd "${compose_project_args[@]}" "${compose_files[@]}" down -v >/dev/null 2>&1 || true;
    fi
    exit "$status";
}

trap cleanup EXIT;
echo "Starting $stack_name stack for smoke test...";

$compose_cmd "${compose_project_args[@]}" "${compose_files[@]}" up -d --build >/dev/null;
echo "Waiting for API to become healthy...";

deadline=$(($(date +%s) + $api_wait_seconds));
while true; do
    if [ "$env" = "dev" ]; then
        if curl -skf "$api_base/health" >/dev/null 2>&1; then break; fi;
    else
        if probe_https_health_openssl "localhost" "8443" "/health"; then break; fi;
    fi
    if [ $(date +%s) -ge $deadline ]; then echo "Timed out waiting for $api_base/health"; exit 1; fi;
    sleep 2;
done;

if [ "$env" = "dev" ]; then
    echo "Checking metrics endpoint...";
    curl -skf "$api_base/metrics" >/dev/null;

    echo "Waiting for Prometheus target api-server to be up...";
    deadline=$(($(date +%s) + $prometheus_wait_seconds));
    query_url="$prometheus_base/api/v1/query?query=up%7Bjob%3D%22api-server%22%7D";

    while true; do
        resp=$(curl -sf "$query_url" || true);
        resp_compact=$(printf "%s" "$resp" | tr -d '\n' | tr -d '\r');
        if echo "$resp_compact" | grep -Fq '"instance":"api-server:9101"' && echo "$resp_compact" | grep -Fq ',"1"]'; then break; fi;
        if [ $(date +%s) -ge $deadline ]; then echo "Timed out waiting for Prometheus api-server target to be up"; echo "$resp"; exit 1; fi;
        sleep 2;
    done;
fi