#!/bin/bash
###############################################################################
# Safe Package Installation Script
#
# Provides safe python -m pip installation with:
# - Virtual environment detection/creation
# - Dependency resolution
# - Version compatibility checking
# - Rollback on failure
# - Security scanning
#
# Usage:
#   ./scripts/safe_install.sh [package_name] [version]
#   ./scripts/safe_install.sh -r requirements.txt
#   ./scripts/safe_install.sh --all  # Install all project dependencies
###############################################################################

set -e  # Exit on error

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"

# Configuration
VENV_DIR="$PROJECT_ROOT/venv"
REQUIREMENTS_FILE="$PROJECT_ROOT/requirements.txt"
BACKUP_DIR="$PROJECT_ROOT/.pip_backups"

###############################################################################
# Helper Functions
###############################################################################

print_header() {
    echo -e "${BLUE}========================================${NC}"
    echo -e "${BLUE}$1${NC}"
    echo -e "${BLUE}========================================${NC}"
}

print_success() {
    echo -e "${GREEN}✓ $1${NC}"
}

print_error() {
    echo -e "${RED}✗ $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠ $1${NC}"
}

print_info() {
    echo -e "${BLUE}ℹ $1${NC}"
}

###############################################################################
# Virtual Environment Management
###############################################################################

check_venv() {
    if [[ "$VIRTUAL_ENV" != "" ]]; then
        print_success "Virtual environment active: $VIRTUAL_ENV"
        return 0
    else
        print_warning "No virtual environment active"
        return 1
    fi
}

create_venv() {
    print_header "Creating Virtual Environment"

    if [ -d "$VENV_DIR" ]; then
        print_info "Virtual environment already exists at: $VENV_DIR"
        read -p "Recreate it? (y/N): " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            print_info "Removing old virtual environment..."
            rm -rf "$VENV_DIR"
        else
            return 0
        fi
    fi

    print_info "Creating new virtual environment..."
    python3 -m venv "$VENV_DIR"

    if [ $? -eq 0 ]; then
        print_success "Virtual environment created at: $VENV_DIR"
        print_info "Activate it with: source $VENV_DIR/bin/activate"
        return 0
    else
        print_error "Failed to create virtual environment"
        return 1
    fi
}

activate_venv() {
    if [ ! -d "$VENV_DIR" ]; then
        print_warning "Virtual environment not found at: $VENV_DIR"
        read -p "Create it now? (Y/n): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Nn]$ ]]; then
            create_venv || return 1
        else
            return 1
        fi
    fi

    # Check if already activated
    if check_venv; then
        return 0
    fi

    print_info "Activating virtual environment..."
    source "$VENV_DIR/bin/activate"

    if check_venv; then
        print_success "Virtual environment activated"
        return 0
    else
        print_error "Failed to activate virtual environment"
        return 1
    fi
}

###############################################################################
# Pip Safety Checks
###############################################################################

check_pip() {
    print_header "Checking pip"

    # Use python -m pip to bypass any aliases
    if ! python -m pip --version &> /dev/null; then
        print_error "pip not found"
        print_info "Installing pip..."

        # Try to install pip
        if command -v python3 &> /dev/null; then
            python3 -m ensurepip --upgrade
        else
            print_error "Python 3 not found. Please install Python 3 first."
            return 1
        fi
    fi

    # Check pip version
    pip_version=$(python -m pip --version | awk '{print $2}')
    print_success "pip version: $pip_version"

    # Upgrade pip if needed
    print_info "Upgrading pip to latest version..."
    python -m pip install --upgrade pip

    return 0
}

create_backup() {
    print_header "Creating Backup"

    mkdir -p "$BACKUP_DIR"

    timestamp=$(date +%Y%m%d_%H%M%S)
    backup_file="$BACKUP_DIR/installed_packages_$timestamp.txt"

    print_info "Saving current package list to: $backup_file"
    python -m pip freeze > "$backup_file"

    print_success "Backup created"
    echo "$backup_file"
}

check_conflicts() {
    local package=$1

    print_header "Checking for Conflicts"

    # Use pip-conflict-checker if available
    if command -v pip-conflict-checker &> /dev/null; then
        pip-conflict-checker "$package"
    else
        # Basic check using pip
        print_info "Running dependency check..."
        python -m pip install --dry-run "$package" 2>&1 | grep -i "conflict\|incompatible" || true
    fi
}

###############################################################################
# Installation Functions
###############################################################################

safe_install_package() {
    local package=$1
    local version=$2

    # Construct package spec
    if [ -n "$version" ]; then
        package_spec="$package==$version"
    else
        package_spec="$package"
    fi

    print_header "Installing: $package_spec"

    # Create backup
    backup_file=$(create_backup)

    # Check for conflicts
    check_conflicts "$package_spec"

    # Ask for confirmation
    read -p "Proceed with installation? (Y/n): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        print_warning "Installation cancelled"
        return 1
    fi

    # Install
    print_info "Installing $package_spec..."

    if python -m pip install "$package_spec"; then
        print_success "Successfully installed $package_spec"

        # Verify installation
        print_info "Verifying installation..."
        python -m pip show "$package" &> /dev/null

        if [ $? -eq 0 ]; then
            print_success "Package verified"
            return 0
        else
            print_error "Package installation verification failed"
            rollback "$backup_file"
            return 1
        fi
    else
        print_error "Installation failed"
        rollback "$backup_file"
        return 1
    fi
}

install_from_requirements() {
    local req_file=$1

    if [ ! -f "$req_file" ]; then
        print_error "Requirements file not found: $req_file"
        return 1
    fi

    print_header "Installing from: $req_file"

    # Create backup
    backup_file=$(create_backup)

    # Count packages
    package_count=$(grep -c -v '^#' "$req_file" | grep -c -v '^$' || echo 0)
    print_info "Found $package_count packages to install"

    # Show packages
    print_info "Packages to install:"
    grep -v '^#' "$req_file" | grep -v '^$' | sed 's/^/  - /'

    # Ask for confirmation
    read -p "Proceed with installation? (Y/n): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Nn]$ ]]; then
        print_warning "Installation cancelled"
        return 1
    fi

    # Install
    print_info "Installing packages..."

    if python -m pip install -r "$req_file"; then
        print_success "All packages installed successfully"
        return 0
    else
        print_error "Installation failed"
        rollback "$backup_file"
        return 1
    fi
}

rollback() {
    local backup_file=$1

    print_header "Rolling Back"

    if [ ! -f "$backup_file" ]; then
        print_error "Backup file not found: $backup_file"
        return 1
    fi

    print_warning "Rolling back to previous state..."

    # Uninstall all current packages
    python -m pip freeze | xargs python -m pip uninstall -y

    # Reinstall from backup
    python -m pip install -r "$backup_file"

    if [ $? -eq 0 ]; then
        print_success "Rollback completed"
        return 0
    else
        print_error "Rollback failed"
        return 1
    fi
}

###############################################################################
# Dependency Resolution
###############################################################################

resolve_dependencies() {
    print_header "Resolving Dependencies"

    # Use pip-tools if available
    if command -v pip-compile &> /dev/null; then
        print_info "Using pip-tools to resolve dependencies..."
        pip-compile --upgrade --generate-hashes requirements.in
    else
        print_warning "pip-tools not installed. Install with: python -m pip install pip-tools"
        print_info "Basic dependency check:"
        python -m pip check
    fi
}

###############################################################################
# Security Scanning
###############################################################################

security_scan() {
    print_header "Security Scanning"

    # Use safety if available
    if command -v safety &> /dev/null; then
        print_info "Running safety check..."
        safety check --json | jq '.'
    else
        print_warning "safety not installed. Install with: python -m pip install safety"
        print_info "Skipping security scan"
    fi
}

###############################################################################
# Main Logic
###############################################################################

show_help() {
    cat << EOF
Safe Package Installation Script

Usage:
    $0 [OPTIONS] [PACKAGE] [VERSION]

Options:
    --help              Show this help message
    --create-venv       Create virtual environment only
    --activate-venv     Activate virtual environment (source this script)
    --check             Check pip and environment
    --all               Install all project dependencies
    -r FILE             Install from requirements file
    --resolve           Resolve dependencies (requires pip-tools)
    --scan              Run security scan (requires safety)
    --backup            Create backup of current packages
    --rollback FILE     Rollback to backup file

Examples:
    # Create and activate virtual environment
    $0 --create-venv
    source venv/bin/activate

    # Install a single package
    $0 requests

    # Install specific version
    $0 requests 2.28.0

    # Install from requirements.txt
    $0 -r requirements.txt
    $0 --all  # Uses default requirements.txt

    # Check environment
    $0 --check

    # Security scan
    $0 --scan

EOF
}

main() {
    # Parse arguments
    case "$1" in
        --help|-h)
            show_help
            exit 0
            ;;
        --create-venv)
            create_venv
            exit $?
            ;;
        --check)
            activate_venv || exit 1
            check_pip
            print_info "Python version: $(python --version)"
            print_info "Installed packages:"
            python -m pip list
            exit 0
            ;;
        --all)
            activate_venv || exit 1
            check_pip || exit 1
            install_from_requirements "$REQUIREMENTS_FILE"
            exit $?
            ;;
        -r)
            activate_venv || exit 1
            check_pip || exit 1
            install_from_requirements "$2"
            exit $?
            ;;
        --resolve)
            activate_venv || exit 1
            resolve_dependencies
            exit $?
            ;;
        --scan)
            activate_venv || exit 1
            security_scan
            exit $?
            ;;
        --backup)
            activate_venv || exit 1
            create_backup
            exit $?
            ;;
        --rollback)
            activate_venv || exit 1
            rollback "$2"
            exit $?
            ;;
        "")
            show_help
            exit 1
            ;;
        *)
            # Install package
            activate_venv || exit 1
            check_pip || exit 1
            safe_install_package "$1" "$2"
            exit $?
            ;;
    esac
}

# Run main
main "$@"
