#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="${SCRIPT_DIR}"
VENV_PYTHON="${PROJECT_ROOT}/.venv/bin/python"
VENV_PIP="${PROJECT_ROOT}/.venv/bin/pip"
GUI_ENTRY="${PROJECT_ROOT}/python_app/gui/main.py"
REQUIREMENTS_FILE="${PROJECT_ROOT}/requirements.txt"

SKIP_BUILD=0
BUILD_ONLY=0
CLEAN_SHM=0

print_usage() {
    cat <<'EOF'
Usage: ./start.sh [options]

Options:
  --skip-build   Skip C++ build step and only run GUI
  --build-only   Build C++ binaries and exit
  --clean-shm    Remove known radar shared-memory segments before start
  -h, --help     Show this help
EOF
}

parse_args() {
    while (($# > 0)); do
        case "$1" in
            --skip-build)
                SKIP_BUILD=1
                ;;
            --build-only)
                BUILD_ONLY=1
                ;;
            --clean-shm)
                CLEAN_SHM=1
                ;;
            -h|--help)
                print_usage
                exit 0
                ;;
            *)
                echo "Unknown argument: $1" >&2
                print_usage
                exit 1
                ;;
        esac
        shift
    done
}

check_environment() {
    if ! command -v python3 >/dev/null 2>&1; then
        echo "python3 is not installed or not found in PATH." >&2
        exit 1
    fi

    if [[ ! -f "${REQUIREMENTS_FILE}" ]]; then
        echo "Requirements file not found: ${REQUIREMENTS_FILE}" >&2
        exit 1
    fi

    if [[ ! -f "${GUI_ENTRY}" ]]; then
        echo "GUI entry not found: ${GUI_ENTRY}" >&2
        exit 1
    fi
}

ensure_python_dependencies() {
    if [[ ! -x "${VENV_PYTHON}" ]]; then
        echo "[start.sh] Creating virtual environment..."
        python3 -m venv "${PROJECT_ROOT}/.venv"
    fi

    if [[ ! -x "${VENV_PIP}" ]]; then
        echo "pip is missing in virtual environment: ${VENV_PIP}" >&2
        exit 1
    fi

    echo "[start.sh] Installing Python dependencies..."
    "${VENV_PIP}" install --upgrade pip
    "${VENV_PIP}" install -r "${REQUIREMENTS_FILE}"
}

run_privileged() {
    if [[ "${EUID}" -eq 0 ]]; then
        "$@"
        return
    fi
    if command -v sudo >/dev/null 2>&1; then
        sudo "$@"
        return
    fi
    echo "Need elevated privileges to run: $*" >&2
    echo "Run as root or install 'sudo'." >&2
    exit 1
}

ensure_system_dependencies() {
    if command -v pkg-config >/dev/null 2>&1 && pkg-config --exists libusb-1.0; then
        return
    fi

    echo "[start.sh] Installing system dependency: libusb-1.0 dev headers..."
    if command -v apt-get >/dev/null 2>&1; then
        run_privileged apt-get update
        run_privileged apt-get install -y pkg-config libusb-1.0-0-dev
    elif command -v dnf >/dev/null 2>&1; then
        run_privileged dnf install -y pkgconf-pkg-config libusb1-devel
    elif command -v yum >/dev/null 2>&1; then
        run_privileged yum install -y pkgconfig libusb1-devel
    elif command -v pacman >/dev/null 2>&1; then
        run_privileged pacman -Sy --needed pkgconf libusb
    elif command -v zypper >/dev/null 2>&1; then
        run_privileged zypper --non-interactive install pkg-config libusb-1_0-devel
    elif command -v brew >/dev/null 2>&1; then
        brew install pkg-config libusb
    else
        echo "Could not detect supported package manager." >&2
        echo "Install manually: pkg-config and libusb development package." >&2
        exit 1
    fi

    if ! command -v pkg-config >/dev/null 2>&1 || ! pkg-config --exists libusb-1.0; then
        echo "libusb-1.0 development package is still unavailable after install attempt." >&2
        exit 1
    fi
}

ensure_usb_access_rules() {
    if [[ "$(uname -s)" != "Linux" ]]; then
        return
    fi
    if ! command -v udevadm >/dev/null 2>&1; then
        return
    fi

    local rule_file="/etc/udev/rules.d/99-radar-librevna.rules"
    local tmp_rule
    tmp_rule="$(mktemp)"

    cat > "${tmp_rule}" <<'EOF'
# LibreVNA USB access for non-root users
SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="564e", TAG+="uaccess"
SUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="4121", TAG+="uaccess"
SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="4121", TAG+="uaccess"
EOF

    if [[ -f "${rule_file}" ]] && cmp -s "${tmp_rule}" "${rule_file}"; then
        rm -f "${tmp_rule}"
        return
    fi

    echo "[start.sh] Installing udev rule for LibreVNA USB access..."
    run_privileged install -m 0644 "${tmp_rule}" "${rule_file}"
    rm -f "${tmp_rule}"

    run_privileged udevadm control --reload-rules
    run_privileged udevadm trigger
    echo "[start.sh] udev rules updated. Reconnect USB device if it is already plugged in."
}

build_cpp_binaries() {
    local jobs
    jobs="${BUILD_JOBS:-$(nproc)}"
    echo "[start.sh] Building C++ binaries (jobs=${jobs})..."
    make -C "${PROJECT_ROOT}" -j"${jobs}" all
}

cleanup_known_shm() {
    echo "[start.sh] Cleaning known shared-memory segments..."
    rm -f /dev/shm/radar_raw /dev/shm/radar_preprocessed /dev/shm/radar_results || true
}

run_gui() {
    echo "[start.sh] Launching GUI..."
    exec "${VENV_PYTHON}" "${GUI_ENTRY}"
}

main() {
    parse_args "$@"
    check_environment
    ensure_system_dependencies
    ensure_usb_access_rules
    ensure_python_dependencies

    if ((CLEAN_SHM == 1)); then
        cleanup_known_shm
    fi

    if ((SKIP_BUILD == 0)); then
        build_cpp_binaries
    fi

    if ((BUILD_ONLY == 1)); then
        echo "[start.sh] Build completed."
        exit 0
    fi

    run_gui
}

main "$@"
