#!/bin/bash

# PropTrader Pro Deployment Script
# This script automates the deployment process for production environments

set -e  # Exit on any error

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

# Configuration
APP_NAME="PropTrader Pro"
APP_DIR="/var/www/proptrader-pro"
BACKUP_DIR="/var/backups/proptrader-pro"
LOG_FILE="/var/log/deploy.log"

# Functions
log() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}

error() {
    echo -e "${RED}[ERROR] $1${NC}"
    echo "[ERROR] $1" >> $LOG_FILE
    exit 1
}

warning() {
    echo -e "${YELLOW}[WARNING] $1${NC}"
    echo "[WARNING] $1" >> $LOG_FILE
}

check_prerequisites() {
    log "Checking prerequisites..."
    
    # Check if running as root
    if [[ $EUID -eq 0 ]]; then
        error "This script should not be run as root"
    fi
    
    # Check if required commands exist
    local commands=("git" "composer" "npm" "php" "mysql" "redis-cli")
    for cmd in "${commands[@]}"; do
        if ! command -v $cmd &> /dev/null; then
            error "Command '$cmd' is not installed"
        fi
    done
    
    # Check if directories exist
    if [[ ! -d "$APP_DIR" ]]; then
        error "Application directory $APP_DIR does not exist"
    fi
    
    log "Prerequisites check completed"
}

backup_application() {
    log "Creating application backup..."
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local backup_file="$BACKUP_DIR/app_backup_$timestamp.tar.gz"
    
    mkdir -p "$BACKUP_DIR"
    
    # Create backup excluding node_modules and storage/logs
    tar -czf "$backup_file" \
        --exclude="$APP_DIR/node_modules" \
        --exclude="$APP_DIR/storage/logs" \
        --exclude="$APP_DIR/storage/framework/cache" \
        -C "$APP_DIR" .
    
    log "Application backup created: $backup_file"
}

backup_database() {
    log "Creating database backup..."
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local backup_file="$BACKUP_DIR/db_backup_$timestamp.sql.gz"
    
    mkdir -p "$BACKUP_DIR"
    
    # Get database credentials from .env
    local db_name=$(grep DB_DATABASE "$APP_DIR/.env" | cut -d '=' -f2)
    local db_user=$(grep DB_USERNAME "$APP_DIR/.env" | cut -d '=' -f2)
    local db_password=$(grep DB_PASSWORD "$APP_DIR/.env" | cut -d '=' -f2)
    
    # Create database backup
    mysqldump -u "$db_user" -p"$db_password" "$db_name" | gzip > "$backup_file"
    
    log "Database backup created: $backup_file"
}

update_code() {
    log "Updating application code..."
    
    cd "$APP_DIR"
    
    # Stash any local changes
    git stash
    
    # Pull latest changes
    git pull origin main
    
    log "Code updated successfully"
}

install_dependencies() {
    log "Installing dependencies..."
    
    cd "$APP_DIR"
    
    # Install PHP dependencies
    log "Installing PHP dependencies..."
    composer install --no-dev --optimize-autoloader --no-interaction
    
    # Install Node dependencies
    log "Installing Node dependencies..."
    npm ci --production
    npm run build
    
    log "Dependencies installed successfully"
}

run_migrations() {
    log "Running database migrations..."
    
    cd "$APP_DIR"
    
    # Run migrations
    php artisan migrate --force
    
    log "Migrations completed successfully"
}

clear_cache() {
    log "Clearing application cache..."
    
    cd "$APP_DIR"
    
    # Clear all caches
    php artisan cache:clear
    php artisan config:clear
    php artisan route:clear
    php artisan view:clear
    php artisan event:clear
    
    # Rebuild caches
    php artisan config:cache
    php artisan route:cache
    php artisan view:cache
    php artisan event:cache
    
    log "Cache cleared and rebuilt successfully"
}

set_permissions() {
    log "Setting file permissions..."
    
    # Set proper permissions
    sudo chown -R www-data:www-data "$APP_DIR"
    sudo chmod -R 755 "$APP_DIR"
    sudo chmod -R 777 "$APP_DIR/storage"
    sudo chmod -R 777 "$APP_DIR/bootstrap/cache"
    
    log "Permissions set successfully"
}

restart_services() {
    log "Restarting services..."
    
    # Restart PHP-FPM
    sudo systemctl restart php8.2-fpm
    
    # Restart Nginx
    sudo systemctl restart nginx
    
    # Restart Redis
    sudo systemctl restart redis-server
    
    # Restart Supervisor workers
    sudo supervisorctl restart all
    
    log "Services restarted successfully"
}

health_check() {
    log "Performing health check..."
    
    # Wait for services to start
    sleep 10
    
    # Check application health
    local health_check_url=$(grep APP_URL "$APP_DIR/.env" | cut -d '=' -f2)/health
    
    if curl -f -s "$health_check_url" > /dev/null; then
        log "Health check passed"
    else
        error "Health check failed"
    fi
    
    # Check database connection
    cd "$APP_DIR"
    if php artisan tinker --execute="DB::connection()->getPdo();" > /dev/null 2>&1; then
        log "Database connection check passed"
    else
        error "Database connection check failed"
    fi
    
    # Check Redis connection
    if redis-cli ping > /dev/null 2>&1; then
        log "Redis connection check passed"
    else
        error "Redis connection check failed"
    fi
}

cleanup_old_backups() {
    log "Cleaning up old backups..."
    
    # Keep only last 7 days of backups
    find "$BACKUP_DIR" -name "app_backup_*.tar.gz" -mtime +7 -delete
    find "$BACKUP_DIR" -name "db_backup_*.sql.gz" -mtime +7 -delete
    
    log "Old backups cleaned up"
}

notify_deployment() {
    log "Deployment notification..."
    
    # Send notification to Slack (if webhook is configured)
    if [[ -n "$SLACK_WEBHOOK_URL" ]]; then
        local message="Deployment completed successfully for $APP_NAME"
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"$message\"}" \
            "$SLACK_WEBHOOK_URL"
    fi
    
    # Send email notification (if configured)
    if [[ -n "$DEPLOYMENT_EMAIL" ]]; then
        echo "Deployment completed successfully for $APP_NAME" | \
            mail -s "Deployment Notification: $APP_NAME" "$DEPLOYMENT_EMAIL"
    fi
}

rollback() {
    log "Rolling back deployment..."
    
    # Get latest backup
    local latest_backup=$(ls -t "$BACKUP_DIR/app_backup_"*.tar.gz | head -1)
    
    if [[ -n "$latest_backup" ]]; then
        log "Restoring from backup: $latest_backup"
        
        # Extract backup
        tar -xzf "$latest_backup" -C "$APP_DIR"
        
        # Restart services
        restart_services
        
        log "Rollback completed"
    else
        error "No backup found for rollback"
    fi
}

main() {
    log "Starting deployment for $APP_NAME..."
    
    # Create log directory
    mkdir -p "$(dirname "$LOG_FILE")"
    
    # Check for rollback flag
    if [[ "$1" == "--rollback" ]]; then
        rollback
        exit 0
    fi
    
    # Run deployment steps
    check_prerequisites
    backup_application
    backup_database
    update_code
    install_dependencies
    run_migrations
    clear_cache
    set_permissions
    restart_services
    health_check
    cleanup_old_backups
    notify_deployment
    
    log "Deployment completed successfully!"
}

# Script usage
usage() {
    echo "Usage: $0 [--rollback]"
    echo "  --rollback    Rollback to previous deployment"
    exit 1
}

# Check for command line arguments
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
    usage
fi

# Run main function
main "$@"
