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

set -e

# Colors (compatible with all terminals)
if [ -t 1 ]; then
  RED='\033[0;31m'
  GREEN='\033[0;32m'
  YELLOW='\033[1;33m'
  BLUE='\033[0;34m'
  CYAN='\033[0;36m'
  RESET='\033[0m'
else
  RED=''
  GREEN=''
  YELLOW=''
  BLUE=''
  CYAN=''
  RESET=''
fi

# Version to install (can be overridden with NSELF_VERSION env var)
NSELF_VERSION="${NSELF_VERSION:-latest}"
GITHUB_REPO="acamarata/nself"
INSTALL_DIR="${NSELF_INSTALL_DIR:-$HOME/.nself}"

# Utility functions
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"
}

# 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 is not directly 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 may not be fully tested"
      ;;
  esac

  log_info "Detected platform: $OS ($ARCH)"
}

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

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

  if [ "$bash_version" -lt 3 ]; then
    log_error "Bash 3.0 or later is required (you have $BASH_VERSION)"
    log_error "Please upgrade bash and try again"
    exit 1
  fi

  if [ "$bash_version" -eq 3 ]; then
    local minor_version="${BASH_VERSION#*.}"
    minor_version="${minor_version%%.*}"
    if [ "$minor_version" -lt 2 ]; then
      log_warning "Bash 3.2+ is recommended (you have $BASH_VERSION)"
    fi
  fi

  log_success "Bash version: $BASH_VERSION"
}

# Check dependencies
check_dependencies() {
  local missing_deps=()

  # Required dependencies
  if ! command -v git >/dev/null 2>&1; then
    missing_deps+=("git")
  fi

  if ! command -v docker >/dev/null 2>&1; then
    log_warning "Docker not found - it will be required to run nself"
  fi

  if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
    missing_deps+=("curl or wget")
  fi

  if [ ${#missing_deps[@]} -gt 0 ]; then
    log_error "Missing required dependencies: ${missing_deps[*]}"
    log_info "Please install them and try again"

    case "$OS" in
      macos)
        log_info "Install with: brew install ${missing_deps[*]}"
        ;;
      linux)
        log_info "Install with: sudo apt-get install ${missing_deps[*]}"
        log_info "Or: sudo yum install ${missing_deps[*]}"
        ;;
    esac

    exit 1
  fi

  log_success "All required dependencies found"
}

# Get latest version from GitHub
get_latest_version() {
  local version

  if command -v curl >/dev/null 2>&1; then
    version=$(curl -sSL "https://api.github.com/repos/$GITHUB_REPO/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
  elif command -v wget >/dev/null 2>&1; then
    version=$(wget -qO- "https://api.github.com/repos/$GITHUB_REPO/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
  else
    log_error "Neither curl nor wget found"
    exit 1
  fi

  if [ -z "$version" ]; then
    log_warning "Could not fetch latest version, using fallback"
    echo "v0.4.0"
  else
    echo "$version"
  fi
}

# Download and install nself
install_nself() {
  log_info "Installing nself to $INSTALL_DIR"

  # Resolve version
  if [ "$NSELF_VERSION" = "latest" ]; then
    NSELF_VERSION=$(get_latest_version)
    log_info "Latest version: $NSELF_VERSION"
  fi

  # Remove existing installation
  if [ -d "$INSTALL_DIR" ]; then
    log_info "Removing existing installation..."
    rm -rf "$INSTALL_DIR"
  fi

  # Create install directory
  mkdir -p "$INSTALL_DIR"

  # Clone repository
  log_info "Downloading nself $NSELF_VERSION..."
  if ! git clone --branch "$NSELF_VERSION" --depth 1 "https://github.com/$GITHUB_REPO.git" "$INSTALL_DIR" >/dev/null 2>&1; then
    log_error "Failed to download nself"
    log_info "Trying without version tag..."

    if ! git clone --depth 1 "https://github.com/$GITHUB_REPO.git" "$INSTALL_DIR" >/dev/null 2>&1; then
      log_error "Failed to clone repository"
      exit 1
    fi
  fi

  # Verify installation
  if [ ! -f "$INSTALL_DIR/bin/nself" ]; then
    log_error "Installation failed: nself binary not found"
    exit 1
  fi

  # Make executable
  chmod +x "$INSTALL_DIR/bin/nself"

  log_success "nself installed to $INSTALL_DIR"
}

# Add to PATH
setup_path() {
  local shell_rc=""
  local shell_name=""

  # Detect shell
  if [ -n "$BASH_VERSION" ]; then
    shell_name="bash"
    if [ "$OS" = "macos" ]; then
      shell_rc="$HOME/.bash_profile"
    else
      shell_rc="$HOME/.bashrc"
    fi
  elif [ -n "$ZSH_VERSION" ]; then
    shell_name="zsh"
    shell_rc="$HOME/.zshrc"
  else
    shell_name="sh"
    shell_rc="$HOME/.profile"
  fi

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

  # Add to shell RC file
  local path_line="export PATH=\"\$PATH:$INSTALL_DIR/bin\""

  if [ -f "$shell_rc" ]; then
    if grep -q "$INSTALL_DIR/bin" "$shell_rc" 2>/dev/null; then
      log_success "PATH already configured in $shell_rc"
    else
      printf "\n# nself\n%s\n" "$path_line" >> "$shell_rc"
      log_success "Added nself to PATH in $shell_rc"
    fi
  else
    printf "# nself\n%s\n" "$path_line" > "$shell_rc"
    log_success "Created $shell_rc with nself PATH"
  fi

  log_info "Reload your shell or run: source $shell_rc"
}

# Verify installation
verify_installation() {
  log_info "Verifying installation..."

  # Test nself command
  if "$INSTALL_DIR/bin/nself" version >/dev/null 2>&1; then
    log_success "nself is working correctly"

    # Show version
    local version
    version=$("$INSTALL_DIR/bin/nself" version --short 2>/dev/null || echo "unknown")
    log_info "Installed version: $version"
  else
    log_warning "nself command test failed, but files are installed"
  fi
}

# Print next steps
print_next_steps() {
  printf "\n${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n"
  printf "${GREEN}✓ nself installed successfully!${RESET}\n"
  printf "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n\n"

  printf "${CYAN}Next steps:${RESET}\n\n"

  # Check if PATH is already configured
  if ! echo "$PATH" | grep -q "$INSTALL_DIR/bin"; then
    printf "1. Add nself to your PATH:\n"
    printf "   ${YELLOW}export PATH=\"\$PATH:$INSTALL_DIR/bin\"${RESET}\n"
    printf "   Or reload your shell: ${YELLOW}source ~/.bashrc${RESET}\n\n"
  fi

  printf "2. Initialize a new project:\n"
  printf "   ${YELLOW}mkdir my-app && cd my-app${RESET}\n"
  printf "   ${YELLOW}nself init${RESET}\n\n"

  printf "3. Build and start:\n"
  printf "   ${YELLOW}nself build${RESET}\n"
  printf "   ${YELLOW}nself start${RESET}\n\n"

  printf "${CYAN}Quick commands:${RESET}\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 version info\n\n"

  printf "${CYAN}Documentation:${RESET}\n"
  printf "  https://github.com/acamarata/nself\n\n"
}

# Main installation flow
main() {
  printf "\n${BLUE}╔══════════════════════════════════════════════════════════╗${RESET}\n"
  printf "${BLUE}║${RESET} ${GREEN}nself Installer${RESET}                                         ${BLUE}║${RESET}\n"
  printf "${BLUE}║${RESET} Self-Hosted Infrastructure Manager                     ${BLUE}║${RESET}\n"
  printf "${BLUE}╚══════════════════════════════════════════════════════════╝${RESET}\n\n"

  # Run checks
  detect_platform
  check_bash_version
  check_dependencies

  printf "\n"

  # Install
  install_nself
  setup_path
  verify_installation

  # Done
  print_next_steps
}

# Run main function
main "$@"
