#!/bin/bash

# =============================================================================
# UBUNTU COMPUTER RENAME SCRIPT
# PURPOSE: Rename Ubuntu computers to AR<Serial> or RP<Serial> format
# LAST UPDATED: June 29, 2025
# KEY ENHANCEMENT: Ubuntu adaptation of Windows PowerShell rename script
# SERVICES: Local system configuration (hostname, hosts file)
# =============================================================================

set -e  # Exit on any 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

# Logging functions
log_success() {
    echo -e "${GREEN}✔ $1${NC}"
}

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

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

log_error() {
    echo -e "${RED}❌ $1${NC}"
}

# Check if running as root
if [[ $EUID -eq 0 ]]; then
   log_error "This script should not be run as root. Run as your regular user with sudo privileges."
   exit 1
fi

# ----------------------
# Set System Information (equivalent to Windows RegisteredOwner)
# ----------------------

log_info "Setting system information..."

# Create or update /etc/machine-info for system identification
# This is the systemd equivalent of Windows RegisteredOwner/Organization
sudo tee /etc/machine-info > /dev/null << EOF
PRETTY_HOSTNAME="$(hostname)"
EOF

log_success "System information has been updated in /etc/machine-info"

# ----------------------
# Get Serial Number
# ----------------------

log_info "Retrieving system serial number..."

# Try multiple methods to get serial number (different hardware may store it differently)
SERIAL=""

# Method 1: dmidecode (most reliable)
if command -v dmidecode >/dev/null 2>&1; then
    SERIAL=$(sudo dmidecode -s system-serial-number 2>/dev/null | head -n1 | tr -d '[:space:]')
fi

# Method 2: /sys/class/dmi/id/product_serial (fallback)
if [[ -z "$SERIAL" ]] && [[ -r /sys/class/dmi/id/product_serial ]]; then
    SERIAL=$(cat /sys/class/dmi/id/product_serial 2>/dev/null | tr -d '[:space:]')
fi

# Method 3: /proc/cpuinfo for some systems (last resort)
if [[ -z "$SERIAL" ]] && [[ -r /proc/cpuinfo ]]; then
    SERIAL=$(grep -i "serial" /proc/cpuinfo 2>/dev/null | head -n1 | cut -d':' -f2 | tr -d '[:space:]')
fi

# If still no serial, show what we found and exit
if [[ -z "$SERIAL" ]]; then
    log_error "Could not retrieve system serial number."
    log_info "Available system information:"
    echo "  Hostname: $(hostname)"
    echo "  Kernel: $(uname -r)"
    echo "  Hardware: $(uname -m)"
    if command -v dmidecode >/dev/null 2>&1; then
        echo "  Manufacturer: $(sudo dmidecode -s system-manufacturer 2>/dev/null || echo 'Unknown')"
        echo "  Product: $(sudo dmidecode -s system-product-name 2>/dev/null || echo 'Unknown')"
    fi
    exit 1
fi

log_info "Found serial number: $SERIAL"

# ----------------------
# Define Special Serial Numbers and Generate New Name
# ----------------------

# Define special serial numbers that should use "RP" prefix (matching PowerShell script)
RP_SERIALS=("2UA7131QT5" "97L7704" "R90NHCCP" "e703d878e5175cac")

# Normalize serial number (remove spaces, convert to uppercase)
NORMALIZED_SERIAL=$(echo "$SERIAL" | tr -d '[:space:]' | tr '[:lower:]' '[:upper:]')

log_info "Normalized serial: $NORMALIZED_SERIAL"

# Check if serial is "Default string" (case-insensitive)
if [[ "$NORMALIZED_SERIAL" == "DEFAULTSTRING" ]]; then
    log_warning "Default serial number detected. Generating random identifier..."
    # Generate 13-character random uppercase alphanumeric string
    CLEAN_SERIAL=$(cat /dev/urandom | tr -dc 'A-Z0-9' | fold -w 13 | head -n 1)
    PREFIX="AR"
    log_info "Generated random serial: $CLEAN_SERIAL"
else
    # Remove non-alphanumeric characters and convert to uppercase
    CLEAN_SERIAL=$(echo "$NORMALIZED_SERIAL" | sed 's/[^A-Za-z0-9]//g' | tr '[:lower:]' '[:upper:]')
    
    # Check if this serial should use RP prefix
    PREFIX="AR"  # Default prefix
    for rp_serial in "${RP_SERIALS[@]}"; do
        if [[ "$SERIAL" == "$rp_serial" ]]; then
            PREFIX="RP"
            log_info "Special serial detected - using RP prefix"
            break
        fi
    done
fi

# Truncate to 13 characters max and create new name
CLEAN_SERIAL_TRUNCATED="${CLEAN_SERIAL:0:13}"
NEW_NAME="${PREFIX}${CLEAN_SERIAL_TRUNCATED}"
CURRENT_NAME=$(hostname)

log_info "Current hostname: $CURRENT_NAME"
log_info "Proposed new hostname: $NEW_NAME"

# ----------------------
# Validate New Hostname
# ----------------------

# Check if hostname follows Linux naming conventions
if [[ ! "$NEW_NAME" =~ ^[a-zA-Z][a-zA-Z0-9-]*$ ]]; then
    log_error "Generated hostname '$NEW_NAME' doesn't follow Linux naming conventions"
    log_error "Hostnames must start with a letter and contain only letters, numbers, and hyphens"
    exit 1
fi

if [[ ${#NEW_NAME} -gt 63 ]]; then
    log_error "Generated hostname '$NEW_NAME' is too long (max 63 characters)"
    exit 1
fi

# Keep hostname in uppercase to match Windows naming convention
# Note: While Linux typically uses lowercase, uppercase hostnames are valid

# ----------------------
# Apply Hostname Change
# ----------------------

if [[ "${CURRENT_NAME^^}" == "${NEW_NAME}" ]]; then
    log_success "Computer is already named $NEW_NAME. No action needed."
else
    log_info "Changing hostname from $CURRENT_NAME to $NEW_NAME..."
    
    # Use hostnamectl (modern systemd method)
    if command -v hostnamectl >/dev/null 2>&1; then
        sudo hostnamectl set-hostname "$NEW_NAME"
        log_success "Hostname changed using hostnamectl"
    else
        # Fallback to manual method
        log_warning "hostnamectl not available, using manual method..."
        
        # Update /etc/hostname
        echo "$NEW_NAME" | sudo tee /etc/hostname > /dev/null
        
        # Update /etc/hosts
        sudo sed -i "s/127\.0\.1\.1.*/127.0.1.1\t$NEW_NAME/" /etc/hosts
        
        # If the line doesn't exist, add it
        if ! grep -q "127.0.1.1" /etc/hosts; then
            echo "127.0.1.1	$NEW_NAME" | sudo tee -a /etc/hosts > /dev/null
        fi
        
        log_success "Hostname files updated manually"
    fi
    
    # Verify the change
    NEW_HOSTNAME=$(hostname)
    if [[ "$NEW_HOSTNAME" == "$NEW_NAME" ]]; then
        log_success "Hostname successfully changed to $NEW_NAME"
    else
        log_warning "Hostname change requires a reboot to take full effect"
        log_info "Current hostname: $NEW_HOSTNAME"
        log_info "Target hostname: $NEW_NAME"
    fi
    
    # ----------------------
    # Reboot Notification
    # ----------------------
    
    echo
    log_warning "The system will reboot to complete the hostname change."
    log_info "All unsaved work will be lost."
    echo
    
    # Check if we're running interactively or piped
    if [[ -t 0 ]]; then
        # Interactive mode - wait for keypress
        read -p "Press ENTER to continue and reboot the system..." -r
    else
        # Piped mode - give user time to see the message and cancel if needed
        log_info "Rebooting in 10 seconds... Press Ctrl+C to cancel."
        for i in {10..1}; do
            echo -n "$i... "
            sleep 1
        done
        echo
    fi
    
    log_info "Rebooting system..."
    sudo reboot
fi

# ----------------------
# Summary
# ----------------------

echo
log_success "Script completed successfully!"
echo
echo "=== SUMMARY ==="
echo "Serial Number: $SERIAL"
echo "Prefix Used: $PREFIX"
echo "New Hostname: $NEW_NAME"
echo "Organization: $ORGANIZATION"
echo "Owner: $OWNER"
echo
log_info "System information saved to /etc/machine-info"
log_info "Hostname configuration updated"

# Display verification commands
echo
echo "=== VERIFICATION COMMANDS ==="
echo "Check current hostname: hostname"
echo "Check detailed hostname info: hostnamectl"
echo "Check hosts file: cat /etc/hosts"
echo "Check machine info: cat /etc/machine-info"