#!/bin/bash
# E2E CLI Installation and Core Commands Test
# Modes: TESTPYPI=1 → install from TestPyPI, server + /v1/chat/completions
#        else → local editable install (pip install -e ".[dev]")
# Tests: install, version, help, doctor, setup, keys, server start, one request to
#        /v1/chat/completions (200 or 503 acceptable), cleanup.

set -e

VENV_DIR="/tmp/test-llmhosts-cli"
TEST_LOG="/tmp/cli_e2e_test_$(date +%Y%m%d_%H%M%S).log"
E2E_PORT="${E2E_PORT:-18765}"
API_KEY="${LLMHOSTS_API_KEY:-sk-test-dummy-e2e}"

# Install mode: TestPyPI vs local editable
VERSION_EXPECT=$(python3 -c "import re; print(re.search(r'__version__\s*=\s*\"([^\"]+)\"', open('llmhosts/__init__.py').read()).group(1))")
if [[ -n "${TESTPYPI:-}" ]] && [[ "${TESTPYPI}" != "0" ]]; then
    INSTALL_MODE="testpypi"
    INSTALL_CMD=''  # Handled inline below (two-step install)
else
    INSTALL_MODE="local"
    INSTALL_CMD='pip install -e ".[dev]" -q'
fi

echo "===== LLMHosts CLI E2E Test Suite =====" | tee "$TEST_LOG"
echo "Date: $(date)" | tee -a "$TEST_LOG"
echo "Python: $(python3 --version)" | tee -a "$TEST_LOG"
echo "Mode: $INSTALL_MODE" | tee -a "$TEST_LOG"
echo "Test environment: $VENV_DIR" | tee -a "$TEST_LOG"
echo "" | tee -a "$TEST_LOG"

# Server PID for cleanup
SERVER_PID=""

cleanup() {
    if [[ -n "$SERVER_PID" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
        echo "Stopping server (PID $SERVER_PID)..." | tee -a "$TEST_LOG"
        kill "$SERVER_PID" 2>/dev/null || true
        sleep 1
        # Force kill if still running (uvicorn workers)
        kill -9 "$SERVER_PID" 2>/dev/null || true
    fi
    echo "Cleaning up test environment..." | tee -a "$TEST_LOG"
    rm -rf "$VENV_DIR" 2>/dev/null || true
}
trap cleanup EXIT

# ============================================================================
# TEST 1: Create virtual environment
# ============================================================================
echo "TEST 1: Creating virtual environment..." | tee -a "$TEST_LOG"
python3 -m venv "$VENV_DIR" 2>&1 | tee -a "$TEST_LOG"
# shellcheck source=/dev/null
source "$VENV_DIR/bin/activate"
echo "✓ Virtual environment created" | tee -a "$TEST_LOG"
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 2: Install dependencies
# ============================================================================
echo "TEST 2: Installing llmhosts ($INSTALL_MODE)..." | tee -a "$TEST_LOG"
pip install --upgrade pip setuptools wheel -q 2>&1 | tee -a "$TEST_LOG"
if [[ "$INSTALL_MODE" == "testpypi" ]]; then
    # Two-step: install deps from real PyPI, then llmhosts from TestPyPI.
    # TestPyPI often has broken builds of popular packages (e.g. fastapi).
    pip install fastapi "uvicorn[standard]" click httpx pydantic pydantic-settings rich toml litellm textual cryptography aiosqlite websockets alembic -q 2>&1 | tee -a "$TEST_LOG"
    pip install --index-url https://test.pypi.org/simple/ --no-deps llmhosts -q 2>&1 | tee -a "$TEST_LOG"
    PIP_EXIT=${PIPESTATUS[0]}
    if [[ $PIP_EXIT -ne 0 ]] || ! command -v llmhosts &>/dev/null; then
        echo "⚠ llmhosts not found on TestPyPI (not yet published). Skipping remaining tests." | tee -a "$TEST_LOG"
        echo "=====================================" | tee -a "$TEST_LOG"
        echo "⚠ TESTS SKIPPED — package not on TestPyPI" | tee -a "$TEST_LOG"
        echo "=====================================" | tee -a "$TEST_LOG"
        exit 0
    fi
else
    # Local mode: must run from repo root (script is invoked from repo root)
    eval "$INSTALL_CMD" 2>&1 | tail -5 | tee -a "$TEST_LOG"
fi
echo "✓ Installation complete" | tee -a "$TEST_LOG"
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 3: Version check
# ============================================================================
echo "TEST 3: Version check" | tee -a "$TEST_LOG"
VERSION=$(llmhosts --version)
echo "  Output: $VERSION" | tee -a "$TEST_LOG"
if [[ "$VERSION" == *"$VERSION_EXPECT"* ]]; then
    echo "✓ Version check PASSED (expected $VERSION_EXPECT)" | tee -a "$TEST_LOG"
else
    echo "✗ Version check FAILED (expected *$VERSION_EXPECT*, got: $VERSION)" | tee -a "$TEST_LOG"
    exit 1
fi
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 4: Help command
# ============================================================================
echo "TEST 4: Help command" | tee -a "$TEST_LOG"
HELP_OUTPUT=$(llmhosts --help)
if [[ "$HELP_OUTPUT" == *"Usage:"* ]] && [[ "$HELP_OUTPUT" == *"Commands:"* ]]; then
    echo "✓ Help command PASSED" | tee -a "$TEST_LOG"
else
    echo "✗ Help command FAILED" | tee -a "$TEST_LOG"
    exit 1
fi
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 5: Setup wizard (if present)
# ============================================================================
echo "TEST 5: Setup wizard" | tee -a "$TEST_LOG"
SETUP_OUTPUT=$(python3 << 'PYTHON_EOF'
from llmhosts.cli import main
from click.testing import CliRunner

runner = CliRunner()
result = runner.invoke(main, ['setup'], input='\n\n\n\n')
print(result.output)
print(f"EXIT_CODE:{result.exit_code}")
PYTHON_EOF
)
SETUP_EXIT=$(echo "$SETUP_OUTPUT" | grep "EXIT_CODE:" | cut -d: -f2)
if [[ "$SETUP_EXIT" == "0" ]] && echo "$SETUP_OUTPUT" | grep -q "Setup complete"; then
    echo "✓ Setup wizard PASSED" | tee -a "$TEST_LOG"
else
    echo "⚠ Setup wizard exit=$SETUP_EXIT (optional)" | tee -a "$TEST_LOG"
fi
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 6: Doctor checks
# ============================================================================
echo "TEST 6: Doctor diagnostic checks" | tee -a "$TEST_LOG"
DOCTOR_OUTPUT=$(llmhosts doctor 2>&1)
echo "$DOCTOR_OUTPUT" | tee -a "$TEST_LOG"
PASSED=$(echo "$DOCTOR_OUTPUT" | grep -c "✓ PASS" || true)
if [[ "${PASSED:-0}" -ge 1 ]]; then
    echo "✓ Doctor checks PASSED ($PASSED checks passed)" | tee -a "$TEST_LOG"
else
    echo "⚠ Doctor: $PASSED passed" | tee -a "$TEST_LOG"
fi
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 7: API Key - add and list
# ============================================================================
echo "TEST 7: Add API key (openai)" | tee -a "$TEST_LOG"
ADD_OUTPUT=$(llmhosts keys add openai "$API_KEY" 2>&1)
echo "  Output: $ADD_OUTPUT" | tee -a "$TEST_LOG"
if [[ "$ADD_OUTPUT" == *"Stored key"* ]] || [[ "$ADD_OUTPUT" == *"stored"* ]]; then
    echo "✓ Add key PASSED" | tee -a "$TEST_LOG"
else
    echo "✗ Add key FAILED" | tee -a "$TEST_LOG"
    exit 1
fi
echo "" | tee -a "$TEST_LOG"

echo "TEST 8: List API keys" | tee -a "$TEST_LOG"
LIST_OUTPUT=$(llmhosts keys list 2>&1)
echo "$LIST_OUTPUT" | tee -a "$TEST_LOG"
if [[ "$LIST_OUTPUT" == *"openai"* ]]; then
    echo "✓ List keys PASSED" | tee -a "$TEST_LOG"
else
    echo "✗ List keys FAILED" | tee -a "$TEST_LOG"
    exit 1
fi
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# TEST 9: Start server and request /v1/chat/completions
# ============================================================================
echo "TEST 9: Server start and /v1/chat/completions request" | tee -a "$TEST_LOG"
llmhosts serve --port "$E2E_PORT" --no-tui >> "$TEST_LOG" 2>&1 &
SERVER_PID=$!

# Wait for server to listen (startup can take 20-40s with discovery)
for i in $(seq 1 45); do
    if curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$E2E_PORT/health" 2>/dev/null | grep -q 200; then
        echo "  Server listening on port $E2E_PORT after ${i}s" | tee -a "$TEST_LOG"
        break
    fi
    if ! kill -0 "$SERVER_PID" 2>/dev/null; then
        echo "✗ Server process exited early" | tee -a "$TEST_LOG"
        exit 1
    fi
    sleep 1
done

if ! curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:$E2E_PORT/health" 2>/dev/null | grep -q 200; then
    echo "✗ Server did not become ready in time" | tee -a "$TEST_LOG"
    exit 1
fi

CHAT_CODE=$(curl -s -o /tmp/chat_resp.json -w "%{http_code}" -X POST "http://127.0.0.1:$E2E_PORT/v1/chat/completions" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"gpt-3.5-turbo","messages":[{"role":"user","content":"hi"}]}')
echo "  /v1/chat/completions response: HTTP $CHAT_CODE" | tee -a "$TEST_LOG"

if [[ "$CHAT_CODE" == "200" ]]; then
    echo "✓ Chat completions PASSED (200)" | tee -a "$TEST_LOG"
elif [[ "$CHAT_CODE" == "503" ]]; then
    echo "✓ Chat completions PASSED (503 no backend — acceptable)" | tee -a "$TEST_LOG"
else
    echo "  Response body (first 500 chars): $(head -c 500 /tmp/chat_resp.json 2>/dev/null)" | tee -a "$TEST_LOG"
    echo "✗ Chat completions FAILED (expected 200 or 503, got $CHAT_CODE)" | tee -a "$TEST_LOG"
    kill "$SERVER_PID" 2>/dev/null || true
    wait "$SERVER_PID" 2>/dev/null || true
    SERVER_PID=""
    exit 1
fi

kill "$SERVER_PID" 2>/dev/null || true
wait "$SERVER_PID" 2>/dev/null || true
SERVER_PID=""
echo "" | tee -a "$TEST_LOG"

# ============================================================================
# Summary
# ============================================================================
echo "=====================================" | tee -a "$TEST_LOG"
echo "✓ ALL TESTS PASSED" | tee -a "$TEST_LOG"
echo "=====================================" | tee -a "$TEST_LOG"
echo "Test log saved to: $TEST_LOG" | tee -a "$TEST_LOG"

exit 0
