#!/bin/bash
#===============================================================================
# Nugiserver Bootstrap Installer
#===============================================================================
#
# This script downloads and installs the latest version of Nugiserver.
#
# Usage:
#   curl -fsSL https://install.nugiserver.com | sudo bash
#   curl -fsSL https://raw.githubusercontent.com/nugitech/nugiserver/main/scripts/bootstrap.sh | sudo bash
#
# Options (pass as environment variables):
#   VERSION=v1.0.0        Install specific version (default: latest)
#   INSTALL_DIR=/opt/...  Custom installation directory
#   SKIP_START=1          Don't start services after install
#
# Or with options:
#   curl -fsSL ... | sudo VERSION=v1.0.0 bash
#
#===============================================================================

set -euo pipefail

# Configuration
# Using self-hosted release server at releases.servyx.nugitech.com
#
RELEASE_SERVER="https://releases.servyx.nugitech.com"
DOWNLOAD_BASE_URL="${DOWNLOAD_BASE_URL:-${RELEASE_SERVER}/releases}"
VERSION_URL="${VERSION_URL:-${RELEASE_SERVER}/VERSION}"

# GitHub fallback (if self-hosted fails)
GITHUB_OWNER="${GITHUB_OWNER:-nugitech}"
GITHUB_REPO="${GITHUB_REPO:-servyx}"

# GitHub token for private repos (required for private repos)
GITHUB_TOKEN="${GITHUB_TOKEN:-}"

# Defaults
VERSION="${VERSION:-latest}"
INSTALL_DIR="${INSTALL_DIR:-/opt/nugiserver}"
TMP_DIR="/tmp/nugiserver-install-$$"
SKIP_START="${SKIP_START:-0}"

# Server credentials (can be passed as env vars or will prompt)
SERVER_ID="${SERVER_ID:-}"
API_KEY="${API_KEY:-}"
SERVER_TOKEN="${SERVER_TOKEN:-}"

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

#===============================================================================
# Helper Functions
#===============================================================================

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step() { echo -e "${CYAN}==>${NC} $1"; }

cleanup() {
  rm -rf "$TMP_DIR" 2>/dev/null || true
}
trap cleanup EXIT

check_root() {
  if [[ $EUID -ne 0 ]]; then
    log_error "This script must be run as root (use sudo)"
    exit 1
  fi
}

check_os() {
  if [[ ! -f /etc/os-release ]]; then
    log_error "Unsupported OS. This installer supports Debian/Ubuntu/CentOS/Fedora/AlmaLinux."
    exit 1
  fi
  
  # Read OS info without overwriting our VERSION variable
  OS_NAME=$(grep -E "^NAME=" /etc/os-release | cut -d'"' -f2)
  OS_VERSION=$(grep -E "^VERSION_ID=" /etc/os-release | cut -d'"' -f2)
  OS_ID=$(grep -E "^ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"')
  
  log_info "Detected OS: $OS_NAME $OS_VERSION"
  
  case "$OS_ID" in
    debian|ubuntu|centos|rhel|fedora|almalinux|rocky)
      log_success "OS is supported"
      ;;
    *)
      log_warn "OS '$OS_ID' may not be fully tested"
      ;;
  esac
}

check_arch() {
  ARCH=$(uname -m)
  case "$ARCH" in
    x86_64|amd64)
      ARCH="amd64"
      ;;
    aarch64|arm64)
      ARCH="arm64"
      ;;
    *)
      log_error "Unsupported architecture: $ARCH"
      exit 1
      ;;
  esac
  log_info "Architecture: $ARCH"
}

get_latest_version() {
  if [[ "$VERSION" == "latest" ]]; then
    log_info "Fetching latest version..."
    
    # Try self-hosted VERSION file first
    if [[ -n "$VERSION_URL" ]]; then
      if command -v curl &> /dev/null; then
        VERSION=$(curl -fsSL "$VERSION_URL" 2>/dev/null | tr -d '[:space:]' || echo "")
      elif command -v wget &> /dev/null; then
        VERSION=$(wget -qO- "$VERSION_URL" 2>/dev/null | tr -d '[:space:]' || echo "")
      fi
      
      if [[ -n "$VERSION" && "$VERSION" =~ ^v[0-9] ]]; then
        log_info "Got version from self-hosted: $VERSION"
        return
      fi
    fi
    
    # Fallback to hardcoded latest
    log_warn "Could not fetch latest version, using default"
    VERSION="v1.0.0"
  fi
  
  log_info "Installing version: $VERSION"
}

download_release() {
  log_step "Downloading Nugiserver $VERSION..."
  
  mkdir -p "$TMP_DIR"
  cd "$TMP_DIR"
  
  # Determine download source
  if [[ -n "$DOWNLOAD_BASE_URL" ]]; then
    # Self-hosted server - direct download (no auth needed)
    log_info "Using self-hosted release server..."
    
    TARBALL_URL="${DOWNLOAD_BASE_URL}/${VERSION}/nugiserver-${VERSION}.tar.gz"
    CHECKSUM_URL="${DOWNLOAD_BASE_URL}/${VERSION}/nugiserver-${VERSION}.tar.gz.sha256"
    
    log_info "Downloading from: $TARBALL_URL"
    
    if command -v curl &> /dev/null; then
      curl -fL --progress-bar -o "nugiserver.tar.gz" "$TARBALL_URL" || {
        log_error "Failed to download release from self-hosted server."
        log_error "Check if $TARBALL_URL exists."
        exit 1
      }
      # Try to download checksum (optional)
      curl -fsSL -o "nugiserver.tar.gz.sha256" "$CHECKSUM_URL" 2>/dev/null || true
    elif command -v wget &> /dev/null; then
      wget --progress=bar:force -O "nugiserver.tar.gz" "$TARBALL_URL" 2>&1 || {
        log_error "Failed to download release from self-hosted server."
        log_error "Check if $TARBALL_URL exists."
        exit 1
      }
      # Try to download checksum (optional)
      wget -q -O "nugiserver.tar.gz.sha256" "$CHECKSUM_URL" 2>/dev/null || true
    else
      log_error "Neither curl nor wget found. Please install one of them."
      exit 1
    fi
    
  elif [[ -n "$GITHUB_TOKEN" ]]; then
    # Private GitHub repo - use API
    log_info "Using GitHub token for private repo access..."
    
    RELEASE_URL="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/releases/tags/${VERSION}"
    ASSET_URL=$(curl -fsSL -H "Authorization: token $GITHUB_TOKEN" "$RELEASE_URL" 2>/dev/null | \
      grep -o '"url": "[^"]*nugiserver-.*\.tar\.gz"' | head -1 | sed 's/"url": "//;s/"$//' || echo "")
    
    if [[ -z "$ASSET_URL" ]]; then
      log_error "Could not find release asset. Check if version $VERSION exists."
      exit 1
    fi
    
    log_info "Downloading from GitHub API..."
    curl -fsSL -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/octet-stream" \
      -o "nugiserver.tar.gz" "$ASSET_URL" || {
      log_error "Failed to download release."
      exit 1
    }
    
  else
    # Public GitHub repo - direct download
    TARBALL_URL="https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/releases/download/${VERSION}/nugiserver-${VERSION}.tar.gz"
    CHECKSUM_URL="https://github.com/${GITHUB_OWNER}/${GITHUB_REPO}/releases/download/${VERSION}/nugiserver-${VERSION}.tar.gz.sha256"
    
    log_info "Downloading from: $TARBALL_URL"
    
    if command -v curl &> /dev/null; then
      curl -fsSL -o "nugiserver.tar.gz" "$TARBALL_URL" || {
        log_error "Failed to download release. Check if version $VERSION exists."
        log_error "For private repos, set GITHUB_TOKEN environment variable."
        exit 1
      }
      
      # Try to download checksum (optional)
      curl -fsSL -o "nugiserver.tar.gz.sha256" "$CHECKSUM_URL" 2>/dev/null || true
    elif command -v wget &> /dev/null; then
      wget -q -O "nugiserver.tar.gz" "$TARBALL_URL" || {
        log_error "Failed to download release. Check if version $VERSION exists."
        exit 1
      }
      wget -q -O "nugiserver.tar.gz.sha256" "$CHECKSUM_URL" 2>/dev/null || true
    else
      log_error "Neither curl nor wget found. Please install curl."
      exit 1
    fi
  fi
  
  # Verify checksum if available
  if [[ -f "nugiserver.tar.gz.sha256" && -s "nugiserver.tar.gz.sha256" ]]; then
    log_info "Verifying checksum..."
    # Extract just the hash and verify against our downloaded file
    EXPECTED_HASH=$(cat nugiserver.tar.gz.sha256 | awk '{print $1}')
    if command -v sha256sum &> /dev/null; then
      ACTUAL_HASH=$(sha256sum nugiserver.tar.gz | awk '{print $1}')
      if [[ "$EXPECTED_HASH" != "$ACTUAL_HASH" ]]; then
        log_error "Checksum verification failed!"
        log_error "Expected: $EXPECTED_HASH"
        log_error "Got:      $ACTUAL_HASH"
        exit 1
      fi
      log_success "Checksum verified"
    elif command -v shasum &> /dev/null; then
      ACTUAL_HASH=$(shasum -a 256 nugiserver.tar.gz | awk '{print $1}')
      if [[ "$EXPECTED_HASH" != "$ACTUAL_HASH" ]]; then
        log_error "Checksum verification failed!"
        exit 1
      fi
      log_success "Checksum verified"
    else
      log_warn "No checksum tool available, skipping verification"
    fi
  else
    log_warn "No checksum file available, skipping verification"
  fi
  
  # Extract (suppress macOS extended attribute warnings on Linux)
  log_info "Extracting..."
  if ! tar -xzf nugiserver.tar.gz 2> >(grep -v "Ignoring unknown extended header" >&2); then
    log_error "Failed to extract package"
    exit 1
  fi
  
  log_success "Download complete"
}

run_installer() {
  log_step "Running installer..."
  
  cd "$TMP_DIR/nugiserver"
  
  # Make installer executable
  chmod +x packages/installer/install.sh
  
  # Export VERSION for the installer to use
  export VERSION
  
  # Run with options
  INSTALLER_OPTS=""
  if [[ "$SKIP_START" == "1" ]]; then
    INSTALLER_OPTS="--dev"
  fi
  
  bash packages/installer/install.sh $INSTALLER_OPTS
}

load_existing_credentials() {
  # Check if this is an upgrade (existing installation)
  local AGENT_ENV="/etc/nugiserver/agent.env"
  
  if [[ -f "$AGENT_ENV" ]]; then
    log_info "Detected existing installation, loading credentials..."
    
    # Source the existing credentials
    set -a  # Auto-export all variables
    source "$AGENT_ENV"
    set +a
    
    # Validate we got the credentials
    if [[ -n "$SERVER_ID" && -n "$API_KEY" && -n "$SERVER_TOKEN" ]]; then
      log_success "Credentials loaded from existing installation"
      export SERVER_ID API_KEY SERVER_TOKEN
      return 0
    fi
  fi
  
  return 1
}

prompt_credentials() {
  echo ""
  
  # Try to load existing credentials first (for upgrades)
  if load_existing_credentials; then
    log_info "Server ID: $SERVER_ID"
    log_info "API Key: ${API_KEY:0:10}..."
    log_info "Server Token: ***configured***"
    return
  fi
  
  log_step "Server Configuration"
  echo ""
  
  # Only prompt if not provided via env vars
  if [[ -z "$SERVER_ID" ]]; then
    read -p "Enter Server ID: " SERVER_ID
  else
    log_info "Server ID: $SERVER_ID"
  fi
  
  if [[ -z "$API_KEY" ]]; then
    read -p "Enter API Key: " API_KEY
  else
    log_info "API Key: ${API_KEY:0:10}..."
  fi
  
  if [[ -z "$SERVER_TOKEN" ]]; then
    read -sp "Enter Server Token: " SERVER_TOKEN
    echo ""
  else
    log_info "Server Token: ***configured***"
  fi
  
  # Validate required fields
  if [[ -z "$SERVER_ID" || -z "$API_KEY" || -z "$SERVER_TOKEN" ]]; then
    log_error "Server ID, API Key, and Server Token are required!"
    exit 1
  fi
  
  # Export for installer
  export SERVER_ID API_KEY SERVER_TOKEN
  
  log_success "Credentials configured"
}

show_completion() {
  echo ""
  echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
  echo -e "${GREEN}║                                                              ║${NC}"
  echo -e "${GREEN}║   🎉 Servyx installed successfully!                          ║${NC}"
  echo -e "${GREEN}║                                                              ║${NC}"
  echo -e "${GREEN}║   Version: $VERSION                                          ║${NC}"
  echo -e "${GREEN}║   Server ID: $SERVER_ID                                      ║${NC}"
  echo -e "${GREEN}║                                                              ║${NC}"
  echo -e "${GREEN}║   Commands:                                                  ║${NC}"
  echo -e "${GREEN}║     servyx status    - Check service status                  ║${NC}"
  echo -e "${GREEN}║     servyx logs      - View logs                             ║${NC}"
  echo -e "${GREEN}║     servyx restart   - Restart services                      ║${NC}"
  echo -e "${GREEN}║                                                              ║${NC}"
  echo -e "${GREEN}║   Documentation: https://docs.servyx.nugitech.com            ║${NC}"
  echo -e "${GREEN}║                                                              ║${NC}"
  echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
  echo ""
}

#===============================================================================
# Main
#===============================================================================

main() {
  echo ""
  echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
  echo -e "${CYAN}║                                                              ║${NC}"
  echo -e "${CYAN}║   🚀 Servyx Bootstrap Installer                              ║${NC}"
  echo -e "${CYAN}║                                                              ║${NC}"
  echo -e "${CYAN}║   This will download and install Servyx on your system.      ║${NC}"
  echo -e "${CYAN}║                                                              ║${NC}"
  echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
  echo ""
  
  check_root
  check_os
  check_arch
  prompt_credentials
  get_latest_version
  download_release
  run_installer
  show_completion
}

main "$@"

