#!/bin/bash

# Onebox Installer Script
# Downloads and installs pre-compiled Onebox binary from Gitea releases
#
# Usage:
#   Direct piped installation (recommended):
#     curl -sSL https://code.foss.global/serve.zone/onebox/raw/branch/main/install.sh | sudo bash
#
#   With version specification:
#     curl -sSL https://code.foss.global/serve.zone/onebox/raw/branch/main/install.sh | sudo bash -s -- --version v1.11.0
#
# Options:
#   -h, --help             Show this help message
#   --version VERSION      Install specific version (e.g., v1.11.0)
#   --install-dir DIR      Installation directory (default: /opt/onebox)

set -e

# Default values
SHOW_HELP=0
SPECIFIED_VERSION=""
INSTALL_DIR="/opt/onebox"
GITEA_BASE_URL="https://code.foss.global"
GITEA_REPO="serve.zone/onebox"
SERVICE_NAME="onebox"

# Parse command line arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    -h|--help)
      SHOW_HELP=1
      shift
      ;;
    --version)
      SPECIFIED_VERSION="$2"
      shift 2
      ;;
    --install-dir)
      INSTALL_DIR="$2"
      shift 2
      ;;
    *)
      echo "Unknown option: $1"
      echo "Use -h or --help for usage information"
      exit 1
      ;;
  esac
done

if [ $SHOW_HELP -eq 1 ]; then
  echo "Onebox Installer Script"
  echo "Downloads and installs pre-compiled Onebox binary"
  echo ""
  echo "Usage: $0 [options]"
  echo ""
  echo "Options:"
  echo "  -h, --help             Show this help message"
  echo "  --version VERSION      Install specific version (e.g., v1.11.0)"
  echo "  --install-dir DIR      Installation directory (default: /opt/onebox)"
  echo ""
  echo "Examples:"
  echo "  # Install latest version"
  echo "  curl -sSL https://code.foss.global/serve.zone/onebox/raw/branch/main/install.sh | sudo bash"
  echo ""
  echo "  # Install specific version"
  echo "  curl -sSL https://code.foss.global/serve.zone/onebox/raw/branch/main/install.sh | sudo bash -s -- --version v1.11.0"
  exit 0
fi

# Check if running as root
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root (sudo bash install.sh or pipe to sudo bash)"
  exit 1
fi

# Helper function to detect OS and architecture
detect_platform() {
  local os=$(uname -s)
  local arch=$(uname -m)

  # Map OS
  case "$os" in
    Linux)
      os_name="linux"
      ;;
    Darwin)
      os_name="macos"
      ;;
    MINGW*|MSYS*|CYGWIN*)
      os_name="windows"
      ;;
    *)
      echo "Error: Unsupported operating system: $os"
      echo "Supported: Linux, macOS, Windows"
      exit 1
      ;;
  esac

  # Map architecture
  case "$arch" in
    x86_64|amd64)
      arch_name="x64"
      ;;
    aarch64|arm64)
      arch_name="arm64"
      ;;
    *)
      echo "Error: Unsupported architecture: $arch"
      echo "Supported: x86_64/amd64 (x64), aarch64/arm64 (arm64)"
      exit 1
      ;;
  esac

  # Construct binary name
  if [ "$os_name" = "windows" ]; then
    echo "onebox-${os_name}-${arch_name}.exe"
  else
    echo "onebox-${os_name}-${arch_name}"
  fi
}

# Get latest release version from Gitea API
get_latest_version() {
  echo "Fetching latest release version from Gitea..." >&2

  local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest"
  local response=$(curl -sSL "$api_url" 2>/dev/null)

  if [ $? -ne 0 ] || [ -z "$response" ]; then
    echo "Error: Failed to fetch latest release information from Gitea API" >&2
    echo "URL: $api_url" >&2
    exit 1
  fi

  # Extract tag_name from JSON response
  local version=$(echo "$response" | grep -o '"tag_name":"[^"]*"' | cut -d'"' -f4)

  if [ -z "$version" ]; then
    echo "Error: Could not determine latest version from API response" >&2
    exit 1
  fi

  echo "$version"
}

# Main installation process
echo "================================================"
echo "  Onebox Installation Script"
echo "================================================"
echo ""

# Detect platform
BINARY_NAME=$(detect_platform)
echo "Detected platform: $BINARY_NAME"
echo ""

# Determine version to install
if [ -n "$SPECIFIED_VERSION" ]; then
  VERSION="$SPECIFIED_VERSION"
  echo "Installing specified version: $VERSION"
else
  VERSION=$(get_latest_version)
  echo "Installing latest version: $VERSION"
fi
echo ""

# Construct download URL
DOWNLOAD_URL="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${BINARY_NAME}"
echo "Download URL: $DOWNLOAD_URL"
echo ""

# Check whether the service should be restarted after a successful install.
SERVICE_WAS_RUNNING=0
if systemctl is-enabled --quiet "$SERVICE_NAME" 2>/dev/null || systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
  SERVICE_WAS_RUNNING=1
fi

# Download and validate the new binary before touching the running service.
echo "Downloading Onebox binary..."
TEMP_DIR=$(mktemp -d)
TEMP_FILE="$TEMP_DIR/$BINARY_NAME"
cleanup_temp() {
  rm -rf "$TEMP_DIR"
}
trap cleanup_temp EXIT

if ! curl -fSL "$DOWNLOAD_URL" -o "$TEMP_FILE"; then
  echo "Error: Failed to download binary from $DOWNLOAD_URL"
  echo ""
  echo "Please check:"
  echo "  1. Your internet connection"
  echo "  2. The specified version exists: ${GITEA_BASE_URL}/${GITEA_REPO}/releases"
  echo "  3. The platform binary is available for this release"
  exit 1
fi

if [ ! -s "$TEMP_FILE" ]; then
  echo "Error: Downloaded file is empty or does not exist"
  exit 1
fi

chmod +x "$TEMP_FILE"
if ! "$TEMP_FILE" --version >/dev/null 2>&1; then
  echo "Error: Downloaded file is not an executable Onebox binary"
  exit 1
fi

SERVICE_STOPPED=0
restart_previous_service_on_error() {
  if [ $SERVICE_STOPPED -eq 1 ]; then
    echo "Installation failed after stopping Onebox; restarting previous service..."
    systemctl start "$SERVICE_NAME" || true
  fi
}
trap 'restart_previous_service_on_error; cleanup_temp' ERR

if [ $SERVICE_WAS_RUNNING -eq 1 ] && systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
  echo "Stopping Onebox service..."
  systemctl stop "$SERVICE_NAME"
  SERVICE_STOPPED=1
fi

# Clean installation directory - ensure only binary exists
if [ -d "$INSTALL_DIR" ]; then
  echo "Cleaning installation directory: $INSTALL_DIR"
  rm -rf "$INSTALL_DIR"
fi

# Create fresh installation directory
echo "Creating installation directory: $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"

# Install binary
BINARY_PATH="$INSTALL_DIR/onebox"
if ! install -m 0755 "$TEMP_FILE" "$BINARY_PATH" || [ ! -f "$BINARY_PATH" ]; then
  echo "Error: Failed to install binary to $BINARY_PATH"
  exit 1
fi

echo "Binary installed successfully to: $BINARY_PATH"
echo ""

# Check if /usr/local/bin is in PATH
if [[ ":$PATH:" == *":/usr/local/bin:"* ]]; then
  BIN_DIR="/usr/local/bin"
else
  BIN_DIR="/usr/bin"
fi

# Create symlink for global access
ln -sf "$BINARY_PATH" "$BIN_DIR/onebox"
echo "Symlink created: $BIN_DIR/onebox -> $BINARY_PATH"
echo ""

# Create data directories
mkdir -p /var/lib/onebox
mkdir -p /var/www/certbot

# Re-enable and restart service if it was previously running (refreshes unit file)
if [ $SERVICE_WAS_RUNNING -eq 1 ]; then
  echo "Refreshing systemd service..."
  onebox systemd enable
  echo "Restarting Onebox service..."
  systemctl restart "$SERVICE_NAME"
  SERVICE_STOPPED=0
  echo "Service restarted successfully."
  echo ""
fi

trap - ERR

echo "================================================"
echo "  Onebox Installation Complete!"
echo "================================================"
echo ""
echo "Installation details:"
echo "  Binary location: $BINARY_PATH"
echo "  Symlink location: $BIN_DIR/onebox"
echo "  Version: $VERSION"
echo ""

# Check if database exists (indicates existing installation)
if [ -f "/var/lib/onebox/onebox.db" ]; then
  echo "Data directory: /var/lib/onebox (preserved)"
  echo ""
  echo "Your existing data has been preserved."
  if [ $SERVICE_WAS_RUNNING -eq 1 ]; then
    echo "The service has been restarted with your current settings."
  else
    echo "Start the service with: onebox systemd start"
  fi
else
  echo "Get started:"
  echo ""
  echo "  onebox --version"
  echo "  onebox --help"
  echo ""
  echo "  1. Configure Cloudflare (optional):"
  echo "     onebox config set cloudflareAPIKey <key>"
  echo "     onebox config set cloudflareEmail <email>"
  echo "     onebox config set cloudflareZoneID <zone-id>"
  echo "     onebox config set serverIP <your-server-ip>"
  echo ""
  echo "  2. Configure ACME email:"
  echo "     onebox config set acmeEmail <your@email.com>"
  echo ""
  echo "  3. Enable systemd service:"
  echo "     onebox systemd enable"
  echo ""
  echo "  4. Start service:"
  echo "     onebox systemd start"
  echo ""
  echo "  5. Deploy your first service:"
  echo "     onebox service add myapp --image nginx:latest --domain app.example.com"
  echo ""
  echo "  Web UI: http://localhost:3000"
  echo "  Initial admin credentials are written to the service logs unless ONEBOX_ADMIN_PASSWORD is set."
fi
echo ""
