#!/bin/bash
# WireShield Python venv setup script
# Called during package installation to create and populate the virtual environment
set -e

BACKEND_DIR="${WIRESHIELD_BACKEND_DIR:-/opt/45drives/wireshield}"
VENV_DIR="$BACKEND_DIR/venv"
STATUS_DIR=/run/wireshield
STATUS_FILE="$STATUS_DIR/venv.status"

# The backend reads this back so the UI can show why the runtime is not ready.
write_status() {
    mkdir -p "$STATUS_DIR" 2>/dev/null || return 0
    printf '%s\t%s\n' "$1" "$2" >"$STATUS_FILE" 2>/dev/null || true
}

# A transaction already holds the package lock - usually the one installing
# WireShield, since this runs from %post. dnf/apt would block on it, not fail.
pkg_manager_busy() {
    for p in dnf dnf5 yum rpm apt apt-get dpkg; do
        pgrep -x "$p" >/dev/null 2>&1 && return 0
    done
    return 1
}

trap 'write_status error "Setting up the WireShield Python environment failed. Check: journalctl -u wireshield"' ERR

cd "$BACKEND_DIR" || exit 1

# Check if Python version is >= 3.9
# The backend annotates with PEP 585 builtin generics (list[X]), which pydantic
# evaluates at import time — 3.8 fails with "'type' object is not subscriptable".
py_ok() {
    "$1" -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 9) else 1)" >/dev/null 2>&1
}

# Function to find a suitable Python binary
pick_py() {
    for py in python3.12 python3.11 python3.10 python3.9 python3; do
        if command -v "$py" >/dev/null 2>&1 && py_ok "$py"; then
            echo "$py"
            return 0
        fi
    done
    return 1
}

# Try to find existing Python
PY_BIN=""
if PY_BIN=$(pick_py); then
    if ! py_ok "$PY_BIN"; then
        echo "Detected $PY_BIN but version is too old (need >= 3.9)" >&2
        PY_BIN=""
    fi
fi

# Install Python if not found or version too old
if [ -z "$PY_BIN" ] && [ "${WIRESHIELD_SKIP_PKG_INSTALL:-0}" != "1" ] && ! pkg_manager_busy; then
    echo "Installing Python 3.9+..." >&2
    if command -v dnf >/dev/null 2>&1; then
        dnf install -y python3.11 python3.11-pip python3.11-devel 2>/dev/null || \
        dnf install -y python39 python39-pip python39-devel 2>/dev/null || \
        dnf install -y python3.9 python3.9-pip python3.9-devel 2>/dev/null || true
    elif command -v yum >/dev/null 2>&1; then
        yum install -y python3.11 python3.11-pip python3.11-devel 2>/dev/null || \
        yum install -y python39 python39-pip python39-devel 2>/dev/null || \
        yum install -y python3.9 python3.9-pip python3.9-devel 2>/dev/null || true
    elif command -v apt-get >/dev/null 2>&1; then
        apt-get update -qq && apt-get install -y python3.11 python3.11-venv python3-pip 2>/dev/null || \
        apt-get install -y python3.9 python3.9-venv python3-pip 2>/dev/null || true
    fi
    
    PY_BIN=$(pick_py) || true
fi

# Verify Python is available and correct version
if [ -z "$PY_BIN" ] || ! py_ok "$PY_BIN"; then
    if [ "${WIRESHIELD_SKIP_PKG_INSTALL:-0}" = "1" ] || pkg_manager_busy; then
        echo "WARNING: Python >= 3.9 is missing and a package transaction is in progress." >&2
        echo "         Setup runs again once it finishes." >&2
        write_status pending "Python 3.9+ is not installed yet; the WireShield runtime is set up automatically once the current package transaction finishes."
        exit 0
    fi
    echo "ERROR: Unable to find/install Python >= 3.9" >&2
    echo "Please install python3.9+ manually and rerun: /usr/libexec/wireshield/setup-venv" >&2
    write_status error "Could not install Python 3.9 or newer, which the WireShield backend requires."
    exit 1
fi

echo "Using Python: $PY_BIN ($("$PY_BIN" --version 2>&1))" >&2

# Setup or recreate venv if Python version changed
if [ -d "$VENV_DIR" ]; then
    if ! "$VENV_DIR/bin/python" -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 9) else 1)" >/dev/null 2>&1; then
        echo "Existing venv uses old Python; recreating with $PY_BIN" >&2
        rm -rf "$VENV_DIR"
        "$PY_BIN" -m venv "$VENV_DIR"
    fi
else
    echo "Creating Python virtual environment..." >&2
    "$PY_BIN" -m venv "$VENV_DIR"
fi

# Install/upgrade Python dependencies
echo "Installing Python dependencies..." >&2
"$VENV_DIR/bin/python" -m pip install --quiet --upgrade pip setuptools wheel
"$VENV_DIR/bin/python" -m pip install --quiet -r requirements.txt

# Verify uvicorn is installed
"$VENV_DIR/bin/python" -m pip show uvicorn >/dev/null || {
    echo "ERROR: uvicorn not installed in venv" >&2
    write_status error "The WireShield Python environment is incomplete (uvicorn missing)."
    exit 1
}

write_status ok "Python environment ready."
echo "Python venv setup complete" >&2
