#!/bin/bash

# Immich Backup Validation Script
# This script validates Immich backup files for integrity and completeness

# Note: We don't use set -e here to ensure all validations are performed

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

# Function to display usage
usage() {
    echo "Usage: $0 [backup_directory]"
    echo ""
    echo "Arguments:"
    echo "  backup_directory    Directory containing backup files (default: ../immich_backups)"
    echo ""
    echo "This script validates:"
    echo "  - Database backup file integrity"
    echo "  - Upload archive integrity"
    echo "  - File sizes and timestamps"
    echo "  - Backup completeness"
}

# Parse command line arguments
BACKUP_DIR="${1:-$(dirname "$0")/../immich_backups}"

# Set up logging to central logs directory
LOG_DIR="$(dirname "$0")/../logs"
mkdir -p "$LOG_DIR"
LOG_FILE="${LOG_DIR}/immich-validation.log"

# Function to log validation results
log_validation() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# Verify backup directory exists
if [ ! -d "$BACKUP_DIR" ]; then
    echo -e "${RED}Error: Backup directory not found: $BACKUP_DIR${NC}"
    log_validation "Error: Backup directory not found: $BACKUP_DIR"
    exit 1
fi

log_validation "Starting backup validation for directory: $BACKUP_DIR"
echo "=== IMMICH BACKUP VALIDATION ==="
echo "Backup directory: $BACKUP_DIR"
echo ""

# Find backup files
DB_BACKUPS=$(find "$BACKUP_DIR" -name "immich_db_backup_*.sql.gz" -type f | sort -r)
UPLOAD_BACKUPS=$(find "$BACKUP_DIR" -name "immich_uploads_*.tar.gz" -type f | sort -r)

TOTAL_ERRORS=0

echo "=== DATABASE BACKUPS ==="
if [ -z "$DB_BACKUPS" ]; then
    echo -e "${YELLOW}Warning: No database backup files found${NC}"
    log_validation "Warning: No database backup files found"
    ((TOTAL_ERRORS++))
else
    for backup in $DB_BACKUPS; do
        echo "Validating: $(basename "$backup")"

        # Check file size
        SIZE=$(stat -c%s "$backup" 2>/dev/null || echo "0")
        if [ "$SIZE" -lt 100 ]; then
            echo -e "  ${RED}✗ File is too small (${SIZE} bytes)${NC}"
            log_validation "Error: File is too small (${SIZE} bytes) - $(basename "$backup")"
            ((TOTAL_ERRORS++))
        else
            echo -e "  ${GREEN}✓ File size OK ($(du -h "$backup" | cut -f1))${NC}"
        fi

        # Check if it's a valid gzip file
        if gzip -t "$backup" 2>/dev/null; then
            echo -e "  ${GREEN}✓ Gzip file integrity OK${NC}"
        else
            echo -e "  ${RED}✗ Gzip file corruption detected${NC}"
            log_validation "Error: Gzip file corruption detected - $(basename "$backup")"
            ((TOTAL_ERRORS++))
        fi

        # Check if SQL content looks valid (basic check)
        if zcat "$backup" 2>/dev/null | head -n 10 | grep -q "PostgreSQL database dump"; then
            echo -e "  ${GREEN}✓ SQL content appears valid${NC}"
        else
            echo -e "  ${YELLOW}? Cannot verify SQL content format${NC}"
        fi

        echo ""
    done
fi

echo "=== UPLOAD BACKUPS ==="
if [ -z "$UPLOAD_BACKUPS" ]; then
    echo -e "${YELLOW}Warning: No upload backup files found${NC}"
    log_validation "Warning: No upload backup files found"
    ((TOTAL_ERRORS++))
else
    for backup in $UPLOAD_BACKUPS; do
        echo "Validating: $(basename "$backup")"

        # Check file size
        SIZE=$(stat -c%s "$backup" 2>/dev/null || echo "0")
        if [ "$SIZE" -lt 100 ]; then
            echo -e "  ${RED}✗ File is too small (${SIZE} bytes)${NC}"
            log_validation "Error: File is too small (${SIZE} bytes) - $(basename "$backup")"
            ((TOTAL_ERRORS++))
        else
            echo -e "  ${GREEN}✓ File size OK ($(du -h "$backup" | cut -f1))${NC}"
        fi

        # Check if it's a valid tar.gz file
        if tar -tzf "$backup" >/dev/null 2>&1; then
            echo -e "  ${GREEN}✓ Tar.gz file integrity OK${NC}"

            # Count files in archive
            FILE_COUNT=$(tar -tzf "$backup" 2>/dev/null | wc -l)
            echo -e "  ${GREEN}✓ Archive contains ${FILE_COUNT} files/directories${NC}"
        else
            echo -e "  ${RED}✗ Tar.gz file corruption detected${NC}"
            log_validation "Error: Tar.gz file corruption detected - $(basename "$backup")"
            ((TOTAL_ERRORS++))
        fi

        echo ""
    done
fi

echo "=== BACKUP PAIRING VALIDATION ==="
# Check if we have matching pairs of backups (same timestamp)
DB_TIMESTAMPS=$(echo "$DB_BACKUPS" | sed 's/.*immich_db_backup_\([0-9_]*\)\.sql\.gz/\1/' | sort)
UPLOAD_TIMESTAMPS=$(echo "$UPLOAD_BACKUPS" | sed 's/.*immich_uploads_\([0-9_]*\)\.tar\.gz/\1/' | sort)

echo "Database backup timestamps: $(echo "$DB_TIMESTAMPS" | tr '\n' ' ')"
echo "Upload backup timestamps: $(echo "$UPLOAD_TIMESTAMPS" | tr '\n' ' ')"

# Find matching pairs
MATCHED_PAIRS=0
for db_ts in $DB_TIMESTAMPS; do
    if echo "$UPLOAD_TIMESTAMPS" | grep -q "^${db_ts}$"; then
        echo -e "${GREEN}✓ Complete backup set found for timestamp: $db_ts${NC}"
        ((MATCHED_PAIRS++))
    else
        echo -e "${YELLOW}? Incomplete backup set for timestamp: $db_ts (missing upload backup)${NC}"
        log_validation "Warning: Incomplete backup set for timestamp: $db_ts (missing upload backup)"
    fi
done

for upload_ts in $UPLOAD_TIMESTAMPS; do
    if ! echo "$DB_TIMESTAMPS" | grep -q "^${upload_ts}$"; then
        echo -e "${YELLOW}? Incomplete backup set for timestamp: $upload_ts (missing database backup)${NC}"
        log_validation "Warning: Incomplete backup set for timestamp: $upload_ts (missing database backup)"
    fi
done

# Find most recent complete backup set
LATEST_COMPLETE=""
for db_ts in $DB_TIMESTAMPS; do
    if echo "$UPLOAD_TIMESTAMPS" | grep -q "^${db_ts}$"; then
        LATEST_COMPLETE="$db_ts"
        break  # First one is most recent due to sort -r
    fi
done

echo ""
echo "=== VALIDATION SUMMARY ==="
echo "Complete backup pairs: $MATCHED_PAIRS"
echo "Total validation errors: $TOTAL_ERRORS"

if [ -n "$LATEST_COMPLETE" ]; then
    echo -e "${GREEN}Most recent complete backup: $LATEST_COMPLETE${NC}"
    echo ""
    echo "=== RESTORATION COMMANDS ==="
    echo "To restore the most recent complete backup:"
    echo ""
    echo "# Dry run (recommended first):"
    echo "./restore-immich.sh \\"
    echo "  --db-backup \"$BACKUP_DIR/immich_db_backup_${LATEST_COMPLETE}.sql.gz\" \\"
    echo "  --uploads-backup \"$BACKUP_DIR/immich_uploads_${LATEST_COMPLETE}.tar.gz\" \\"
    echo "  --dry-run"
    echo ""
    echo "# Actual restoration:"
    echo "./restore-immich.sh \\"
    echo "  --db-backup \"$BACKUP_DIR/immich_db_backup_${LATEST_COMPLETE}.sql.gz\" \\"
    echo "  --uploads-backup \"$BACKUP_DIR/immich_uploads_${LATEST_COMPLETE}.tar.gz\""
    echo ""
    echo "# Restore database only:"
    echo "./restore-immich.sh \\"
    echo "  --db-backup \"$BACKUP_DIR/immich_db_backup_${LATEST_COMPLETE}.sql.gz\" \\"
    echo "  --uploads-backup \"$BACKUP_DIR/immich_uploads_${LATEST_COMPLETE}.tar.gz\" \\"
    echo "  --skip-uploads"
    echo ""
    echo "# Restore uploads only:"
    echo "./restore-immich.sh \\"
    echo "  --db-backup \"$BACKUP_DIR/immich_db_backup_${LATEST_COMPLETE}.sql.gz\" \\"
    echo "  --uploads-backup \"$BACKUP_DIR/immich_uploads_${LATEST_COMPLETE}.tar.gz\" \\"
    echo "  --skip-db"
fi

log_validation "Validation summary: $MATCHED_PAIRS complete backup pairs, $TOTAL_ERRORS errors"

if [ "$TOTAL_ERRORS" -eq 0 ]; then
    echo -e "${GREEN}✓ All backup validations passed${NC}"
    log_validation "Success: All backup validations passed"
    exit 0
else
    echo -e "${RED}✗ Backup validation failed with $TOTAL_ERRORS errors${NC}"
    log_validation "Error: Backup validation failed with $TOTAL_ERRORS errors"
    exit 1
fi
