#!/bin/bash
#
# backup-files.sh - Critical files archive backup
#
# Creates a gzip-compressed tar archive of important project files
# Excludes node_modules, vendor, venv, __pycache__, .git, and logs
#

set -euo pipefail

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_ROOT="$(dirname "$SCRIPT_DIR")"
STORAGE_DIR="$BACKUP_ROOT/storage/files"
LOG_FILE="$BACKUP_ROOT/logs/backup.log"
PROJECT_DIR="$(dirname "$BACKUP_ROOT")"

# Timestamp format for backup files
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$STORAGE_DIR/backup_${TIMESTAMP}.tar.gz"
LATEST_LINK="$STORAGE_DIR/latest.tar.gz"

# Logging function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FILES] $1" | tee -a "$LOG_FILE"
}

# Error handler
error_exit() {
    log "ERROR: $1"
    exit 1
}

# Ensure storage directory exists
mkdir -p "$STORAGE_DIR"

log "Starting files backup..."

# Change to project directory for relative paths in archive
cd "$PROJECT_DIR"

# Define what to backup (relative to project root)
BACKUP_PATHS=(
    "wordpress/wp-content/themes/generatepress-child"
    "wordpress/wp-content/uploads"
    "src"
    "dev"
    "mariadb"
    "content-pipeline"
    ".env"
    "docker-compose.yml"
    "php.ini"
    "composer.json"
    "composer.lock"
)

# Build list of existing paths to backup
EXISTING_PATHS=()
for path in "${BACKUP_PATHS[@]}"; do
    if [[ -e "$path" ]]; then
        EXISTING_PATHS+=("$path")
    else
        log "Skipping non-existent path: $path"
    fi
done

if [[ ${#EXISTING_PATHS[@]} -eq 0 ]]; then
    error_exit "No files to backup - all paths are missing"
fi

log "Backing up ${#EXISTING_PATHS[@]} paths..."

# Create the archive with exclusions
tar --create \
    --gzip \
    --file="$BACKUP_FILE" \
    --exclude='node_modules' \
    --exclude='vendor' \
    --exclude='venv' \
    --exclude='__pycache__' \
    --exclude='.git' \
    --exclude='*.log' \
    --exclude='*.pyc' \
    --exclude='.pytest_cache' \
    --exclude='.mypy_cache' \
    --exclude='tmp' \
    --exclude='.tmp' \
    --exclude='*.tmp' \
    --exclude='.DS_Store' \
    --exclude='Thumbs.db' \
    "${EXISTING_PATHS[@]}" 2>/dev/null || {
        # tar returns 1 for warnings (like "file changed as we read it")
        # Only fail on actual errors (exit code > 1)
        if [[ $? -gt 1 ]]; then
            error_exit "tar command failed"
        fi
    }

# Verify backup was created and has content
if [[ ! -f "$BACKUP_FILE" ]]; then
    error_exit "Backup file was not created"
fi

BACKUP_SIZE=$(stat -f%z "$BACKUP_FILE" 2>/dev/null || stat -c%s "$BACKUP_FILE" 2>/dev/null)
if [[ "$BACKUP_SIZE" -lt 1000 ]]; then
    rm -f "$BACKUP_FILE"
    error_exit "Backup file is too small (${BACKUP_SIZE} bytes), likely failed"
fi

# Update latest symlink
rm -f "$LATEST_LINK"
ln -s "$BACKUP_FILE" "$LATEST_LINK"

# Get human-readable size
HUMAN_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)

# Count files in archive
FILE_COUNT=$(tar -tzf "$BACKUP_FILE" 2>/dev/null | wc -l)

log "Files backup completed: $BACKUP_FILE ($HUMAN_SIZE, $FILE_COUNT entries)"

exit 0
