#!/bin/sh
# Crontab för att köra backupscriptet en gång klockan 15:00 varje dag:
#0 15 * * * /usr/local/bin/castit_backup.sh serhat serre0931 /var/www/backup/ >> /var/log/castit_backup.log 2>&1

set -eu

# Loggfil för backup
LOG_FILE="/var/log/castit_backup.log"

# Funktion för att logga med timestamp
log() {
  # Säkerställ att loggkatalogen finns
  mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE" 2>/dev/null || echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}

# Funktion för att konvertera datum till timestamp (kompatibel med både GNU och BSD date)
date_to_timestamp() {
  local date_str="$1"
  # Försök GNU date först (Linux)
  date -d "$date_str" +%s 2>/dev/null || \
  # Försök BSD date (macOS/FreeBSD)
  date -j -f "%Y-%m-%d" "$date_str" +%s 2>/dev/null || \
  echo ""
}

# Funktion för att rensa gamla backups
# Strategi: Behåll senaste 4 dagarnas backups, sedan 1 backup per månad i 1 år
cleanup_old_backups() {
  local backup_dir="$1"
  local today=$(date +%s)
  local four_days_ago=$((today - 4 * 24 * 60 * 60))
  local one_year_ago=$((today - 365 * 24 * 60 * 60))

  log "Starting cleanup of old backups..."
  log "Retention policy: Keep last 4 days, then 1 backup per month for 1 year"

  # Steg 1: Ta bort backups äldre än 1 år
  for backup_folder in "$backup_dir"/*; do
    [ -d "$backup_folder" ] || continue

    folder_name=$(basename "$backup_folder")
    backup_date=$(echo "$folder_name" | cut -d'_' -f1)

    if ! echo "$backup_date" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
      continue
    fi

    backup_timestamp=$(date_to_timestamp "$backup_date")
    if [ -z "$backup_timestamp" ]; then
      continue
    fi

    if [ "$backup_timestamp" -lt "$one_year_ago" ]; then
      log "Removing backup older than 1 year: $folder_name"
      rm -rf "$backup_folder" 2>/dev/null || log "WARNING: Failed to remove $folder_name"
    fi
  done

  # Steg 2: För backups mellan 4 dagar och 1 år, hitta första backupen per månad
  # Skapa en associativ array-liknande struktur med awk
  local temp_file=$(mktemp 2>/dev/null || echo "/tmp/castit_backup_temp_$$")
  > "$temp_file"

  # Samla alla backups mellan 4 dagar och 1 år, sorterade efter datum
  for backup_folder in "$backup_dir"/*; do
    [ -d "$backup_folder" ] || continue

    folder_name=$(basename "$backup_folder")
    backup_date=$(echo "$folder_name" | cut -d'_' -f1)

    if ! echo "$backup_date" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
      continue
    fi

    backup_timestamp=$(date_to_timestamp "$backup_date")
    if [ -z "$backup_timestamp" ]; then
      continue
    fi

    # Om backup är mellan 4 dagar och 1 år, lägg till i temp-filen
    if [ "$backup_timestamp" -ge "$one_year_ago" ] && [ "$backup_timestamp" -lt "$four_days_ago" ]; then
      year_month=$(echo "$backup_date" | cut -d'-' -f1-2)
      echo "$backup_timestamp|$year_month|$folder_name" >> "$temp_file"
    fi
  done

  # Hitta första backupen för varje månad (lägsta timestamp per månad)
  awk -F'|' '
    {
      if (!($2 in first) || $1 < first[$2]) {
        first[$2] = $1
        keep[$2] = $3
      }
    }
    END {
      for (month in keep) {
        print keep[month]
      }
    }
  ' "$temp_file" > "${temp_file}.keep" 2>/dev/null || true

  # Steg 3: Ta bort backups som inte ska behållas
  for backup_folder in "$backup_dir"/*; do
    [ -d "$backup_folder" ] || continue

    folder_name=$(basename "$backup_folder")
    backup_date=$(echo "$folder_name" | cut -d'_' -f1)

    if ! echo "$backup_date" | grep -qE '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
      continue
    fi

    backup_timestamp=$(date_to_timestamp "$backup_date")
    if [ -z "$backup_timestamp" ]; then
      continue
    fi

    # Behåll backups från senaste 4 dagarna
    if [ "$backup_timestamp" -ge "$four_days_ago" ]; then
      continue
    fi

    # Behåll månadsvisa backups
    if [ -f "${temp_file}.keep" ] && grep -q "^$folder_name$" "${temp_file}.keep" 2>/dev/null; then
      continue
    fi

    # Ta bort övriga backups mellan 4 dagar och 1 år
    if [ "$backup_timestamp" -ge "$one_year_ago" ] && [ "$backup_timestamp" -lt "$four_days_ago" ]; then
      year_month=$(echo "$backup_date" | cut -d'-' -f1-2)
      log "Removing backup (keeping monthly backup for $year_month): $folder_name"
      rm -rf "$backup_folder" 2>/dev/null || log "WARNING: Failed to remove $folder_name"
    fi
  done

  # Rensa temporära filer
  rm -f "$temp_file" "${temp_file}.keep" 2>/dev/null || true

  log "Cleanup completed."
}

# Kontrollera antal argument
if [ $# -ne 3 ]; then
  log "ERROR: Syntax: $0 <mysql_user> <mysql_password> <dump_dir>"
  exit 1
fi

USER="$1"
PASS="$2"
DIR="${3%/}"  # Ta bort avslutande snedstreck om det finns
TS="$(date +%F_%H%M%S)"
OUT="$DIR/$TS"

log "Starting backup process..."
log "Dumping MySQL database 'castit' to $OUT ($TS)"

# Skapa backup-katalog med säkra behörigheter
umask 077
if ! mkdir -p "$OUT"; then
  log "ERROR: Failed to create backup directory: $OUT"
  exit 1
fi

# Kontrollera att mysqldump finns
if [ ! -x /usr/bin/mysqldump ]; then
  log "ERROR: mysqldump not found or not executable"
  exit 1
fi

# Kontrollera att gzip finns
if ! command -v gzip >/dev/null 2>&1; then
  log "ERROR: gzip not found"
  exit 1
fi

# Kör backup
if /usr/bin/mysqldump \
    --single-transaction \
    --routines --triggers --events \
    --hex-blob \
    --default-character-set=utf8mb4 \
    --set-gtid-purged=OFF \
    -u "$USER" -p"$PASS" "castit" \
    | gzip -c > "$OUT/castit.sql.gz" 2>>"$LOG_FILE"; then
  SIZE=$(du -sh "$OUT" | cut -f1)
  log "SUCCESS: Backup completed. Size: $SIZE"
  log "Databasedump done: $OUT"

  # Rensa gamla backups enligt retention policy
  cleanup_old_backups "$DIR"
else
  log "ERROR: Failed dumping castit database"
  exit 1
fi