#!/bin/bash
# ============================================================
# Linux Lockdown — DARK DATA SCANNER
# Finds invisible junk, forgotten debris, and system bloat
# Usage: curl -sL https://linuxlockdown.com/darkdata.sh | sudo bash
# ============================================================

VERSION="1.0.0"
HOSTNAME=$(hostname)
DATE=$(date +"%Y-%m-%d %H:%M:%S")
REPORT_FILE="/tmp/darkdata-report-$(date +%Y%m%d-%H%M%S).txt"

# Colors
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# Require root for full scan
if [ "$EUID" -ne 0 ]; then
    echo -e "${YELLOW}⚠  Running without root — some scans will be limited.${NC}"
    echo "   For full scan: sudo bash darkdata.sh"
    echo ""
fi

# Human-readable bytes
hsize() {
    local bytes=$1
    if [ "$bytes" -lt 1024 ]; then
        echo "${bytes}B"
    elif [ "$bytes" -lt 1048576 ]; then
        echo "$((bytes / 1024))KB"
    elif [ "$bytes" -lt 1073741824 ]; then
        echo "$((bytes / 1048576))MB"
    else
        echo "$(awk "BEGIN{printf \"%.1f\", $bytes / 1073741824}")GB"
    fi
}

# Get directory size in bytes
dsize() {
    local dir=$1
    if [ -d "$dir" ]; then
        du -sb "$dir" 2>/dev/null | awk '{print $1}'
    else
        echo 0
    fi
}

# Banner
clear
cat << 'BANNER'
╔══════════════════════════════════════════════════════════════╗
║                                                              ║
║         LINUX LOCKDOWN — DARK DATA SCANNER v1.0              ║
║                                                              ║
║   "Most people clean what they can see. Dark data is         ║
║    everything they can't. Invisible files, system junk,      ║
║    forgotten debris. All of it slowing you down."            ║
║                                                              ║
╚══════════════════════════════════════════════════════════════╝
BANNER

echo ""
echo "  Scanning: $HOSTNAME"
echo "  Date:     $DATE"
echo "  Report:   $REPORT_FILE"
echo ""
echo "  Working... this takes 30-60 seconds..."
echo ""

TOTAL=0
CATEGORIES=()

# ----- SCANS -----
declare -A RESULTS

echo -e "${CYAN}[1/14]${NC} Scanning APT/Package caches..."
APT=$(dsize /var/cache/apt/archives)
YUM=$(dsize /var/cache/yum)
DNF=$(dsize /var/cache/dnf)
SNAP=$(dsize /var/lib/snapd/cache)
PKG_TOTAL=$((APT + YUM + DNF + SNAP))
RESULTS[pkg_cache]=$PKG_TOTAL
TOTAL=$((TOTAL + PKG_TOTAL))

echo -e "${CYAN}[2/14]${NC} Scanning journal/system logs..."
JOURNAL=$(journalctl --disk-usage 2>/dev/null | grep -oP '\d+(\.\d+)?[KMG]' | head -1 | awk 'BEGIN{OFS=""} { 
    n=substr($0,1,length($0)-1); unit=substr($0,length($0),1);
    if(unit=="K") print n*1024;
    else if(unit=="M") print n*1048576;
    else if(unit=="G") print n*1073741824;
    else print n;
}')
JOURNAL=${JOURNAL:-0}
JOURNAL=${JOURNAL%.*}  # strip decimals
VAR_LOG=$(find /var/log -type f \( -name "*.gz" -o -name "*.[0-9]" -o -name "*.[0-9].gz" -o -name "*.old" \) -exec du -b {} + 2>/dev/null | awk '{sum+=$1} END{print sum+0}')
LOG_TOTAL=$((JOURNAL + VAR_LOG))
RESULTS[logs]=$LOG_TOTAL
TOTAL=$((TOTAL + LOG_TOTAL))

echo -e "${CYAN}[3/14]${NC} Scanning Docker debris..."
DOCKER=0
if command -v docker &>/dev/null; then
    DOCKER_DATA=$(docker system df --format "{{.Size}}" 2>/dev/null | head -1)
    DOCKER=$(dsize /var/lib/docker/overlay2 2>/dev/null || echo 0)
    DOCKER_STOPPED=$(docker ps -a --format "{{.ID}}" --filter "status=exited" 2>/dev/null | wc -l)
    DOCKER_IMAGES=$(docker images --filter "dangling=true" -q 2>/dev/null | wc -l)
fi
RESULTS[docker]=$DOCKER
TOTAL=$((TOTAL + DOCKER))

echo -e "${CYAN}[4/14]${NC} Scanning temp files..."
TMP=$(dsize /tmp)
VAR_TMP=$(dsize /var/tmp)
TMP_TOTAL=$((TMP + VAR_TMP))
RESULTS[temp]=$TMP_TOTAL
TOTAL=$((TOTAL + TMP_TOTAL))

echo -e "${CYAN}[5/14]${NC} Scanning crash dumps..."
CRASH=$(dsize /var/crash)
COREDUMP=$(dsize /var/lib/systemd/coredump)
CRASH_TOTAL=$((CRASH + COREDUMP))
RESULTS[crashes]=$CRASH_TOTAL
TOTAL=$((TOTAL + CRASH_TOTAL))

echo -e "${CYAN}[6/14]${NC} Scanning forgotten backups in user homes..."
BACKUP_FILES=$(find /home /root -type f \( -name "*.tar.gz" -o -name "*.tar.bz2" -o -name "*.zip" -o -name "*.sql.bak" -o -name "*.bak" -o -name "backup-*" -o -name "*.dump" \) -mtime +30 -size +10M -exec du -b {} + 2>/dev/null | awk '{sum+=$1} END{print sum+0}')
RESULTS[old_backups]=$BACKUP_FILES
TOTAL=$((TOTAL + BACKUP_FILES))

echo -e "${CYAN}[7/14]${NC} Scanning old kernel versions..."
KERNELS=0
if command -v dpkg &>/dev/null; then
    KERNEL_COUNT=$(dpkg -l 'linux-image-*' 2>/dev/null | grep -c '^ii' || echo 0)
    if [ "$KERNEL_COUNT" -gt 2 ]; then
        KERNELS=$(du -b /boot/vmlinuz-* /boot/initrd.img-* 2>/dev/null | awk '{sum+=$1} END{print sum+0}')
        KERNELS=$((KERNELS * (KERNEL_COUNT - 2) / KERNEL_COUNT))
    fi
fi
RESULTS[old_kernels]=$KERNELS
TOTAL=$((TOTAL + KERNELS))

echo -e "${CYAN}[8/14]${NC} Scanning orphaned packages..."
ORPHANS=0
if command -v deborphan &>/dev/null; then
    ORPHAN_COUNT=$(deborphan 2>/dev/null | wc -l)
elif command -v apt-mark &>/dev/null; then
    ORPHAN_COUNT=$(apt-mark showauto 2>/dev/null | wc -l)
    ORPHAN_COUNT=$((ORPHAN_COUNT / 20)) # rough estimate
else
    ORPHAN_COUNT=0
fi
RESULTS[orphans]=$ORPHAN_COUNT

echo -e "${CYAN}[9/14]${NC} Scanning node_modules debris..."
NODE_MODULES=$(find /home /var/www -name "node_modules" -type d 2>/dev/null | xargs du -sb 2>/dev/null | awk '{sum+=$1} END{print sum+0}')
RESULTS[node_modules]=$NODE_MODULES
TOTAL=$((TOTAL + NODE_MODULES))

echo -e "${CYAN}[10/14]${NC} Scanning pip/npm caches..."
PIP_CACHE=$(dsize /root/.cache/pip)
PIP_CACHE_USER=$(find /home -maxdepth 4 -name ".cache" -type d 2>/dev/null -exec dsize {} \; | awk '{sum+=$1} END{print sum+0}')
NPM_CACHE=$(dsize /root/.npm)
CACHE_TOTAL=$((PIP_CACHE + PIP_CACHE_USER + NPM_CACHE))
RESULTS[dev_cache]=$CACHE_TOTAL
TOTAL=$((TOTAL + CACHE_TOTAL))

echo -e "${CYAN}[11/14]${NC} Scanning old mail spool..."
MAIL_QUEUE=$(dsize /var/spool/postfix/deferred)
MAIL_DEAD=$(find /var/mail /var/spool/mail -name "*.bak" -o -name "*.old" 2>/dev/null -exec du -b {} + | awk '{sum+=$1} END{print sum+0}')
MAIL_TOTAL=$((MAIL_QUEUE + MAIL_DEAD))
RESULTS[mail]=$MAIL_TOTAL
TOTAL=$((TOTAL + MAIL_TOTAL))

echo -e "${CYAN}[12/14]${NC} Scanning user cache directories..."
USER_CACHE=$(find /home -maxdepth 3 -type d -name "cache" -o -name ".cache" 2>/dev/null -exec dsize {} \; | awk '{sum+=$1} END{print sum+0}')
RESULTS[user_cache]=$USER_CACHE
TOTAL=$((TOTAL + USER_CACHE))

echo -e "${CYAN}[13/14]${NC} Scanning zombie/defunct processes..."
ZOMBIES=$(ps aux 2>/dev/null | awk '$8=="Z" {count++} END{print count+0}')
RESULTS[zombies]=$ZOMBIES

echo -e "${CYAN}[14/14]${NC} Scanning overall disk usage..."
DISK_USED=$(df -B1 / | awk 'NR==2{print $3}')
DISK_TOTAL=$(df -B1 / | awk 'NR==2{print $2}')
DISK_FREE=$(df -B1 / | awk 'NR==2{print $4}')
DISK_PCT=$(df / | awk 'NR==2{gsub("%",""); print $5}')

echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BOLD}                    DARK DATA REPORT${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "  Server:           ${BOLD}$HOSTNAME${NC}"
echo -e "  Disk used:        $(hsize $DISK_USED) of $(hsize $DISK_TOTAL) (${DISK_PCT}%)"
echo -e "  Free space:       $(hsize $DISK_FREE)"
echo ""
echo -e "${BOLD}  DARK DATA FOUND:${NC}"
echo ""

# Summary table
printf "  %-35s %12s %8s\n" "CATEGORY" "SIZE" "STATUS"
printf "  %-35s %12s %8s\n" "───────────────────────────────────" "────────────" "────────"

report_line() {
    local name=$1
    local bytes=$2
    local threshold_mb=${3:-100}
    local threshold_bytes=$((threshold_mb * 1024 * 1024))
    local status
    local color
    if [ "$bytes" -gt "$threshold_bytes" ]; then
        status="HIGH"
        color=$RED
    elif [ "$bytes" -gt $((threshold_bytes / 10)) ]; then
        status="MEDIUM"
        color=$YELLOW
    else
        status="LOW"
        color=$GREEN
    fi
    printf "  %-35s %12s ${color}%8s${NC}\n" "$name" "$(hsize $bytes)" "$status"
}

report_line "Package caches (apt/yum/snap)" ${RESULTS[pkg_cache]} 500
report_line "Journal + rotated logs" ${RESULTS[logs]} 500
report_line "Docker debris" ${RESULTS[docker]} 1000
report_line "Temp files (/tmp, /var/tmp)" ${RESULTS[temp]} 100
report_line "Crash dumps + core files" ${RESULTS[crashes]} 50
report_line "Old backups in home dirs" ${RESULTS[old_backups]} 500
report_line "Old kernels" ${RESULTS[old_kernels]} 200
report_line "node_modules" ${RESULTS[node_modules]} 500
report_line "Dev caches (pip/npm)" ${RESULTS[dev_cache]} 200
report_line "Mail queue/dead letters" ${RESULTS[mail]} 50
report_line "User cache dirs" ${RESULTS[user_cache]} 500

echo ""
echo -e "${BOLD}  OTHER FINDINGS:${NC}"
printf "  %-35s %12s\n" "Zombie processes" "${RESULTS[zombies]}"
printf "  %-35s %12s\n" "Orphaned packages" "${RESULTS[orphans]}"

echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BOLD}  TOTAL DARK DATA:        ${RED}$(hsize $TOTAL)${NC}"

# Calculate percentage of disk
PCT=$(awk -v t=$TOTAL -v u=$DISK_USED 'BEGIN{if(u>0) printf "%.1f", t*100/u; else print 0}')
echo -e "${BOLD}  % of used disk space:   ${RED}${PCT}%${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Save report
{
    echo "DARK DATA REPORT — $HOSTNAME — $DATE"
    echo "============================================"
    echo ""
    echo "Disk: $(hsize $DISK_USED) of $(hsize $DISK_TOTAL) (${DISK_PCT}%)"
    echo "Free: $(hsize $DISK_FREE)"
    echo ""
    echo "Package caches:     $(hsize ${RESULTS[pkg_cache]})"
    echo "Logs:               $(hsize ${RESULTS[logs]})"
    echo "Docker:             $(hsize ${RESULTS[docker]})"
    echo "Temp files:         $(hsize ${RESULTS[temp]})"
    echo "Crashes:            $(hsize ${RESULTS[crashes]})"
    echo "Old backups:        $(hsize ${RESULTS[old_backups]})"
    echo "Old kernels:        $(hsize ${RESULTS[old_kernels]})"
    echo "node_modules:       $(hsize ${RESULTS[node_modules]})"
    echo "Dev caches:         $(hsize ${RESULTS[dev_cache]})"
    echo "Mail:               $(hsize ${RESULTS[mail]})"
    echo "User cache:         $(hsize ${RESULTS[user_cache]})"
    echo ""
    echo "TOTAL:              $(hsize $TOTAL) (${PCT}% of used)"
} > "$REPORT_FILE"

# Recommendations
echo -e "${BOLD}  WHAT THIS MEANS:${NC}"
echo ""
if [ "$TOTAL" -gt 10737418240 ]; then
    echo -e "  ${RED}⚠  Your server has ${BOLD}$(hsize $TOTAL)${NC}${RED} of invisible junk.${NC}"
    echo -e "  ${RED}   This is slowing you down and taking up storage unnecessarily.${NC}"
elif [ "$TOTAL" -gt 1073741824 ]; then
    echo -e "  ${YELLOW}⚠  Your server has $(hsize $TOTAL) of dark data.${NC}"
    echo -e "  ${YELLOW}   Worth cleaning, but not critical yet.${NC}"
else
    echo -e "  ${GREEN}✓  Your server is relatively clean ($(hsize $TOTAL) dark data).${NC}"
fi

echo ""
echo -e "${BOLD}  CALL TO ACTION:${NC}"
echo ""
echo "  Linux Lockdown can safely clean all of this for you."
echo ""
echo "  • One-off clean:      £199 per server"
echo "  • Managed plan:       Included free (from £299/mo)"
echo "  • Visit:              https://linuxlockdown.com"
echo "  • Email:              contact@linuxlockdown.com"
echo ""
echo "  Full report saved to: $REPORT_FILE"
echo ""
