#!/bin/bash

# Plex Database Directory Cleanup Script
# Author: Peter Wood <peter@peterwood.dev>
# Created: June 21, 2025
#
# This script safely removes temporary, recovery, and corrupted files
# from the Plex databases directory while preserving active databases
# and legitimate Plex built-in backups.

# Don't exit on errors, we want to continue processing all files
set +e

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

# Configuration
PLEX_DB_DIR="/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases"
DRY_RUN=false
VERBOSE=false

# Usage function
show_usage() {
    cat << EOF
Usage: $0 [OPTIONS]

Clean up temporary, recovery, and corrupted files from Plex databases directory.

OPTIONS:
    --dry-run        Show what would be removed without actually removing
    --verbose        Show detailed output
    --help           Show this help message

DESCRIPTION:
    This script removes:
    - Temporary files (*-tmp, *-2025-*-tmp)
    - MD5 checksum files (*.md5)
    - Recovery files (*recovery*)
    - Repaired files (*repaired*)
    - Empty backup files (*empty-backup*)
    - DBRepair.log files
    - Corrupted database directories (corrupted-*)

    This script preserves:
    - Active database files (*.db, *.db-shm, *.db-wal)
    - Plex built-in backups (*.backup.*)
    - Legitimate dated backups (*.db.YYYYMMDD)
    - EPG databases (tv.plex.providers.epg.cloud-*.db)

EXAMPLES:
    $0 --dry-run        # Preview what would be removed
    $0 --verbose        # Remove files with detailed output
    sudo $0             # Remove files (requires root for some files)

EOF
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --verbose)
            VERBOSE=true
            shift
            ;;
        --help)
            show_usage
            exit 0
            ;;
        *)
            echo -e "${RED}Error: Unknown option '$1'${NC}"
            show_usage
            exit 1
            ;;
    esac
done

# Function to log messages
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_verbose() {
    if [[ "$VERBOSE" == "true" ]]; then
        echo -e "${BLUE}[VERBOSE]${NC} $1"
    fi
}

# Function to safely remove files/directories
safe_remove() {
    local item="$1"
    local item_type="$2"  # "file" or "directory"
    
    if [[ ! -e "$item" ]]; then
        log_verbose "Skipping $item (does not exist)"
        return 0
    fi
    
    if [[ "$DRY_RUN" == "true" ]]; then
        echo -e "${YELLOW}[DRY-RUN]${NC} Would remove $item_type: $(basename "$item")"
        if [[ "$item_type" == "directory" ]]; then
            echo -e "${YELLOW}         ${NC} Contents: $(ls -la "$item" 2>/dev/null | wc -l) items"
        else
            echo -e "${YELLOW}         ${NC} Size: $(ls -lah "$item" 2>/dev/null | awk '{print $5}')"
        fi
    else
        log_verbose "Removing $item_type: $(basename "$item")"
        if [[ "$item_type" == "directory" ]]; then
            if rm -rf "$item" 2>/dev/null; then
                log_success "Removed directory: $(basename "$item")"
            else
                log_error "Failed to remove directory: $(basename "$item")"
                return 1
            fi
        else
            if rm -f "$item" 2>/dev/null; then
                log_success "Removed file: $(basename "$item")"
            else
                log_error "Failed to remove file: $(basename "$item")"
                return 1
            fi
        fi
    fi
}

# Main cleanup function
cleanup_databases() {
    log_info "Starting Plex database directory cleanup..."
    
    if [[ ! -d "$PLEX_DB_DIR" ]]; then
        log_error "Plex databases directory not found: $PLEX_DB_DIR"
        exit 1
    fi
    
    cd "$PLEX_DB_DIR" || {
        log_error "Cannot access Plex databases directory: $PLEX_DB_DIR"
        exit 1
    }
    
    local files_removed=0
    local dirs_removed=0
    local total_size_removed=0
    
    log_info "Scanning directory: $PLEX_DB_DIR"
    
    # Remove temporary files
    log_info "Cleaning up temporary files..."
    for file in *-tmp *-2025-*-tmp; do
        if [[ -f "$file" && "$file" != "*-tmp" && "$file" != "*-2025-*-tmp" ]]; then
            safe_remove "$file" "file"
            ((files_removed++))
        fi
    done
    
    # Remove MD5 checksum files
    log_info "Cleaning up MD5 checksum files..."
    for file in *.md5; do
        if [[ -f "$file" && "$file" != "*.md5" ]]; then
            safe_remove "$file" "file"
            ((files_removed++))
        fi
    done
    
    # Remove recovery files
    log_info "Cleaning up recovery files..."
    for file in *recovery*; do
        if [[ -f "$file" && "$file" != "*recovery*" ]]; then
            safe_remove "$file" "file"
            ((files_removed++))
        fi
    done
    
    # Remove repaired files
    log_info "Cleaning up repaired files..."
    for file in *repaired*; do
        if [[ -f "$file" && "$file" != "*repaired*" ]]; then
            safe_remove "$file" "file"
            ((files_removed++))
        fi
    done
    
    # Remove empty backup files
    log_info "Cleaning up empty backup files..."
    for file in *empty-backup*; do
        if [[ -f "$file" && "$file" != "*empty-backup*" ]]; then
            safe_remove "$file" "file"
            ((files_removed++))
        fi
    done
    
    # Remove DBRepair.log
    log_info "Cleaning up repair log files..."
    if [[ -f "DBRepair.log" ]]; then
        safe_remove "DBRepair.log" "file"
        ((files_removed++))
    fi
    
    # Remove corrupted directories
    log_info "Cleaning up corrupted database directories..."
    for dir in corrupted-*; do
        if [[ -d "$dir" && "$dir" != "corrupted-*" ]]; then
            safe_remove "$dir" "directory"
            ((dirs_removed++))
        fi
    done
    
    # Summary
    echo
    log_info "=== Cleanup Summary ==="
    if [[ "$DRY_RUN" == "true" ]]; then
        echo -e "${YELLOW}[DRY-RUN]${NC} Files that would be removed: $files_removed"
        echo -e "${YELLOW}[DRY-RUN]${NC} Directories that would be removed: $dirs_removed"
    else
        log_success "Files removed: $files_removed"
        log_success "Directories removed: $dirs_removed"
    fi
    
    # Show what remains
    echo
    log_info "=== Remaining Files ==="
    echo -e "${GREEN}Active database files:${NC}"
    ls -lah *.db *.db-shm *.db-wal 2>/dev/null | grep -E "\.(db|db-shm|db-wal)$" || echo "  None found"
    
    echo
    echo -e "${GREEN}Backup files:${NC}"
    ls -lah *.backup.* 2>/dev/null || echo "  None found"
    
    echo
    echo -e "${GREEN}Historical backups:${NC}"
    ls -lah *.db.2[0-9][0-9][0-9][0-9][0-9][0-9][0-9] 2>/dev/null || echo "  None found"
    
    echo
    echo -e "${GREEN}Other database files:${NC}"
    ls -lah tv.plex.providers.*.db 2>/dev/null || echo "  None found"
}

# Pre-flight checks
preflight_checks() {
    log_info "Performing pre-flight checks..."
    
    # Check if Plex is running
    if pgrep -f "Plex Media Server" > /dev/null; then
        log_warning "Plex Media Server is currently running!"
        log_warning "For safety, consider stopping Plex before cleanup:"
        log_warning "  sudo systemctl stop plexmediaserver"
        echo
        read -p "Continue anyway? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Cleanup cancelled by user"
            exit 0
        fi
    fi
    
    # Check permissions
    if [[ ! -w "$PLEX_DB_DIR" ]]; then
        log_warning "You may not have write permissions to the databases directory"
        log_warning "Consider running with sudo if you encounter permission errors"
    fi
    
    # Check disk space
    local available_space=$(df -h "$PLEX_DB_DIR" | awk 'NR==2 {print $4}')
    log_info "Available disk space: $available_space"
}

# Main execution
main() {
    echo -e "${BLUE}+================================================================+${NC}"
    echo -e "${BLUE}|              PLEX DATABASE CLEANUP TOOL                       |${NC}"
    echo -e "${BLUE}+================================================================+${NC}"
    echo
    
    if [[ "$DRY_RUN" == "true" ]]; then
        log_warning "DRY-RUN MODE: No files will actually be removed"
        echo
    fi
    
    preflight_checks
    cleanup_databases
    
    echo
    if [[ "$DRY_RUN" == "true" ]]; then
        log_info "Dry-run completed. Run without --dry-run to actually remove files."
    else
        log_success "Database cleanup completed successfully!"
        log_info "You can now restart Plex Media Server if it was stopped."
    fi
}

# Execute main function
main "$@"
