#!/bin/bash

# backup-gitea.sh - Backup Gitea data and PostgreSQL database
# Author: Shell Repository
# Description: Comprehensive backup solution for Gitea with PostgreSQL database

set -e

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

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_DIR="/home/acedanger/backups/gitea"
COMPOSE_DIR="/home/acedanger/docker/gitea"
COMPOSE_FILE="$COMPOSE_DIR/docker-compose.yml"
LOG_FILE="$SCRIPT_DIR/logs/gitea-backup.log"

# Ensure logs directory exists
mkdir -p "$(dirname "$LOG_FILE")"

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

# Display usage information
usage() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Backup Gitea data and PostgreSQL database"
    echo ""
    echo "Options:"
    echo "  -h, --help              Show this help message"
    echo "  -d, --dry-run           Show what would be backed up without doing it"
    echo "  -f, --force             Force backup even if one was recently created"
    echo "  -r, --restore FILE      Restore from specified backup directory"
    echo "  -l, --list              List available backups"
    echo "  -c, --cleanup           Clean up old backups (keeps last 7 days)"
    echo "  --keep-days DAYS        Number of days to keep backups (default: 7)"
    echo ""
    echo "Examples:"
    echo "  $0                      # Regular backup"
    echo "  $0 --dry-run            # See what would be backed up"
    echo "  $0 --list               # List available backups"
    echo "  $0 --restore /path/to/backup  # Restore from backup"
}

# Check dependencies
check_dependencies() {
    local missing_deps=()

    command -v docker >/dev/null 2>&1 || missing_deps+=("docker")
    command -v docker-compose >/dev/null 2>&1 || missing_deps+=("docker-compose")

    if [ ${#missing_deps[@]} -ne 0 ]; then
        echo -e "${RED}Error: Missing required dependencies: ${missing_deps[*]}${NC}"
        echo "Please install the missing dependencies and try again."
        exit 1
    fi

    # Check if docker-compose file exists
    if [ ! -f "$COMPOSE_FILE" ]; then
        echo -e "${RED}Error: Docker compose file not found at $COMPOSE_FILE${NC}"
        exit 1
    fi

    # Check if we can access Docker
    if ! docker info >/dev/null 2>&1; then
        echo -e "${RED}Error: Cannot access Docker. Check if Docker is running and you have permissions.${NC}"
        exit 1
    fi
}

# Check if Gitea services are running
check_gitea_services() {
    cd "$COMPOSE_DIR"

    if ! docker-compose ps | grep -q "Up"; then
        echo -e "${YELLOW}Warning: Gitea services don't appear to be running${NC}"
        echo "Some backup operations may fail if services are not running."
        read -p "Continue anyway? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            echo "Backup cancelled"
            exit 1
        fi
    fi
}

# List available backups
list_backups() {
    echo -e "${BLUE}=== Available Gitea Backups ===${NC}"

    if [ ! -d "$BACKUP_DIR" ]; then
        echo -e "${YELLOW}No backup directory found at $BACKUP_DIR${NC}"
        return 0
    fi

    local count=0

    # Find backup directories
    for backup_path in "$BACKUP_DIR"/gitea_backup_*; do
        if [ -d "$backup_path" ]; then
            local backup_name
            backup_name=$(basename "$backup_path")
            local backup_date
            backup_date=$(echo "$backup_name" | sed 's/gitea_backup_//' | sed 's/_/ /')
            local size
            size=$(du -sh "$backup_path" 2>/dev/null | cut -f1)
            local info_file="$backup_path/backup_info.txt"

            echo -e "${GREEN}📦 $backup_name${NC}"
            echo "   Date: $backup_date"
            echo "   Size: $size"
            echo "   Path: $backup_path"

            if [ -f "$info_file" ]; then
                local gitea_version
                gitea_version=$(grep "Gitea Version:" "$info_file" 2>/dev/null | cut -d: -f2- | xargs)
                if [ -n "$gitea_version" ]; then
                    echo "   Version: $gitea_version"
                fi
            fi

            echo ""
            count=$((count + 1))
        fi
    done

    if [ $count -eq 0 ]; then
        echo -e "${YELLOW}No backups found in $BACKUP_DIR${NC}"
        echo "Run a backup first to create one."
    else
        echo -e "${BLUE}Total backups found: $count${NC}"
    fi
}

# Change to compose directory
cd "$COMPOSE_DIR"

# Create timestamped backup directory
BACKUP_PATH="$BACKUP_DIR/gitea_backup_$DATE"
mkdir -p "$BACKUP_PATH"

# Backup PostgreSQL database
echo "Backing up PostgreSQL database..."
docker-compose exec -T db pg_dump -U ${POSTGRES_USER:-gitea} ${POSTGRES_DB:-gitea} > "$BACKUP_PATH/database.sql"

# Backup Gitea data volume
echo "Backing up Gitea data volume..."
docker run --rm \
    -v gitea_gitea:/data:ro \
    -v "$BACKUP_PATH":/backup \
    alpine:latest \
    tar czf /backup/gitea_data.tar.gz -C /data .

# Backup PostgreSQL data volume (optional, as we have the SQL dump)
echo "Backing up PostgreSQL data volume..."
docker run --rm \
    -v gitea_postgres:/data:ro \
    -v "$BACKUP_PATH":/backup \
    alpine:latest \
    tar czf /backup/postgres_data.tar.gz -C /data .

# Copy docker-compose configuration
echo "Backing up configuration files..."
cp "$COMPOSE_FILE" "$BACKUP_PATH/"
if [ -f ".env" ]; then
    cp ".env" "$BACKUP_PATH/"
fi

# Create a restore script
cat > "$BACKUP_PATH/restore.sh" << 'EOF'
#!/bin/bash
# Restore script for Gitea backup

set -e

RESTORE_DIR="$(dirname "$0")"
COMPOSE_DIR="/home/acedanger/docker/gitea"

echo "WARNING: This will stop Gitea and replace all data!"
read -p "Are you sure you want to continue? (yes/no): " confirm

if [ "$confirm" != "yes" ]; then
    echo "Restore cancelled"
    exit 1
fi

cd "$COMPOSE_DIR"

# Stop services
echo "Stopping Gitea services..."
docker-compose down

# Remove existing volumes
echo "Removing existing volumes..."
docker volume rm gitea_gitea gitea_postgres || true

# Recreate volumes
echo "Creating volumes..."
docker volume create gitea_gitea
docker volume create gitea_postgres

# Restore Gitea data
echo "Restoring Gitea data..."
docker run --rm \
    -v gitea_gitea:/data \
    -v "$RESTORE_DIR":/backup:ro \
    alpine:latest \
    tar xzf /backup/gitea_data.tar.gz -C /data

# Start database for restore
echo "Starting database for restore..."
docker-compose up -d db

# Wait for database to be ready
echo "Waiting for database to be ready..."
sleep 10

# Restore database
echo "Restoring database..."
docker-compose exec -T db psql -U ${POSTGRES_USER:-gitea} -d ${POSTGRES_DB:-gitea} < "$RESTORE_DIR/database.sql"

# Start all services
echo "Starting all services..."
docker-compose up -d

echo "Restore completed!"
EOF

chmod +x "$BACKUP_PATH/restore.sh"

# Create info file
cat > "$BACKUP_PATH/backup_info.txt" << EOF
Gitea Backup Information
========================
Backup Date: $(date)
Backup Location: $BACKUP_PATH
Gitea Version: $(docker-compose exec -T server gitea --version | head -1)
PostgreSQL Version: $(docker-compose exec -T db postgres --version)

Files included:
- database.sql: PostgreSQL database dump
- gitea_data.tar.gz: Gitea data volume
- postgres_data.tar.gz: PostgreSQL data volume
- docker-compose.yml: Docker compose configuration
- .env: Environment variables (if exists)
- restore.sh: Restore script

To restore this backup, run:
cd $BACKUP_PATH
./restore.sh
EOF

# Cleanup old backups (keep last 7 days)
echo "Cleaning up old backups..."
find "$BACKUP_DIR" -type d -name "gitea_backup_*" -mtime +7 -exec rm -rf {} + 2>/dev/null || true

echo "Backup completed successfully!"
echo "Backup saved to: $BACKUP_PATH"
echo "Backup size: $(du -sh "$BACKUP_PATH" | cut -f1)"