#!/usr/bin/env bash
#
# start.sh - Start all DeerFlow development services
#
# Must be run from the repo root directory.

set -e

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

# ── Load environment variables from .env ──────────────────────────────────────
if [ -f "$REPO_ROOT/.env" ]; then
    set -a
    source "$REPO_ROOT/.env"
    set +a
fi

# ── Argument parsing ─────────────────────────────────────────────────────────

DEV_MODE=true
for arg in "$@"; do
    case "$arg" in
        --dev)  DEV_MODE=true ;;
        --prod) DEV_MODE=false ;;
        *) echo "Unknown argument: $arg"; echo "Usage: $0 [--dev|--prod]"; exit 1 ;;
    esac
done

if $DEV_MODE; then
    FRONTEND_CMD="pnpm run dev"
else
    if command -v python3 >/dev/null 2>&1; then
        PYTHON_BIN="python3"
    elif command -v python >/dev/null 2>&1; then
        PYTHON_BIN="python"
    else
        echo "Python is required to generate BETTER_AUTH_SECRET, but neither python3 nor python was found."
        exit 1
    fi
    FRONTEND_STANDALONE_DIR="$REPO_ROOT/frontend/.next/standalone"
    FRONTEND_STANDALONE_SERVER="$FRONTEND_STANDALONE_DIR/server.js"
    FRONTEND_STANDALONE_STATIC_DIR="$FRONTEND_STANDALONE_DIR/.next/static"
    FRONTEND_SOURCE_STATIC_DIR="$REPO_ROOT/frontend/.next/static"
    FRONTEND_STANDALONE_PUBLIC_DIR="$FRONTEND_STANDALONE_DIR/public"
    FRONTEND_SOURCE_PUBLIC_DIR="$REPO_ROOT/frontend/public"

    if [ ! -f "$FRONTEND_STANDALONE_SERVER" ]; then
        echo "✗ Frontend standalone server not found: $FRONTEND_STANDALONE_SERVER"
        echo "  make start (prod) now uses prebuilt standalone assets and will not run local build."
        echo "  Please prepare frontend artifacts first (example):"
        echo "    pnpm -C frontend build"
        exit 1
    fi

    # Align local runtime layout with deploy-frontend-standalone.sh:
    # standalone + .next/static + public under frontend/.next/standalone/
    if [ ! -d "$FRONTEND_STANDALONE_STATIC_DIR" ] && [ -d "$FRONTEND_SOURCE_STATIC_DIR" ]; then
        mkdir -p "$FRONTEND_STANDALONE_DIR/.next"
        cp -R "$FRONTEND_SOURCE_STATIC_DIR" "$FRONTEND_STANDALONE_STATIC_DIR"
    fi
    if [ ! -d "$FRONTEND_STANDALONE_PUBLIC_DIR" ] && [ -d "$FRONTEND_SOURCE_PUBLIC_DIR" ]; then
        cp -R "$FRONTEND_SOURCE_PUBLIC_DIR" "$FRONTEND_STANDALONE_PUBLIC_DIR"
    fi

    if [ ! -d "$FRONTEND_STANDALONE_STATIC_DIR" ]; then
        echo "✗ Missing standalone static assets: $FRONTEND_STANDALONE_STATIC_DIR"
        echo "  Please ensure .next/static is available for standalone runtime."
        exit 1
    fi
    if [ ! -d "$FRONTEND_STANDALONE_PUBLIC_DIR" ]; then
        echo "✗ Missing standalone public assets: $FRONTEND_STANDALONE_PUBLIC_DIR"
        echo "  Please ensure public/ is available for standalone runtime."
        exit 1
    fi

    FRONTEND_CMD="env BETTER_AUTH_SECRET=$($PYTHON_BIN -c 'import secrets; print(secrets.token_hex(16))') HOSTNAME=0.0.0.0 PORT=3000 node server.js"
fi

# ── Stop existing services ────────────────────────────────────────────────────

echo "Stopping existing services if any..."
pkill -f "langgraph dev" 2>/dev/null || true
pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
pkill -f "next dev" 2>/dev/null || true
pkill -f "next-server" 2>/dev/null || true
pkill -f "frontend/.next/standalone/server.js" 2>/dev/null || true
nginx -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" -s quit 2>/dev/null || true
sleep 1
pkill -9 nginx 2>/dev/null || true
killall -9 nginx 2>/dev/null || true
./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
sleep 1

# ── Banner ────────────────────────────────────────────────────────────────────

echo ""
echo "=========================================="
echo "  Starting DeerFlow Development Server"
echo "=========================================="
echo ""
if $DEV_MODE; then
    echo "  Mode: DEV  (hot-reload enabled)"
    echo "  Tip:  run \`make start\` in production mode"
else
    echo "  Mode: PROD (hot-reload disabled)"
    echo "  Tip:  run \`make dev\` to start in development mode"
fi
echo ""
echo "Services starting up..."
echo "  → Backend: LangGraph + Gateway"
echo "  → Frontend: Next.js"
echo "  → Nginx: Reverse Proxy"
echo ""

# ── Config check ─────────────────────────────────────────────────────────────

if ! { \
        [ -n "$DEER_FLOW_CONFIG_PATH" ] && [ -f "$DEER_FLOW_CONFIG_PATH" ] || \
        [ -f backend/config.yaml ] || \
        [ -f config.yaml ]; \
    }; then
    echo "✗ No DeerFlow config file found."
    echo "  Checked these locations:"
    echo "    - $DEER_FLOW_CONFIG_PATH (when DEER_FLOW_CONFIG_PATH is set)"
    echo "    - backend/config.yaml"
    echo "    - ./config.yaml"
    echo ""
    echo "  Run 'make config' from the repo root to generate ./config.yaml, then set required model API keys in .env or your config file."
    exit 1
fi

# ── Auto-upgrade config ──────────────────────────────────────────────────

"$REPO_ROOT/scripts/config-upgrade.sh"

# ── Cleanup trap ─────────────────────────────────────────────────────────────

cleanup() {
    trap - INT TERM
    echo ""
    echo "Shutting down services..."
    if [ "${SKIP_LANGGRAPH_SERVER:-0}" != "1" ]; then
        pkill -f "langgraph dev" 2>/dev/null || true
    fi
    pkill -f "uvicorn app.gateway.app:app" 2>/dev/null || true
    pkill -f "next dev" 2>/dev/null || true
    pkill -f "next start" 2>/dev/null || true
    pkill -f "next-server" 2>/dev/null || true
    pkill -f "frontend/.next/standalone/server.js" 2>/dev/null || true
    # Kill nginx using the captured PID first (most reliable),
    # then fall back to pkill/killall for any stray nginx workers.
    if [ -n "${NGINX_PID:-}" ] && kill -0 "$NGINX_PID" 2>/dev/null; then
        kill -TERM "$NGINX_PID" 2>/dev/null || true
        sleep 1
        kill -9 "$NGINX_PID" 2>/dev/null || true
    fi
    pkill -9 nginx 2>/dev/null || true
    killall -9 nginx 2>/dev/null || true
    echo "Cleaning up sandbox containers..."
    ./scripts/cleanup-containers.sh deer-flow-sandbox 2>/dev/null || true
    echo "✓ All services stopped"
    exit 0
}
trap cleanup INT TERM

# ── Start services ────────────────────────────────────────────────────────────

mkdir -p logs
mkdir -p temp/client_body_temp temp/proxy_temp temp/fastcgi_temp temp/uwsgi_temp temp/scgi_temp

if $DEV_MODE; then
    LANGGRAPH_EXTRA_FLAGS="--no-reload"
    GATEWAY_EXTRA_FLAGS="--reload --reload-include='*.yaml' --reload-include='.env' --reload-exclude='*.pyc' --reload-exclude='__pycache__' --reload-exclude='sandbox/' --reload-exclude='.deer-flow/'"
else
    LANGGRAPH_EXTRA_FLAGS="--no-reload"
    GATEWAY_EXTRA_FLAGS=""
fi

if [ "${SKIP_LANGGRAPH_SERVER:-0}" != "1" ]; then
    echo "Starting LangGraph server..."
    # Read log_level from config.yaml, fallback to env var, then to "info"
    CONFIG_LOG_LEVEL=$(grep -m1 '^log_level:' config.yaml 2>/dev/null | awk '{print $2}' | tr -d ' ')
    LANGGRAPH_LOG_LEVEL="${LANGGRAPH_LOG_LEVEL:-${CONFIG_LOG_LEVEL:-info}}"
    LANGGRAPH_JOBS_PER_WORKER="${LANGGRAPH_JOBS_PER_WORKER:-10}"
    LANGGRAPH_ALLOW_BLOCKING="${LANGGRAPH_ALLOW_BLOCKING:-0}"
    LANGGRAPH_ALLOW_BLOCKING_FLAG=""
    if [ "$LANGGRAPH_ALLOW_BLOCKING" = "1" ]; then
        LANGGRAPH_ALLOW_BLOCKING_FLAG="--allow-blocking"
    fi
    (cd backend && NO_COLOR=1 uv run langgraph dev --no-browser $LANGGRAPH_ALLOW_BLOCKING_FLAG --n-jobs-per-worker "$LANGGRAPH_JOBS_PER_WORKER" --server-log-level $LANGGRAPH_LOG_LEVEL $LANGGRAPH_EXTRA_FLAGS > ../logs/langgraph.log 2>&1) &
    ./scripts/wait-for-port.sh 2024 60 "LangGraph" || {
        echo "  See logs/langgraph.log for details"
        tail -20 logs/langgraph.log
        if grep -qE "config_version|outdated|Environment variable .* not found|KeyError|ValidationError|config\.yaml" logs/langgraph.log 2>/dev/null; then
            echo ""
            echo "  Hint: This may be a configuration issue. Try running 'make config-upgrade' to update your config.yaml."
        fi
        cleanup
    }
    echo "✓ LangGraph server started on localhost:2024"
else
    echo "⏩ Skipping LangGraph server (SKIP_LANGGRAPH_SERVER=1)"
    echo "   Use /api/langgraph-compat/* via Gateway instead"
fi

echo "Starting Gateway API..."
(cd backend && PYTHONPATH=. uv run uvicorn app.gateway.app:app --host 0.0.0.0 --port 8001 $GATEWAY_EXTRA_FLAGS > ../logs/gateway.log 2>&1) &
./scripts/wait-for-port.sh 8001 30 "Gateway API" || {
    echo "✗ Gateway API failed to start. Last log output:"
    tail -60 logs/gateway.log
    echo ""
    echo "Likely configuration errors:"
    grep -E "Failed to load configuration|Environment variable .* not found|config\.yaml.*not found" logs/gateway.log | tail -5 || true
    echo ""
    echo "  Hint: Try running 'make config-upgrade' to update your config.yaml with the latest fields."
    cleanup
}
echo "✓ Gateway API started on localhost:8001"

echo "Starting Frontend..."
if $DEV_MODE; then
    (cd frontend && $FRONTEND_CMD > ../logs/frontend.log 2>&1) &
else
    (cd frontend/.next/standalone && $FRONTEND_CMD > ../../../logs/frontend.log 2>&1) &
fi
./scripts/wait-for-port.sh 3000 120 "Frontend" || {
    echo "  See logs/frontend.log for details"
    tail -20 logs/frontend.log
    cleanup
}
echo "✓ Frontend started on localhost:3000"

echo "Starting Nginx reverse proxy..."
nginx -g 'daemon off;' -c "$REPO_ROOT/docker/nginx/nginx.local.conf" -p "$REPO_ROOT" > logs/nginx.log 2>&1 &
NGINX_PID=$!
./scripts/wait-for-port.sh 2026 10 "Nginx" || {
    echo "  See logs/nginx.log for details"
    tail -10 logs/nginx.log
    cleanup
}
echo "✓ Nginx started on localhost:2026"

# ── Ready ─────────────────────────────────────────────────────────────────────

echo ""
echo "=========================================="
if $DEV_MODE; then
    echo "  ✓ DeerFlow development server is running!"
else
    echo "  ✓ DeerFlow production server is running!"
fi
echo "=========================================="
echo ""
echo "  🌐 Application: http://localhost:2026"
echo "  📡 API Gateway: http://localhost:2026/api/*"
if [ "${SKIP_LANGGRAPH_SERVER:-0}" = "1" ]; then
    echo "  🤖 LangGraph: skipped (SKIP_LANGGRAPH_SERVER=1)"
else
    echo "  🤖 LangGraph: http://localhost:2026/api/langgraph/* (served by langgraph dev)"
fi
echo "  🧪 LangGraph Compat (experimental): http://localhost:2026/api/langgraph-compat/* (served by Gateway)"
if [ "${SKIP_LANGGRAPH_SERVER:-0}" = "1" ]; then
    echo ""
    echo "  💡 Set NEXT_PUBLIC_LANGGRAPH_BASE_URL=/api/langgraph-compat in frontend/.env.local"
fi
echo ""
echo "  📋 Logs:"
echo "     - LangGraph: logs/langgraph.log"
echo "     - Gateway:   logs/gateway.log"
echo "     - Frontend:  logs/frontend.log"
echo "     - Nginx:     logs/nginx.log"
echo ""
echo "Press Ctrl+C to stop all services"

wait
