#!/bin/bash

# =============================================================================
# Drive Health Checker (v8)
#
# A "pretty" script to list drives, let the user select one,
# and run a SMART health check.
#
# v8 Update:
#   - Replaced string joining with printf for a perfectly
#     aligned, multi-column menu (ID, LABEL, DEVICE, SIZE, MODEL).
#   - Reworked list-building logic to use parallel arrays.
# =============================================================================

# --- Define Colors ---
if command -v tput &> /dev/null; then
    GREEN=$(tput setaf 2)
    RED=$(tput setaf 1)
    YELLOW=$(tput setaf 3)
    BLUE=$(tput setaf 4)
    BOLD=$(tput bold)
    NC=$(tput sgr0) # No Color
else
    GREEN='\033[0;32m'
    RED='\033[0;31m'
    YELLOW='\033[1;33m'
    BLUE='\033[0;34m'
    BOLD='\033[1m'
    NC='\033[0m'
fi

# --- Helper Function for Headers ---
print_header() {
    echo -e "\n${BLUE}${BOLD}--- $1 ---${NC}"
}

# --- 1. System Checks ---

# Check for root privileges
if [ "$EUID" -ne 0 ]; then
  echo -e "${RED}${BOLD}Error:${NC} This script must be run with sudo for drive access."
  echo -e "Please run as: ${GREEN}sudo $0${NC}"
  exit 1
fi

# Check for dependencies
if ! command -v smartctl &> /dev/null || ! command -v lsblk &> /dev/null; then
    echo -e "${YELLOW}Warning:${NC} 'smartctl' or 'lsblk' command not found."
    echo -e "This script requires ${BOLD}smartmontools${NC} and ${BOLD}util-linux${NC}."
    echo -e "As a Manjaro user, you can install them by running:"
    echo -e "${GREEN}sudo pacman -S smartmontools util-linux${NC}"
    exit 1
fi

# --- 2. Get Drive List (once) ---

# --- UPDATED SECTION ---
print_header "Building Drive List (this may take a second)..."

# Declare parallel arrays to hold drive components
declare -a drive_names=()
declare -a drive_labels=()
declare -a drive_sizes=()
declare -a drive_models=()

# Get a list of just the disk names (e.g., sda, sdb)
disks=$(lsblk -d -n -o NAME -e 7,11)

if [ -z "$disks" ]; then
    echo -e "${RED}No physical drives found.${NC}"
    exit 1
fi

# Loop through each disk to build the component lists
for disk in $disks; do
    # Add device name
    drive_names+=("$disk")
    
    # Get Size and Model
    # We use 'read' to handle models with spaces
    read -r size model < <(lsblk -d -n -o SIZE,MODEL "/dev/$disk")
    drive_sizes+=("$size")
    drive_models+=("$model")

    # Get the first available filesystem LABEL
    label=$(lsblk -n -o LABEL "/dev/$disk" | grep -v "^$" | head -n 1)
    
    # Format label for display (or use a placeholder)
    if [ -n "$label" ]; then
        drive_labels+=("($label)")
    else
        drive_labels+=("( )") # Placeholder for alignment
    fi
done
# --- END UPDATED SECTION ---


# --- 3. Main Loop ---

while true; do
    clear
    print_header "Available Physical Drives"
    
    # --- UPDATED MENU PRINTING ---
    # Print the header
    printf "  ${BOLD}%-4s %-16s %-8s %-7s %s${NC}\n" "ID)" "LABEL" "DEVICE" "SIZE" "MODEL"
    printf "  ${BOLD}%-4s %-16s %-8s %-7s %s${NC}\n" "---" "---------------" "------" "------" "-----------------"

    # Loop and print each drive using printf for alignment
    for ((i=0; i<${#drive_names[@]}; i++)); do
        id="$((i+1))"
        # Print the formatted line
        printf "  ${YELLOW}%-4s${NC} ${YELLOW}%-16s${NC} %-8s %-7s %s\n" \
            "$id)" \
            "${drive_labels[$i]}" \
            "${drive_names[$i]}" \
            "${drive_sizes[$i]}" \
            "${drive_models[$i]}"
    done
    # --- END UPDATED MENU ---

    echo -e "  ${YELLOW}q)${NC} Quit"
    echo "" # Add a newline

    # Prompt user
    read -p "${YELLOW}${BOLD}Select a drive (number) or 'q' to quit: ${NC}" selection

    # Process input
    case "$selection" in
        q|Q|quit|Quit)
            echo -e "${GREEN}Exiting.${NC}"
            break
            ;;
        *)
            # Check if it's a valid number
            if ! [[ "$selection" =~ ^[0-9]+$ ]] || [ "$selection" -lt 1 ] || [ "$selection" -gt ${#drive_names[@]} ]; then
                echo -e "\n${RED}Invalid selection.${NC} Press Enter to try again."
                read -p ""
                continue # Restart the loop
            fi

            # --- 4. It's a valid number, get the drive ---
            
            # --- UPDATED PARSING ---
            # Convert selection to zero-based index
            ((idx = selection - 1))
            
            # Get components from our parallel arrays
            device_name="${drive_names[$idx]}"
            model_name="${drive_models[$idx]}"
            label_name="${drive_labels[$idx]}"
            device_path="/dev/$device_name"

            # Build a cleaner header for the report
            print_header "Health Report for $device_path (${BOLD}${label_name} ${model_name}${NC})"
            # --- END UPDATED PARSING ---
            
            if ! smartctl -i "$device_path" | grep -q "SMART support is: Available"; then
                echo -e "${YELLOW}Warning:${NC} This drive (${BOLD}$device_path${NC}) does not report SMART support."
                echo "Cannot perform health check."
            else
                # --- 5. Run Health Check ---
                smartctl -s on "$device_path" &> /dev/null
                echo -e "Running SMART health check..."

                attributes=$(smartctl -A "$device_path")
                health_result=$(smartctl -H "$device_path" | grep 'overall-health' | awk '{print $6}')
                temp=$(echo "$attributes" | grep -i 'Temperature_Celsius' | awk '{print $10}')
                power_on_hours=$(echo "$attributes" | grep -i 'Power_On_Hours' | awk '{print $10}')
                serial_number=$(smartctl -i "$device_path" | grep 'Serial Number:' | awk '{print $3}')
                reallocated_sectors=$(echo "$attributes" | grep -i 'Reallocated_Sector_Ct' | awk '{print $10}')
                pending_sectors=$(echo "$attributes" | grep -i 'Current_Pending_Sector_Ct' | awk '{print $10}')
                uncorrectable_sectors=$(echo "$attributes" | grep -i 'Offline_Uncorrectable' | awk '{print $10}')
                
                [ -z "$reallocated_sectors" ] && reallocated_sectors=0
                [ -z "$pending_sectors" ] && pending_sectors=0
                [ -z "$uncorrectable_sectors" ] && uncorrectable_sectors=0
                
                # --- 6. Display Verdict ---
                echo -e "\n${BOLD}Quick Summary:${NC}"
                echo -e "  ${BLUE}Serial Number:${NC}      $serial_number"
                echo -e "  ${BLUE}Power On Hours:${NC}     $power_on_hours"
                echo -e "  ${BLUE}Temperature:${NC}        ${temp}°C"
                echo -e "\n  ${BOLD}Bad Sector Analysis:${NC}"
                echo -e "  ${BLUE}Reallocated Sectors:${NC}  ${reallocated_sectors}"
                echo -e "  ${BLUE}Pending Sectors:${NC}      ${pending_sectors}"
                echo -e "  ${BLUE}Uncorrectable Sectors:${NC}  ${uncorrectable_sectors}"

                echo -e "\n${BOLD}--- VERDICT ---${NC}"
                
                if [ "$health_result" = "PASSED" ] && [ "$pending_sectors" -eq 0 ] && [ "$uncorrectable_sectors" -eq 0 ]; then
                    echo -e "${GREEN}✅ PASSED${NC}"
                    echo -e "The drive's overall SMART health assessment is ${BOLD}PASSED${NC}."
                    if [ "$reallocated_sectors" -ne 0 ]; then
                        echo -e "${YELLOW}Note:${NC} The drive has reallocated ${BOLD}$reallocated_sectors${NC} sectors. This is not an"
                        echo -e "immediate failure, but you should monitor this value."
                    fi
                elif [ "$health_result" = "PASSED" ]; then
                    echo -e "${YELLOW}⚠️ WARNING${NC}"
                    echo -e "The drive's overall SMART health is ${BOLD}PASSED${NC}, but it reports critical issues!"
                    if [ "$pending_sectors" -ne 0 ]; then
                        echo -e "${RED}Critical:${NC} ${BOLD}$pending_sectors${NC} pending sectors. The drive is struggling to read data."
                    fi
                    if [ "$uncorrectable_sectors" -ne 0 ]; then
                        echo -e "${RED}Critical:${NC} ${BOLD}$uncorrectable_sectors${NC} uncorrectable sectors. ${BOLD}Data has been lost.${NC}"
                    fi
                    echo -e "${YELLOW}ACTION REQUIRED: Back up any critical data immediately.${NC}"
                else
                    echo -e "${RED}❌ FAILED${NC}"
                    echo -e "The drive's overall SMART health assessment is ${BOLD}${health_result}${NC}."
                    echo -e "${YELLOW}ACTION REQUIRED: Back up any critical data immediately"
                    echo -e "and consider replacing this drive.${NC}"
                fi

                # Ask to show full report
                echo "" # Newline
                read -p "${YELLOW}Show full SMART report for $device_path? (y/N): ${NC}" show_full
                if [[ "$show_full" =~ ^[Yy]$ ]]; then
                    print_header "Full SMART Report for $device_path"
                    echo "Look for 'Percentage_Used' or 'Media_Wearout_Indicator' on SSDs."
                    smartctl -a "$device_path" | less
                fi
            fi
            
            # --- 7. Pause before looping ---
            echo -e "\n${YELLOW}Press Enter to return to the drive list...${NC}"
            read -p ""
            ;;
    esac
done

exit 0