#!/usr/bin/env bash
# nself Installation Script
# Compatible with Bash 3.2+ (macOS, Linux, WSL)
# Usage: curl -fsSL https://install.nself.org | bash

set -e

# Colors (only when running in a terminal)
if [ -t 1 ]; then
  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[1;33m'
  BLUE='\033[0;34m'
  CYAN='\033[0;36m'
  BOLD='\033[1m'
  RESET='\033[0m'
else
  RED=''
  GREEN=''
  YELLOW=''
  BLUE=''
  CYAN=''
  BOLD=''
  RESET=''
fi

# Configuration
GITHUB_REPO="nself-org/cli"
GITHUB_API="https://api.github.com/repos/$GITHUB_REPO"
INSTALL_DIR="${NSELF_INSTALL_DIR:-$HOME/.nself}"
NSELF_VERSION="${NSELF_VERSION:-}"
FORCE_REINSTALL="${FORCE_REINSTALL:-false}"

# Logging
log_info() {
  printf "${BLUE}→${RESET} %s\n" "$1"
}

log_success() {
  printf "${GREEN}✓${RESET} %s\n" "$1"
}

log_error() {
  printf "${RED}✗${RESET} %s\n" "$1" >&2
}

log_warning() {
  printf "${YELLOW}!${RESET} %s\n" "$1"
}

log_step() {
  printf "\n${BOLD}%s${RESET}\n" "$1"
}

# Detect OS and architecture
detect_platform() {
  OS="$(uname -s)"
  ARCH="$(uname -m)"

  case "$OS" in
    Linux*)
      OS="linux"
      ;;
    Darwin*)
      OS="macos"
      ;;
    MINGW*|MSYS*|CYGWIN*)
      log_error "Windows native is not supported. Please use WSL (Windows Subsystem for Linux)."
      exit 1
      ;;
    *)
      log_error "Unsupported operating system: $OS"
      exit 1
      ;;
  esac

  case "$ARCH" in
    x86_64|amd64)
      ARCH="x86_64"
      ;;
    aarch64|arm64)
      ARCH="arm64"
      ;;
    *)
      log_warning "Architecture '$ARCH' is not officially tested"
      ;;
  esac

  log_info "Platform: $OS ($ARCH)"
}

# Check bash version
check_bash_version() {
  local major
  major="${BASH_VERSION%%.*}"

  if [ -z "$major" ]; then
    log_warning "Cannot determine bash version"
    return 0
  fi

  if [ "$major" -lt 3 ]; then
    log_error "Bash 3.2+ is required (detected: $BASH_VERSION)"
    exit 1
  fi

  log_success "Bash $BASH_VERSION"
}

# Check required dependencies
check_dependencies() {
  local missing=""

  if ! command -v git >/dev/null 2>&1; then
    missing="$missing git"
  fi

  if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
    missing="$missing curl-or-wget"
  fi

  if [ -n "$missing" ]; then
    log_error "Missing required dependencies:$missing"
    case "$OS" in
      macos)
        log_info "Install with Homebrew: brew install git curl"
        ;;
      linux)
        log_info "Install with apt:  sudo apt-get install -y git curl"
        log_info "Install with yum:  sudo yum install -y git curl"
        ;;
    esac
    exit 1
  fi

  log_success "Dependencies satisfied (git, curl)"

  if ! command -v docker >/dev/null 2>&1; then
    log_warning "Docker not found — required to run nself services"
    log_warning "Install Docker: https://docs.docker.com/get-docker/"
  else
    log_success "Docker found"
  fi
}

# Fetch the latest release tag from GitHub
get_latest_version() {
  local tag=""

  if command -v curl >/dev/null 2>&1; then
    tag=$(curl -sSL "$GITHUB_API/releases/latest" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
  elif command -v wget >/dev/null 2>&1; then
    tag=$(wget -qO- "$GITHUB_API/releases/latest" 2>/dev/null | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
  fi

  if [ -z "$tag" ]; then
    log_warning "Could not fetch latest version from GitHub — using main branch"
    echo "main"
  else
    echo "$tag"
  fi
}

# Download and install nself
install_nself() {
  local version="$1"

  log_info "Installing nself $version to $INSTALL_DIR"

  # Handle existing installation
  if [ -d "$INSTALL_DIR" ]; then
    if [ "$FORCE_REINSTALL" = "true" ]; then
      log_info "Removing existing installation..."
      rm -rf "$INSTALL_DIR"
    else
      # Check if it's already the same version
      local installed_version=""
      if [ -f "$INSTALL_DIR/src/VERSION" ]; then
        installed_version="v$(cat "$INSTALL_DIR/src/VERSION" 2>/dev/null | tr -d '[:space:]')"
      elif "$INSTALL_DIR/bin/nself" version --short >/dev/null 2>&1; then
        installed_version=$("$INSTALL_DIR/bin/nself" version --short 2>/dev/null)
      fi

      if [ -n "$installed_version" ] && [ "$installed_version" = "$version" ]; then
        log_success "nself $version is already installed"
        return 0
      fi

      log_info "Updating existing installation..."
      rm -rf "$INSTALL_DIR"
    fi
  fi

  mkdir -p "$INSTALL_DIR"

  # Clone the repository at the target version
  log_info "Downloading nself $version..."

  local clone_ok=false

  if [ "$version" != "main" ]; then
    if git clone --branch "$version" --depth 1 "https://github.com/$GITHUB_REPO.git" "$INSTALL_DIR" >/dev/null 2>&1; then
      clone_ok=true
    fi
  fi

  if [ "$clone_ok" = "false" ]; then
    log_info "Falling back to main branch..."
    if ! git clone --depth 1 "https://github.com/$GITHUB_REPO.git" "$INSTALL_DIR" >/dev/null 2>&1; then
      log_error "Download failed. Check your internet connection and try again."
      exit 1
    fi
  fi

  # Verify the binary exists
  if [ ! -f "$INSTALL_DIR/bin/nself" ]; then
    log_error "Installation integrity check failed: bin/nself not found"
    rm -rf "$INSTALL_DIR"
    exit 1
  fi

  chmod +x "$INSTALL_DIR/bin/nself"
  log_success "Downloaded to $INSTALL_DIR"
}

# Add nself to PATH in shell config
setup_path() {
  local shell_rc=""

  # Skip if already in PATH
  if echo "$PATH" | grep -q "$INSTALL_DIR/bin"; then
    log_success "PATH already configured"
    return 0
  fi

  # Detect the active shell's config file
  if [ -n "$ZSH_VERSION" ]; then
    shell_rc="$HOME/.zshrc"
  elif [ -n "$BASH_VERSION" ]; then
    if [ "$OS" = "macos" ]; then
      shell_rc="$HOME/.bash_profile"
    else
      shell_rc="$HOME/.bashrc"
    fi
  else
    shell_rc="$HOME/.profile"
  fi

  local path_line="export PATH=\"\$PATH:$INSTALL_DIR/bin\""

  if grep -q "$INSTALL_DIR/bin" "$shell_rc" 2>/dev/null; then
    log_success "PATH entry exists in $shell_rc"
  else
    printf "\n# nself\n%s\n" "$path_line" >> "$shell_rc"
    log_success "Added to PATH in $shell_rc"
  fi

  # Export for the current session
  export PATH="$PATH:$INSTALL_DIR/bin"
}

# Run a quick sanity check
verify_installation() {
  if "$INSTALL_DIR/bin/nself" version >/dev/null 2>&1; then
    local version
    version=$("$INSTALL_DIR/bin/nself" version --short 2>/dev/null || echo "installed")
    log_success "nself $version is working"
  else
    log_warning "Installed but could not verify — try: $INSTALL_DIR/bin/nself version"
  fi
}

print_success() {
  printf "\n${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
  printf "${GREEN}  nself installed successfully${RESET}\n"
  printf "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n\n"

  printf "${CYAN}Get started:${RESET}\n\n"
  printf "  ${YELLOW}mkdir my-app && cd my-app${RESET}\n"
  printf "  ${YELLOW}nself init${RESET}\n"
  printf "  ${YELLOW}nself build && nself start${RESET}\n\n"

  printf "${CYAN}Quick reference:${RESET}\n\n"
  printf "  ${BLUE}nself help${RESET}      Show all commands\n"
  printf "  ${BLUE}nself doctor${RESET}    Check system requirements\n"
  printf "  ${BLUE}nself version${RESET}   Show installed version\n\n"

  printf "${CYAN}Docs:${RESET} https://docs.nself.org\n"
  printf "${CYAN}GitHub:${RESET} https://github.com/nself-org/cli\n\n"
}

main() {
  printf "\n${BLUE}╔══════════════════════════════════════════════════════╗${RESET}\n"
  printf "${BLUE}║${RESET}   ${BOLD}nself${RESET} — Self-Hosted Backend Infrastructure        ${BLUE}║${RESET}\n"
  printf "${BLUE}╚══════════════════════════════════════════════════════╝${RESET}\n\n"

  log_step "Checking environment..."
  detect_platform
  check_bash_version
  check_dependencies

  log_step "Resolving version..."
  local version="$NSELF_VERSION"
  if [ -z "$version" ]; then
    version=$(get_latest_version)
  fi
  log_info "Installing: $version"

  log_step "Downloading nself..."
  install_nself "$version"

  log_step "Configuring PATH..."
  setup_path

  log_step "Verifying installation..."
  verify_installation

  print_success
}

main "$@"
