#!/usr/bin/env bash
# preflight.sh - Pre-flight checks for nself commands

# Check if running in nself source directory
check_not_in_source() {
  if [[ -f "bin/nself" ]] && [[ -d "src/cli" ]] && [[ -d "src/lib" ]] && [[ -f "install.sh" ]]; then
    log_error "Cannot run nself commands in the nself source repository!"
    echo ""
    log_info "Please run from a separate project directory:"
    echo "  mkdir ~/myproject && cd ~/myproject"
    echo "  nself init"
    return 1
  fi
  return 0
}

# Check for environment configuration file
check_env_file() {
  if [[ ! -f ".env" ]] && [[ ! -f ".env.local" ]] && [[ ! -f ".env.dev" ]]; then
    log_error "No environment file found (.env, .env.local, or .env.dev)"
    echo ""
    log_info "Please run: nself init"
    echo ""
    echo "This will create the required configuration files."
    return 1
  fi
  return 0
}

# Check for docker-compose.yml
check_docker_compose() {
  if [[ ! -f "docker-compose.yml" ]]; then
    log_error "No docker-compose.yml found - project not built yet"
    echo ""
    log_info "Please run: nself build"
    echo ""
    echo "This will generate all required project files."
    return 1
  fi
  
  # Check if docker-compose.yml was manually created (missing nself markers)
  if ! grep -q "# Generated by nself" docker-compose.yml 2>/dev/null; then
    if [[ ! -f ".env" ]]; then
      log_warning "docker-compose.yml exists but appears to be manually created"
      log_info "Missing .env file - this will cause 'unbound variable' errors"
      echo ""
      log_info "Recommended: Remove manual files and use nself commands:"
      echo "  rm docker-compose.yml"
      echo "  nself init"
      echo "  nself build"
      echo "  nself start"
      return 1
    fi
  fi
  
  return 0
}

# Check Docker is installed and running
check_docker() {
  # Check if docker command exists
  if ! command -v docker &>/dev/null; then
    log_error "Docker is not installed"
    echo ""
    log_info "Please install Docker from:"
    echo "  https://www.docker.com/products/docker-desktop (macOS/Windows)"
    echo "  https://docs.docker.com/engine/install/ (Linux)"
    return 1
  fi

  # More robust Docker daemon check (works better in LXC/container environments)
  # Try multiple methods to detect if Docker is available
  local docker_available=false
  
  # Method 1: Try docker version (more reliable than docker info in containers)
  if docker version --format '{{.Server.Version}}' &>/dev/null; then
    docker_available=true
  # Method 2: Check if we can list containers (works in some restricted environments)
  elif docker ps --format '{{.ID}}' &>/dev/null; then
    docker_available=true
  # Method 3: Original docker info check as fallback
  elif docker info &>/dev/null; then
    docker_available=true
  fi
  
  if [[ "$docker_available" == "false" ]]; then
    # Provide more specific error messages based on the environment
    if [[ -S /var/run/docker.sock ]]; then
      if [[ ! -r /var/run/docker.sock ]] || [[ ! -w /var/run/docker.sock ]]; then
        log_error "Docker socket exists but is not accessible"
        echo ""
        log_info "You may need to add your user to the docker group:"
        echo "  sudo usermod -aG docker \$USER"
        echo "  Then log out and back in"
      else
        log_error "Docker daemon is not responding"
        echo ""
        log_info "Please ensure Docker service is running:"
        echo "  sudo systemctl start docker  # For systemd"
        echo "  sudo service docker start    # For init.d"
      fi
    else
      log_error "Docker daemon is not running"
      echo ""
      log_info "Please start Docker service:"
      echo "  sudo systemctl start docker  # For systemd (most Linux distros)"
      echo "  sudo service docker start    # For init.d"
      echo "  Or start Docker Desktop if on macOS/Windows"
    fi
    return 1
  fi

  return 0
}

# Check for required commands (cross-platform)
check_required_commands() {
  local missing_commands=()

  # List of required commands
  local required_commands=(
    "docker"
    "sed"
    "awk"
    "grep"
  )

  for cmd in "${required_commands[@]}"; do
    if ! command -v "$cmd" &>/dev/null; then
      missing_commands+=("$cmd")
    fi
  done

  if [[ ${#missing_commands[@]} -gt 0 ]]; then
    log_error "Missing required commands: ${missing_commands[*]}"
    return 1
  fi

  return 0
}

# Check platform-specific requirements
check_platform() {
  local platform="$(uname -s)"

  case "$platform" in
  Darwin*)
    # macOS specific checks
    # Bash version check (macOS ships with old bash)
    if [[ "${BASH_VERSION%%.*}" -lt 3 ]]; then
      log_warning "Bash version is old (${BASH_VERSION})"
      log_info "Consider upgrading bash: brew install bash"
    fi
    ;;
  Linux*)
    # Linux specific checks
    # Check if running with proper permissions
    if [[ "$EUID" -eq 0 ]] && [[ -z "${ALLOW_ROOT:-}" ]]; then
      log_warning "Running as root is not recommended"
      log_info "Set ALLOW_ROOT=true to bypass this warning"
    fi
    
    # Check for WSL2
    if grep -qi microsoft /proc/version 2>/dev/null; then
      log_info "WSL2 detected - special configuration may be needed"
      
      # Check if using localhost domain
      if [[ "${BASE_DOMAIN:-localhost}" == "localhost" ]]; then
        log_warning "WSL2 doesn't resolve *.localhost automatically"
        log_info "Recommended: Set BASE_DOMAIN=local.nself.org in .env"
        log_info "Alternative: Add entries to /etc/hosts for *.localhost domains"
      fi
    fi
    ;;
  MINGW* | MSYS* | CYGWIN*)
    # Windows specific checks
    log_warning "Windows detected - some features may not work correctly"
    log_info "Consider using WSL2 for better compatibility"
    ;;
  *)
    log_warning "Unknown platform: $platform"
    ;;
  esac

  return 0
}

# Run all pre-flight checks for init command
preflight_init() {
  check_not_in_source || return 1
  check_required_commands || return 1
  check_platform || return 1
  return 0
}

# Run all pre-flight checks for build command
preflight_build() {
  check_not_in_source || return 1
  check_env_file || return 1
  check_required_commands || return 1
  check_platform || return 1
  return 0
}

# Run all pre-flight checks for up command
preflight_up() {
  check_not_in_source || return 1
  check_env_file || return 1
  check_docker_compose || return 1
  check_docker || return 1
  check_required_commands || return 1
  check_platform || return 1
  return 0
}

# Export all functions
export -f check_not_in_source
export -f check_env_file
export -f check_docker_compose
export -f check_docker
export -f check_required_commands
export -f check_platform
export -f preflight_init
export -f preflight_build
export -f preflight_up
