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

usage() {
  cat <<'EOF'
Install SPL local daemon on Linux.

Options:
  --repo-root PATH        Repository root. Defaults to two levels above this script.
  --prefix PATH           Install root. Defaults to ~/.splime/local-daemon.
  --home PATH             Daemon state directory. Defaults to ~/.spl-daemon.
  --python PATH           Python 3.13+ executable. Defaults to python3.13.
  --host HOST             Bind host. Defaults to 127.0.0.1.
  --port PORT             Preferred port. Defaults to 8765.
  --wheel-dir PATH        Install from local wheels with --find-links.
  --wheel-url URL         Download SPL wheel bundle. Defaults to https://splime.io/downloads/splime-wheels-0.1.0.zip.
  --no-wheel-download     Skip the default SPL wheel bundle and install from package index.
  --install-service       Install a systemd user service.
  --start                 Start/restart the service after install.
  -h, --help              Show this help.
EOF
}

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
PREFIX="${HOME}/.splime/local-daemon"
DAEMON_HOME="${HOME}/.spl-daemon"
PYTHON_BIN="${PYTHON_BIN:-python3.13}"
HOST="127.0.0.1"
PORT="8765"
WHEEL_DIR=""
WHEEL_URL="${SPL_WHEEL_URL:-https://splime.io/downloads/splime-wheels-0.1.0.zip}"
INSTALL_SERVICE=0
START_SERVICE=0
CLI_BIN_DIR="${HOME}/.local/bin"

append_path_block() {
  local profile_file="$1"
  local begin_marker="# >>> SPLime local daemon >>>"
  local end_marker="# <<< SPLime local daemon <<<"
  mkdir -p "$(dirname "$profile_file")"
  touch "$profile_file"
  if grep -Fq "$begin_marker" "$profile_file"; then
    return 0
  fi
  cat >> "$profile_file" <<EOF

$begin_marker
if [ -d "$CLI_BIN_DIR" ]; then
  case ":\$PATH:" in
    *":$CLI_BIN_DIR:"*) ;;
    *) export PATH="$CLI_BIN_DIR:\$PATH" ;;
  esac
fi
$end_marker
EOF
}

install_cli_wrapper() {
  local wrapper_file="$CLI_BIN_DIR/spl-daemon"
  mkdir -p "$CLI_BIN_DIR"
  cat > "$wrapper_file" <<EOF
#!/usr/bin/env bash
exec "$VENV_DIR/bin/spl-daemon" "\$@"
EOF
  chmod +x "$wrapper_file"

  append_path_block "${HOME}/.profile"
  append_path_block "${HOME}/.bashrc"
  append_path_block "${HOME}/.zshrc"
}

download_file() {
  local url="$1"
  local destination="$2"
  if command -v curl >/dev/null 2>&1; then
    curl -fL "$url" -o "$destination"
  elif command -v wget >/dev/null 2>&1; then
    wget -O "$destination" "$url"
  else
    "$VENV_DIR/bin/python" - "$url" "$destination" <<'PY'
import pathlib
import sys
import urllib.request

url = sys.argv[1]
destination = pathlib.Path(sys.argv[2])
with urllib.request.urlopen(url, timeout=120) as response:
    destination.write_bytes(response.read())
PY
  fi
}

install_downloaded_wheel_bundle() {
  local wheel_cache_dir="$PREFIX/wheel-cache"
  local archive_file="$wheel_cache_dir/splime-wheels.zip"
  local extract_dir="$wheel_cache_dir/extracted"
  rm -rf "$wheel_cache_dir"
  mkdir -p "$extract_dir"

  echo "Downloading SPL wheel bundle from $WHEEL_URL"
  download_file "$WHEEL_URL" "$archive_file"
  "$VENV_DIR/bin/python" -m zipfile -e "$archive_file" "$extract_dir"

  local framework_wheel
  local daemon_wheel
  framework_wheel="$(find "$extract_dir" -type f -name 'spl_framework-*.whl' | sort | tail -n 1)"
  daemon_wheel="$(find "$extract_dir" -type f -name 'spl_daemon-*.whl' | sort | tail -n 1)"
  if [[ -z "$framework_wheel" || -z "$daemon_wheel" ]]; then
    echo "Downloaded wheel bundle does not contain spl-framework and spl-daemon wheels." >&2
    exit 1
  fi

  "$VENV_DIR/bin/python" -m pip install --upgrade --force-reinstall "$framework_wheel" "$daemon_wheel"
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --repo-root) REPO_ROOT="$2"; shift 2 ;;
    --prefix) PREFIX="$2"; shift 2 ;;
    --home) DAEMON_HOME="$2"; shift 2 ;;
    --python) PYTHON_BIN="$2"; shift 2 ;;
    --host) HOST="$2"; shift 2 ;;
    --port) PORT="$2"; shift 2 ;;
    --wheel-dir) WHEEL_DIR="$2"; shift 2 ;;
    --wheel-url) WHEEL_URL="$2"; shift 2 ;;
    --no-wheel-download) WHEEL_URL=""; shift ;;
    --install-service) INSTALL_SERVICE=1; shift ;;
    --start) START_SERVICE=1; shift ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown option: $1" >&2; usage; exit 2 ;;
  esac
done

REPO_ROOT="$(cd "$REPO_ROOT" && pwd)"
PREFIX="$(mkdir -p "$PREFIX" && cd "$PREFIX" && pwd)"
DAEMON_HOME="$(mkdir -p "$DAEMON_HOME" && cd "$DAEMON_HOME" && pwd)"
VENV_DIR="$PREFIX/venv"

"$PYTHON_BIN" -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 13) else "Python 3.13+ is required")'

echo "Creating private virtual environment: $VENV_DIR"
"$PYTHON_BIN" -m venv "$VENV_DIR"
"$VENV_DIR/bin/python" -m pip install --upgrade pip

if [[ -n "$WHEEL_DIR" ]]; then
  WHEEL_DIR="$(cd "$WHEEL_DIR" && pwd)"
  echo "Installing spl-framework and spl-daemon from wheels in $WHEEL_DIR"
  "$VENV_DIR/bin/python" -m pip install --upgrade --force-reinstall --no-index --find-links "$WHEEL_DIR" spl-framework spl-daemon
elif [[ -d "$REPO_ROOT/spl-core" && -d "$REPO_ROOT/spl-daemon" ]]; then
  echo "Installing spl-framework and spl-daemon from source checkout"
  "$VENV_DIR/bin/python" -m pip install --upgrade --force-reinstall "$REPO_ROOT/spl-core" "$REPO_ROOT/spl-daemon"
elif [[ -n "$WHEEL_URL" ]]; then
  install_downloaded_wheel_bundle
else
  echo "Installing spl-daemon from package index"
  "$VENV_DIR/bin/python" -m pip install --upgrade --force-reinstall spl-daemon
fi

echo "Installing/updating certifi CA bundle for HTTPS verification"
"$VENV_DIR/bin/python" -m pip install --upgrade certifi
CA_BUNDLE="$("$VENV_DIR/bin/python" -c 'import certifi; print(certifi.where())')"
if [[ ! -f "$CA_BUNDLE" ]]; then
  echo "certifi CA bundle was not found: $CA_BUNDLE" >&2
  exit 1
fi

"$VENV_DIR/bin/python" -c 'from spl.client import SPLClient; import spl.daemon.server; print("SPL daemon import check ok")'

mkdir -p "$PREFIX" "$DAEMON_HOME"
cat > "$PREFIX/daemon.env" <<EOF
SPL_DAEMON_HOME=$DAEMON_HOME
SPL_DAEMON_HOST=$HOST
SPL_DAEMON_PORT=$PORT
SSL_CERT_FILE=$CA_BUNDLE
REQUESTS_CA_BUNDLE=$CA_BUNDLE
EOF

install_cli_wrapper

if [[ "$INSTALL_SERVICE" -eq 1 ]]; then
  SERVICE_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
  SERVICE_FILE="$SERVICE_DIR/spl-daemon.service"
  mkdir -p "$SERVICE_DIR"
  cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=SPLime local daemon
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Environment=SPL_DAEMON_HOME=$DAEMON_HOME
Environment=SSL_CERT_FILE=$CA_BUNDLE
Environment=REQUESTS_CA_BUNDLE=$CA_BUNDLE
ExecStart=$VENV_DIR/bin/spl-daemon serve --host $HOST --port $PORT --home $DAEMON_HOME
Restart=always
RestartSec=10
WorkingDirectory=$DAEMON_HOME

[Install]
WantedBy=default.target
EOF
  systemctl --user daemon-reload
  systemctl --user enable spl-daemon.service
  echo "Installed user service: $SERVICE_FILE"
  if [[ "$START_SERVICE" -eq 1 ]]; then
    systemctl --user restart spl-daemon.service
    echo "Started spl-daemon.service"
  fi
elif [[ "$START_SERVICE" -eq 1 ]]; then
  echo "--start requires --install-service on Linux" >&2
  exit 2
fi

echo "Installed SPL local daemon."
echo "Binary: $VENV_DIR/bin/spl-daemon"
echo "CLI:    $CLI_BIN_DIR/spl-daemon"
echo "Home:   $DAEMON_HOME"
