#!/usr/bin/env bash
#
# LLMHosts.com Database Backup Script
# Implements T-04 (Cloud-Native Portable) with automated SQLite backups
#
# Usage:
#   ./backup.sh [--retention-days 30] [--storage s3|local] [--bucket backup-bucket]
#
# Environment:
#   DB_PATH - Path to SQLite database (default: /data/llmhost.db)
#   BACKUP_DIR - Local backup directory (default: /backups)
#   S3_BUCKET - S3 bucket name (if storage=s3)
#   AWS_ACCESS_KEY_ID - AWS credentials (if storage=s3)
#   AWS_SECRET_ACCESS_KEY - AWS credentials (if storage=s3)

set -euo pipefail

# Configuration
DB_PATH="${DB_PATH:-/data/llmhost.db}"
BACKUP_DIR="${BACKUP_DIR:-/backups}"
RETENTION_DAYS="${RETENTION_DAYS:-30}"
STORAGE_TYPE="${STORAGE_TYPE:-local}"
S3_BUCKET="${S3_BUCKET:-}"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILENAME="llmhost_${TIMESTAMP}.db"
BACKUP_PATH="${BACKUP_DIR}/${BACKUP_FILENAME}"

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --retention-days)
      RETENTION_DAYS="$2"
      shift 2
      ;;
    --storage)
      STORAGE_TYPE="$2"
      shift 2
      ;;
    --bucket)
      S3_BUCKET="$2"
      shift 2
      ;;
    *)
      echo "Unknown option: $1"
      exit 1
      ;;
  esac
done

# Logging
log() {
  echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*"
}

error() {
  echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2
}

# Verify database exists
if [[ ! -f "$DB_PATH" ]]; then
  error "Database not found: $DB_PATH"
  exit 1
fi

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Backup using SQLite's .backup command (atomic, consistent)
log "Starting backup of $DB_PATH"
sqlite3 "$DB_PATH" ".backup '${BACKUP_PATH}'"

# Verify backup integrity
log "Verifying backup integrity"
if sqlite3 "$BACKUP_PATH" "PRAGMA integrity_check;" | grep -q "ok"; then
  log "Backup integrity verified"
else
  error "Backup integrity check failed!"
  rm -f "$BACKUP_PATH"
  exit 1
fi

# Compress backup
log "Compressing backup"
gzip -9 "${BACKUP_PATH}"
BACKUP_PATH="${BACKUP_PATH}.gz"

# Calculate checksum
CHECKSUM=$(sha256sum "$BACKUP_PATH" | awk '{print $1}')
echo "$CHECKSUM" > "${BACKUP_PATH}.sha256"
log "Checksum: $CHECKSUM"

# Upload to storage
case "$STORAGE_TYPE" in
  local)
    log "Backup saved locally: $BACKUP_PATH"
    ;;
  s3)
    if [[ -z "$S3_BUCKET" ]]; then
      error "S3_BUCKET not set"
      exit 1
    fi
    log "Uploading to S3: s3://${S3_BUCKET}/${BACKUP_FILENAME}.gz"
    aws s3 cp "$BACKUP_PATH" "s3://${S3_BUCKET}/${BACKUP_FILENAME}.gz"
    aws s3 cp "${BACKUP_PATH}.sha256" "s3://${S3_BUCKET}/${BACKUP_FILENAME}.sha256"
    log "Upload complete"
    ;;
  b2)
    if [[ -z "$B2_BUCKET" ]]; then
      error "B2_BUCKET not set"
      exit 1
    fi
    log "Uploading to B2: ${B2_BUCKET}/${BACKUP_FILENAME}.gz"
    b2 upload-file --quiet "$B2_BUCKET" "$BACKUP_PATH" "${BACKUP_FILENAME}.gz"
    b2 upload-file --quiet "$B2_BUCKET" "${BACKUP_PATH}.sha256" "${BACKUP_FILENAME}.sha256"
    log "Upload complete"
    ;;
  *)
    error "Unknown storage type: $STORAGE_TYPE"
    exit 1
    ;;
esac

# Cleanup old local backups (retention policy)
log "Cleaning up backups older than ${RETENTION_DAYS} days"
find "$BACKUP_DIR" -name "llmhost_*.db.gz" -mtime +${RETENTION_DAYS} -delete
find "$BACKUP_DIR" -name "llmhost_*.db.gz.sha256" -mtime +${RETENTION_DAYS} -delete

# Summary
BACKUP_SIZE=$(du -h "$BACKUP_PATH" | cut -f1)
log "Backup complete: $BACKUP_PATH (${BACKUP_SIZE})"
log "Retention: ${RETENTION_DAYS} days"

# Prometheus metrics (if enabled)
if [[ -n "${METRICS_DIR:-}" ]]; then
  mkdir -p "$METRICS_DIR"
  echo "llmhost_backup_last_success_timestamp $(date +%s)" > "$METRICS_DIR/backup.prom"
  echo "llmhost_backup_size_bytes $(stat -f%z "$BACKUP_PATH" 2>/dev/null || stat -c%s "$BACKUP_PATH")" >> "$METRICS_DIR/backup.prom"
fi

exit 0
