#!/usr/bin/env bash
#
# Krasis — Thin wrapper that ensures Python/venv are ready, then delegates
# to the Python TUI launcher for hardware detection, model selection,
# interactive configuration, and server launch.
#
# Usage:
#   ./krasis                        Interactive TUI setup + launch
#   ./krasis --non-interactive      Use saved/default config, launch immediately
#   ./krasis --skip-setup           Skip venv/build checks
#   ./krasis --venv PATH            Use existing virtualenv
#   ./krasis --help                 Show help
#
set -euo pipefail

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

# Detect platform: Windows (Git Bash/MSYS/Cygwin) uses Scripts/, Unix uses bin/
if [[ "$(uname -s)" == MINGW* || "$(uname -s)" == MSYS* || "$(uname -s)" == CYGWIN* ]]; then
    VENV_BIN="Scripts"
else
    VENV_BIN="bin"
fi

# ═══════════════════════════════════════════════════════════════════════
# Utilities
# ═══════════════════════════════════════════════════════════════════════

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

info()  { echo -e "${GREEN}✓${NC} $*"; }
warn()  { echo -e "${YELLOW}⚠${NC} $*"; }
err()   { echo -e "${RED}✗${NC} $*" >&2; }
header() { echo -e "\n${BOLD}${BLUE}═══ $* ═══${NC}\n"; }

# ═══════════════════════════════════════════════════════════════════════
# Argument pre-parse (extract --skip-setup and --venv before passing through)
# ═══════════════════════════════════════════════════════════════════════

SKIP_SETUP=false
PASSTHROUGH_ARGS=()

while [[ $# -gt 0 ]]; do
    case "$1" in
        --skip-setup) SKIP_SETUP=true; PASSTHROUGH_ARGS+=("$1"); shift ;;
        --venv)       VENV_DIR="$2"; PASSTHROUGH_ARGS+=("$1" "$2"); shift 2 ;;
        *)            PASSTHROUGH_ARGS+=("$1"); shift ;;
    esac
done

# ═══════════════════════════════════════════════════════════════════════
# Phase 1: Setup (venv, build, dependencies)
# This MUST stay in bash — it creates/activates the venv before Python
# is available for the launcher.
# ═══════════════════════════════════════════════════════════════════════

phase_setup() {
    if $SKIP_SETUP; then
        info "Skipping setup checks (--skip-setup)"
        if [[ -f "$VENV_DIR/$VENV_BIN/activate" ]]; then
            source "$VENV_DIR/$VENV_BIN/activate"
        fi
        return 0
    fi

    header "Phase 1: Setup"

    # Python 3.10+
    local py_version
    if ! command -v python3 &>/dev/null; then
        err "python3 not found. Install Python 3.10+."
        exit 1
    fi
    py_version=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
    local py_major py_minor
    py_major=$(echo "$py_version" | cut -d. -f1)
    py_minor=$(echo "$py_version" | cut -d. -f2)
    if (( py_major < 3 || (py_major == 3 && py_minor < 10) )); then
        err "Python $py_version found, but 3.10+ is required."
        exit 1
    fi
    info "Python $py_version"

    # Venv
    if [[ ! -d "$VENV_DIR" ]] || [[ ! -f "$VENV_DIR/$VENV_BIN/activate" ]]; then
        # Clean up partial venv if activate is missing
        if [[ -d "$VENV_DIR" ]] && [[ ! -f "$VENV_DIR/$VENV_BIN/activate" ]]; then
            warn "Incomplete venv detected, recreating..."
            rm -rf "$VENV_DIR"
        fi
        info "Creating virtual environment at $VENV_DIR ..."
        if ! python3 -m venv "$VENV_DIR" 2>&1; then
            err "Failed to create virtual environment."
            err "On Ubuntu/Debian, install: sudo apt install python${py_version}-venv"
            exit 1
        fi
        if [[ ! -f "$VENV_DIR/$VENV_BIN/activate" ]]; then
            err "Virtual environment created but activate script is missing."
            err "On Ubuntu/Debian, install: sudo apt install python${py_version}-venv"
            rm -rf "$VENV_DIR"
            exit 1
        fi
    fi
    source "$VENV_DIR/$VENV_BIN/activate"
    info "Venv active: $(which python3)"

    # Check krasis importable
    if ! python3 -c "from krasis import KrasisEngine" 2>/dev/null; then
        warn "Krasis not installed — building from source..."

        # Try sourcing cargo env in case Rust was just installed
        if ! command -v cargo &>/dev/null && [[ -f "$HOME/.cargo/env" ]]; then
            source "$HOME/.cargo/env"
        fi
        if ! command -v cargo &>/dev/null; then
            err "cargo not found. Install Rust, then restart your shell:"
            echo "  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
            echo "  source ~/.cargo/env"
            exit 1
        fi
        info "cargo found: $(cargo --version)"

        if ! python3 -c "import maturin" 2>/dev/null; then
            info "Installing maturin..."
            pip install maturin
        fi

        info "Building krasis (pip install -e .) — this may take a few minutes..."
        (cd "$SCRIPT_DIR" && pip install -e .)
        info "Krasis built successfully"
    else
        info "Krasis importable"
    fi

    # torch — don't auto-install, just check
    if ! python3 -c "import torch" 2>/dev/null; then
        err "PyTorch not installed. Install with:"
        echo "  pip install torch --index-url https://download.pytorch.org/whl/cu126"
        exit 1
    fi
    info "PyTorch $(python3 -c 'import torch; print(torch.__version__)')"

    # flashinfer — warn only
    if ! python3 -c "import flashinfer" 2>/dev/null; then
        warn "flashinfer not installed — GPU attention will fall back to manual implementation"
    else
        info "flashinfer available"
    fi

    # Small deps — auto-install
    local missing_deps=()
    for dep in uvicorn fastapi safetensors; do
        if ! python3 -c "import $dep" 2>/dev/null; then
            missing_deps+=("$dep")
        fi
    done
    if (( ${#missing_deps[@]} > 0 )); then
        info "Installing: ${missing_deps[*]}"
        pip install -q "${missing_deps[@]}"
    fi
    info "All dependencies satisfied"

    # System checks (read-only, advisory)
    if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]]; then
        local gov
        gov=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)
        if [[ "$gov" != "performance" ]]; then
            warn "CPU governor is '$gov' (not 'performance') — may reduce throughput"
        fi
    fi

    if [[ -f /proc/sys/vm/nr_hugepages ]]; then
        local hp
        hp=$(cat /proc/sys/vm/nr_hugepages)
        if (( hp == 0 )); then
            warn "Huge pages not enabled — may reduce memory bandwidth"
        fi
    fi
}

# ═══════════════════════════════════════════════════════════════════════
# Main
# ═══════════════════════════════════════════════════════════════════════

phase_setup

# Determine python binary
PYTHON_BIN="python3"
if [[ -f "$VENV_DIR/$VENV_BIN/python" ]]; then
    PYTHON_BIN="$VENV_DIR/$VENV_BIN/python"
fi

# Hand off to Python launcher for everything else
exec "$PYTHON_BIN" -m krasis.launcher "${PASSTHROUGH_ARGS[@]}"
