#!/usr/bin/env bash
# ============================================================================
# V3Q.AI — Universal Auto-Setup Script
# Works on: macOS, Linux (Debian/Ubuntu, RHEL/CentOS, Alpine)
# Idempotent: safe to run multiple times — detects existing state.
#
# Usage:
#   chmod +x scripts/setup.sh
#   ./scripts/setup.sh
#
# What it does:
#   1. Detect OS and prerequisites (Python 3.12+, Node.js 18+, Docker)
#   2. Create config/.env from template if missing
#   3. Start or detect PostgreSQL (Docker or native)
#   4. Run database schema setup (idempotent SQL)
#   5. Create Python virtualenv and install backend dependencies
#   6. Install frontend dependencies and build
#   7. Create data directories
#   8. Check Ollama status
#   9. Run backend preflight checks
#  10. Print startup commands
# ============================================================================

set -euo pipefail

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# Track issues
WARNINGS=()
ERRORS=()

# Get the directory where this script lives, then go to project root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$PROJECT_ROOT"

# ---- Utility functions ----

info()    { echo -e "${BLUE}[INFO]${NC} $*"; }
ok()      { echo -e "${GREEN}[  OK]${NC} $*"; }
warn()    { echo -e "${YELLOW}[WARN]${NC} $*"; WARNINGS+=("$*"); }
fail()    { echo -e "${RED}[FAIL]${NC} $*"; ERRORS+=("$*"); }
step()    { echo -e "\n${CYAN}${BOLD}[$1]${NC} ${BOLD}$2${NC}"; }
divider() { echo -e "${CYAN}$(printf '=%.0s' {1..60})${NC}"; }

command_exists() { command -v "$1" &>/dev/null; }

version_ge() {
    # Returns 0 if $1 >= $2 (semver major.minor)
    local IFS=.
    local i ver1=($1) ver2=($2)
    for ((i=0; i<${#ver2[@]}; i++)); do
        if ((10#${ver1[i]:-0} < 10#${ver2[i]:-0})); then return 1; fi
        if ((10#${ver1[i]:-0} > 10#${ver2[i]:-0})); then return 0; fi
    done
    return 0
}

# ---- Load .env if it exists (for POSTGRES_* vars) ----
load_env() {
    local envfile="$PROJECT_ROOT/config/.env"
    if [ -f "$envfile" ]; then
        set -a
        # shellcheck disable=SC1090
        source "$envfile" 2>/dev/null || true
        set +a
    fi
}

# ============================================================================
echo ""
divider
echo -e "  ${BOLD}V3Q.AI — Auto-Setup${NC}"
divider

# ---- Step 1: Detect OS & Prerequisites ----
step "1/10" "Detecting system & prerequisites"

OS="$(uname -s)"
ARCH="$(uname -m)"
info "System: $OS $ARCH"

case "$OS" in
    Darwin) PLATFORM="macos" ;;
    Linux)  PLATFORM="linux" ;;
    MINGW*|MSYS*|CYGWIN*) PLATFORM="windows" ;;
    *) fail "Unsupported OS: $OS"; exit 1 ;;
esac

# Python 3.12+
PYTHON_CMD=""
for cmd in python3.12 python3 python; do
    if command_exists "$cmd"; then
        PY_VER=$("$cmd" --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1)
        if version_ge "$PY_VER" "3.12"; then
            PYTHON_CMD="$cmd"
            break
        fi
    fi
done

if [ -z "$PYTHON_CMD" ]; then
    fail "Python 3.12+ not found."
    echo "       Install: https://python.org/downloads/"
    if [ "$PLATFORM" = "macos" ]; then echo "       Or: brew install python@3.12"; fi
    if [ "$PLATFORM" = "linux" ]; then echo "       Or: sudo apt install python3.12 python3.12-venv"; fi
else
    PY_FULL=$("$PYTHON_CMD" --version 2>&1)
    ok "Python: $PY_FULL ($PYTHON_CMD)"
fi

# Node.js 18+
if command_exists node; then
    NODE_VER=$(node --version | grep -oE '[0-9]+' | head -1)
    if [ "$NODE_VER" -ge 18 ] 2>/dev/null; then
        ok "Node.js: $(node --version)"
    else
        fail "Node.js 18+ required, found $(node --version)"
        echo "       Install: https://nodejs.org/"
    fi
else
    fail "Node.js not found."
    echo "       Install: https://nodejs.org/"
    if [ "$PLATFORM" = "macos" ]; then echo "       Or: brew install node"; fi
fi

# npm
if command_exists npm; then
    ok "npm: $(npm --version)"
else
    fail "npm not found (should come with Node.js)"
fi

# Docker (optional — needed only if using Docker for PostgreSQL)
HAS_DOCKER=false
if command_exists docker; then
    if docker info &>/dev/null; then
        ok "Docker: available and running"
        HAS_DOCKER=true
    else
        warn "Docker installed but not running. Start Docker Desktop if you want Docker-managed PostgreSQL."
    fi
else
    info "Docker not installed (optional — only needed if you want Docker-managed PostgreSQL)"
fi

# ---- Step 2: Environment File ----
step "2/10" "Environment configuration"

if [ ! -f "config/.env" ]; then
    if [ -f "config/.env.example" ]; then
        cp "config/.env.example" "config/.env"
        ok "Created config/.env from template"
        warn "EDIT config/.env — set at minimum: ANTHROPIC_API_KEY"
    else
        fail "No config/.env.example found. Cannot create .env"
    fi
else
    ok "config/.env exists"
fi

load_env

# Check critical env vars
if [ -z "${ANTHROPIC_API_KEY:-}" ] || [ "${ANTHROPIC_API_KEY:-}" = "sk-ant-xxxxxxxxxxxxxxxxxxxxx" ]; then
    warn "ANTHROPIC_API_KEY not set in config/.env — Claude API won't work until you set it"
fi

# ---- Step 3: PostgreSQL ----
step "3/10" "PostgreSQL database"

PG_HOST="${POSTGRES_HOST:-localhost}"
PG_PORT="${POSTGRES_PORT:-5432}"
PG_DB="${POSTGRES_DB:-v3q}"
PG_USER="${POSTGRES_USER:-v3q_admin}"
PG_PASS="${POSTGRES_PASSWORD:-v3q_dev_2024}"

# Check if PostgreSQL is already reachable
PG_REACHABLE=false
if command_exists pg_isready; then
    if pg_isready -h "$PG_HOST" -p "$PG_PORT" -q 2>/dev/null; then
        PG_REACHABLE=true
        ok "PostgreSQL already running on $PG_HOST:$PG_PORT"
    fi
elif command_exists psql; then
    if PGPASSWORD="$PG_PASS" psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -c "SELECT 1" &>/dev/null; then
        PG_REACHABLE=true
        ok "PostgreSQL already reachable on $PG_HOST:$PG_PORT"
    fi
fi

if [ "$PG_REACHABLE" = false ]; then
    if [ "$HAS_DOCKER" = true ]; then
        info "Starting PostgreSQL via Docker Compose..."
        docker compose up -d postgres 2>&1 | sed 's/^/       /'

        # Wait for healthy
        info "Waiting for PostgreSQL to become healthy..."
        for i in $(seq 1 30); do
            if docker compose exec -T postgres pg_isready -U "$PG_USER" -d "$PG_DB" &>/dev/null; then
                PG_REACHABLE=true
                ok "PostgreSQL started via Docker (took ${i}s)"
                break
            fi
            sleep 1
        done

        if [ "$PG_REACHABLE" = false ]; then
            fail "PostgreSQL did not become healthy in 30s"
            echo "       Check: docker compose logs postgres"
        fi
    else
        # Try native PostgreSQL
        if [ "$PLATFORM" = "macos" ] && command_exists brew; then
            info "Attempting to start PostgreSQL via Homebrew..."
            brew services start postgresql@16 2>/dev/null || brew services start postgresql 2>/dev/null || true
            sleep 3
            if pg_isready -h localhost -p "$PG_PORT" -q 2>/dev/null; then
                PG_REACHABLE=true
                ok "PostgreSQL started via Homebrew"
            fi
        fi

        if [ "$PG_REACHABLE" = false ]; then
            fail "PostgreSQL not reachable on $PG_HOST:$PG_PORT"
            echo "       Options:"
            echo "         1. Install Docker and re-run this script"
            echo "         2. Install PostgreSQL 16 natively and start it"
            if [ "$PLATFORM" = "macos" ]; then echo "         3. brew install postgresql@16 && brew services start postgresql@16"; fi
            if [ "$PLATFORM" = "linux" ]; then echo "         3. sudo apt install postgresql-16 && sudo systemctl start postgresql"; fi
        fi
    fi
fi

# ---- Step 4: Database & Schema Setup ----
step "4/10" "Database schema setup"

if [ "$PG_REACHABLE" = true ]; then
    # Check if we can connect to the v3q database specifically
    DB_EXISTS=false

    # Try connecting to the database
    if [ "$HAS_DOCKER" = true ] && docker compose ps postgres --format '{{.State}}' 2>/dev/null | grep -q running; then
        # Docker PostgreSQL — use docker exec
        if docker compose exec -T postgres psql -U "$PG_USER" -d "$PG_DB" -c "SELECT 1" &>/dev/null; then
            DB_EXISTS=true
        else
            # Database might not exist yet; create it
            info "Creating database '$PG_DB'..."
            docker compose exec -T postgres psql -U "$PG_USER" -d postgres -c "CREATE DATABASE $PG_DB OWNER $PG_USER" 2>/dev/null || true
            DB_EXISTS=true
        fi

        # Run schema setup (idempotent)
        info "Running schema setup..."
        if docker compose exec -T postgres psql -U "$PG_USER" -d "$PG_DB" < scripts/setup_postgresql.sql &>/dev/null; then
            ok "Database schema is up to date"
        else
            # Try again with more verbose output
            docker compose exec -T postgres psql -U "$PG_USER" -d "$PG_DB" < scripts/setup_postgresql.sql 2>&1 | grep -i error | head -3
            warn "Schema setup had warnings (may be OK if tables already exist)"
        fi

    elif command_exists psql; then
        # Native PostgreSQL — use psql directly
        export PGPASSWORD="$PG_PASS"

        # Check if DB exists
        if psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -c "SELECT 1" &>/dev/null; then
            DB_EXISTS=true
        else
            info "Creating database '$PG_DB'..."
            psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d postgres -c "CREATE DATABASE $PG_DB" 2>/dev/null || true
            DB_EXISTS=true
        fi

        info "Running schema setup..."
        if psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -f scripts/setup_postgresql.sql &>/dev/null; then
            ok "Database schema is up to date"
        else
            warn "Schema setup had warnings (likely OK — tables may already exist)"
        fi
        unset PGPASSWORD
    else
        warn "psql not available — cannot run schema setup."
        echo "       Run manually: psql -U $PG_USER -d $PG_DB -f scripts/setup_postgresql.sql"
    fi
else
    warn "Skipping schema setup — PostgreSQL not reachable"
fi

# ---- Step 5: Python Backend ----
step "5/10" "Python backend dependencies"

if [ -n "$PYTHON_CMD" ]; then
    VENV_DIR="$PROJECT_ROOT/backend/.venv"

    if [ -d "$VENV_DIR" ] && [ -f "$VENV_DIR/bin/python" ]; then
        ok "Python venv already exists at backend/.venv"
    else
        info "Creating Python virtual environment..."
        "$PYTHON_CMD" -m venv "$VENV_DIR"
        ok "Created venv at backend/.venv"
    fi

    # Activate and install
    # shellcheck disable=SC1091
    source "$VENV_DIR/bin/activate"

    info "Installing Python dependencies (this may take a minute)..."
    if pip install -r backend/requirements.txt --quiet 2>&1 | tail -3; then
        ok "Python dependencies installed"
    else
        fail "pip install failed. Check backend/requirements.txt"
        echo "       Some packages (pyodbc, hdbcli) need system libraries:"
        if [ "$PLATFORM" = "macos" ]; then echo "         brew install unixodbc"; fi
        if [ "$PLATFORM" = "linux" ]; then echo "         sudo apt install unixodbc-dev"; fi
    fi
else
    fail "Skipping Python setup — Python 3.12+ not found"
fi

# ---- Step 6: Frontend ----
step "6/10" "Frontend dependencies & build"

if command_exists npm; then
    cd "$PROJECT_ROOT/frontend"

    if [ -d "node_modules" ]; then
        ok "node_modules already exists"
        info "Running npm install to ensure dependencies are current..."
    else
        info "Installing frontend dependencies..."
    fi

    if npm install --loglevel=warn 2>&1 | tail -5; then
        ok "Frontend dependencies installed"
    else
        fail "npm install failed"
        echo "       Try: cd frontend && rm -rf node_modules package-lock.json && npm install"
    fi

    info "Building frontend for production..."
    # Use vite build directly to skip vue-tsc type checking (which can fail on fresh installs)
    if npx vite build 2>&1 | tail -5; then
        ok "Frontend built (dist/)"
    else
        warn "Frontend build failed — you can still use dev mode: cd frontend && npm run dev"
    fi

    cd "$PROJECT_ROOT"
else
    fail "Skipping frontend — npm not found"
fi

# ---- Step 7: Data Directories ----
step "7/10" "Data directories"

mkdir -p data/results logs
ok "data/results and logs directories ready"

# ---- Step 8: Ollama ----
step "8/10" "Ollama (local LLM)"

OLLAMA_URL="${OLLAMA_BASE_URL:-http://localhost:11434}"
OLLAMA_MODEL_NAME="${OLLAMA_MODEL:-qwen2.5:32b}"

if command_exists ollama; then
    # Check if Ollama is running
    if curl -sf "${OLLAMA_URL}/api/tags" &>/dev/null; then
        ok "Ollama is running"
        # Check if model is available
        if curl -sf "${OLLAMA_URL}/api/tags" | grep -q "${OLLAMA_MODEL_NAME%%:*}"; then
            ok "Model '${OLLAMA_MODEL_NAME}' is available"
        else
            warn "Model '${OLLAMA_MODEL_NAME}' not found. Pull it with: ollama pull ${OLLAMA_MODEL_NAME}"
        fi
    else
        warn "Ollama installed but not running. Start with: ollama serve"
    fi
else
    warn "Ollama not installed (needed for local LLM)."
    echo "       Install: https://ollama.com"
    echo "       Then: ollama serve && ollama pull ${OLLAMA_MODEL_NAME}"
fi

# ---- Step 9: Backend Preflight ----
step "9/10" "Backend preflight checks"

if [ -n "$PYTHON_CMD" ] && [ -f "$VENV_DIR/bin/python" ]; then
    source "$VENV_DIR/bin/activate"
    cd "$PROJECT_ROOT/backend"

    # Run preflight (it prints its own report)
    "$VENV_DIR/bin/python" -c "
import asyncio
from preflight import run_preflight

async def check():
    result = await run_preflight()
    result.print_report()
    return not result.has_critical_errors

ok = asyncio.run(check())
exit(0 if ok else 1)
" 2>&1 || warn "Preflight had issues (see report above)"

    cd "$PROJECT_ROOT"
else
    warn "Skipping preflight — Python venv not ready"
fi

# ---- Step 10: Summary ----
step "10/10" "Setup Summary"

echo ""
divider

if [ ${#ERRORS[@]} -gt 0 ]; then
    echo -e "\n  ${RED}${BOLD}ERRORS (${#ERRORS[@]}):${NC}"
    for e in "${ERRORS[@]}"; do
        echo -e "    ${RED}[X]${NC} $e"
    done
fi

if [ ${#WARNINGS[@]} -gt 0 ]; then
    echo -e "\n  ${YELLOW}${BOLD}WARNINGS (${#WARNINGS[@]}):${NC}"
    for w in "${WARNINGS[@]}"; do
        echo -e "    ${YELLOW}[!]${NC} $w"
    done
fi

if [ ${#ERRORS[@]} -eq 0 ]; then
    echo -e "\n  ${GREEN}${BOLD}SETUP COMPLETE${NC}"
    if [ ${#WARNINGS[@]} -gt 0 ]; then
        echo -e "  ${YELLOW}(with ${#WARNINGS[@]} warnings — see above)${NC}"
    fi
else
    echo -e "\n  ${RED}${BOLD}SETUP INCOMPLETE — fix the errors above and re-run${NC}"
fi

echo ""
divider
echo -e "  ${BOLD}How to start V3Q.AI:${NC}"
divider
echo ""
echo -e "  ${BOLD}1. Edit config (if not done):${NC}"
echo "     nano config/.env   # set ANTHROPIC_API_KEY"
echo ""
echo -e "  ${BOLD}2. Start backend:${NC}"
echo "     cd backend"
echo "     source .venv/bin/activate"
echo "     python main.py"
echo "     # Backend runs on http://localhost:${APP_PORT:-8001}"
echo ""
echo -e "  ${BOLD}3. Start frontend (development):${NC}"
echo "     cd frontend"
echo "     npm run dev"
echo "     # Open http://localhost:5173"
echo ""
echo -e "  ${BOLD}OR for production (frontend already built):${NC}"
echo "     # Just run the backend — serve dist/ via a reverse proxy"
echo ""
echo -e "  ${BOLD}4. Open browser:${NC}"
echo "     http://localhost:5173  (dev mode)"
echo "     Go to Config tab to add database connections and sync tables."
echo ""
divider
echo ""
