#!/bin/bash

# Vision Videoke Apache Deployment Script
# Deploys or updates Vision Videoke application in Apache subdirectory

set -e

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

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

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

warn() {
    echo -e "${YELLOW}[WARNING] $1${NC}"
}

info() {
    echo -e "${BLUE}[INFO] $1${NC}"
}

# Configuration
SUBDIRECTORY=${1:-music}
APP_DIR="/var/www/html/$SUBDIRECTORY"
SOURCE_DIR=${2:-"/tmp/visionvideoke-source"}
BACKUP_DIR="/var/backups/visionvideoke"
LOG_FILE="/var/log/visionvideoke/deploy.log"

# Detect Apache service and user
if systemctl list-units --type=service | grep -q "httpd.service"; then
    APACHE_SERVICE="httpd"
    APACHE_USER="apache"
elif systemctl list-units --type=service | grep -q "apache2.service"; then
    APACHE_SERVICE="apache2"
    APACHE_USER="www-data"
else
    error "Apache service not found"
fi

# Function to check prerequisites
check_prerequisites() {
    log "Checking prerequisites..."
    
    # Check if application directory exists
    if [ ! -d "$APP_DIR" ]; then
        error "Application directory not found: $APP_DIR. Please run the installer first."
    fi
    
    # Check if Node.js is installed
    if ! command -v node &> /dev/null; then
        error "Node.js is not installed"
    fi
    
    # Check if PM2 is installed
    if ! command -v pm2 &> /dev/null; then
        error "PM2 is not installed"
    fi
    
    # Check if Apache is running
    if ! systemctl is-active --quiet $APACHE_SERVICE; then
        error "Apache is not running"
    fi
    
    # Create log directory
    sudo mkdir -p $(dirname $LOG_FILE)
    sudo chown ec2-user:ec2-user $(dirname $LOG_FILE)
    
    log "Prerequisites check completed"
}

# Function to create backup
create_backup() {
    log "Creating backup..."
    
    if [ -d "$APP_DIR" ] && [ "$(ls -A $APP_DIR)" ]; then
        BACKUP_NAME="backup-$SUBDIRECTORY-$(date +%Y%m%d-%H%M%S).tar.gz"
        sudo mkdir -p $BACKUP_DIR
        
        tar -czf "$BACKUP_DIR/$BACKUP_NAME" -C "$APP_DIR" . \
            --exclude=node_modules \
            --exclude=.git \
            --exclude=temp \
            --exclude=logs \
            --exclude=uploads 2>/dev/null || true
        
        log "Backup created: $BACKUP_NAME"
        
        # Keep only last 10 backups
        cd $BACKUP_DIR
        ls -t backup-$SUBDIRECTORY-*.tar.gz | tail -n +11 | xargs rm -f 2>/dev/null || true
    else
        log "No existing application to backup"
    fi
}

# Function to stop application
stop_application() {
    log "Stopping application..."
    
    # Stop PM2 process
    pm2 stop "visionvideoke-$SUBDIRECTORY" 2>/dev/null || true
    
    log "Application stopped"
}

# Function to deploy application
deploy_application() {
    log "Deploying application from: $SOURCE_DIR"
    
    if [ ! -d "$SOURCE_DIR" ]; then
        error "Source directory not found: $SOURCE_DIR"
    fi
    
    # Copy application files (excluding certain directories)
    log "Copying application files..."
    rsync -av --delete "$SOURCE_DIR/" "$APP_DIR/" \
        --exclude=node_modules \
        --exclude=.git \
        --exclude=dist \
        --exclude=build \
        --exclude=.env.local \
        --exclude=.env.production \
        --exclude=uploads \
        --exclude=temp \
        --exclude=logs
    
    # Preserve uploads and temp directories
    sudo mkdir -p $APP_DIR/{uploads,temp,logs}
    
    # Set proper ownership
    sudo chown -R $APACHE_USER:$APACHE_USER $APP_DIR
    
    # Preserve environment file if it exists
    if [ -f "$APP_DIR/.env" ]; then
        log "Preserving existing environment configuration"
    else
        warn "No environment file found. You may need to configure $APP_DIR/.env"
    fi
    
    log "Application files deployed"
}

# Function to configure for subdirectory deployment
configure_subdirectory() {
    log "Configuring application for subdirectory deployment..."
    
    cd $APP_DIR
    
    # Update package.json if it exists
    if [ -f "package.json" ]; then
        # Add subdirectory-specific scripts
        node -e "
        const fs = require('fs');
        const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
        
        pkg.scripts = pkg.scripts || {};
        pkg.scripts['build:subdirectory'] = 'REACT_APP_BASE_PATH=/$SUBDIRECTORY npm run build';
        pkg.scripts['start:production'] = 'NODE_ENV=production node server.js';
        
        fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
        " 2>/dev/null || warn "Could not update package.json scripts"
    fi
    
    # Update Vite config for subdirectory if it exists
    if [ -f "vite.config.js" ]; then
        # Backup original config
        cp vite.config.js vite.config.js.backup
        
        # Update base path for subdirectory
        sed -i "s|base: '/'|base: '/$SUBDIRECTORY/'|g" vite.config.js 2>/dev/null || true
        sed -i "s|base: '/.*/'|base: '/$SUBDIRECTORY/'|g" vite.config.js 2>/dev/null || true
    fi
    
    # Create or update environment variables for subdirectory
    if [ -f ".env" ]; then
        # Update existing environment file
        sed -i "s|REACT_APP_BASE_PATH=.*|REACT_APP_BASE_PATH=/$SUBDIRECTORY|g" .env
        sed -i "s|SUBDIRECTORY_PATH=.*|SUBDIRECTORY_PATH=/$SUBDIRECTORY|g" .env
        sed -i "s|API_BASE_PATH=.*|API_BASE_PATH=/$SUBDIRECTORY/api|g" .env
        sed -i "s|PUBLIC_PATH=.*|PUBLIC_PATH=/$SUBDIRECTORY|g" .env
        
        # Add subdirectory variables if they don't exist
        grep -q "REACT_APP_BASE_PATH" .env || echo "REACT_APP_BASE_PATH=/$SUBDIRECTORY" >> .env
        grep -q "SUBDIRECTORY_PATH" .env || echo "SUBDIRECTORY_PATH=/$SUBDIRECTORY" >> .env
        grep -q "API_BASE_PATH" .env || echo "API_BASE_PATH=/$SUBDIRECTORY/api" >> .env
        grep -q "PUBLIC_PATH" .env || echo "PUBLIC_PATH=/$SUBDIRECTORY" >> .env
    fi
    
    log "Subdirectory configuration completed"
}

# Function to install dependencies
install_dependencies() {
    log "Installing dependencies..."
    
    cd $APP_DIR
    
    # Install Node.js dependencies
    sudo -u $APACHE_USER npm ci --production=false 2>&1 | tee -a $LOG_FILE
    
    log "Dependencies installed"
}

# Function to build application
build_application() {
    log "Building application..."
    
    cd $APP_DIR
    
    # Set environment variables for build
    export REACT_APP_BASE_PATH="/$SUBDIRECTORY"
    export PUBLIC_URL="/$SUBDIRECTORY"
    
    # Build the application
    if [ -f "package.json" ] && grep -q '"build"' package.json; then
        sudo -u $APACHE_USER npm run build 2>&1 | tee -a $LOG_FILE
        
        # Verify build output
        if [ -d "dist" ] || [ -d "build" ]; then
            log "Application built successfully"
            
            # Copy build files to root if needed
            if [ -d "build" ] && [ ! -d "dist" ]; then
                sudo -u $APACHE_USER cp -r build dist
            fi
        else
            warn "Build directory not found. Application may not have built correctly."
        fi
    else
        warn "No build script found in package.json"
    fi
}

# Function to update PM2 configuration
update_pm2_config() {
    log "Updating PM2 configuration..."
    
    cd $APP_DIR
    
    # Create or update ecosystem.config.js
    cat > ecosystem.config.js <<EOF
module.exports = {
  apps: [{
    name: 'visionvideoke-$SUBDIRECTORY',
    script: 'server.js',
    cwd: '$APP_DIR',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      PORT: 3001,
      SUBDIRECTORY_PATH: '/$SUBDIRECTORY',
      API_BASE_PATH: '/$SUBDIRECTORY/api',
      PUBLIC_PATH: '/$SUBDIRECTORY'
    },
    error_file: '/var/log/visionvideoke/error.log',
    out_file: '/var/log/visionvideoke/out.log',
    log_file: '/var/log/visionvideoke/combined.log',
    time: true,
    max_memory_restart: '1G',
    node_args: '--max-old-space-size=1024',
    watch: false,
    ignore_watch: ['node_modules', 'logs', 'uploads', 'temp'],
    restart_delay: 4000,
    max_restarts: 10,
    min_uptime: '10s',
    env_file: '$APP_DIR/.env'
  }]
};
EOF
    
    sudo chown $APACHE_USER:$APACHE_USER ecosystem.config.js
    
    log "PM2 configuration updated"
}

# Function to start application
start_application() {
    log "Starting application..."
    
    cd $APP_DIR
    
    # Delete existing PM2 process if it exists
    pm2 delete "visionvideoke-$SUBDIRECTORY" 2>/dev/null || true
    
    # Start application with PM2
    sudo -u $APACHE_USER pm2 start ecosystem.config.js
    
    # Save PM2 configuration
    sudo -u $APACHE_USER pm2 save
    
    # Wait for application to start
    sleep 5
    
    # Check if application is running
    if pm2 list | grep -q "visionvideoke-$SUBDIRECTORY.*online"; then
        log "Application started successfully"
    else
        error "Failed to start application"
    fi
}

# Function to test deployment
test_deployment() {
    log "Testing deployment..."
    
    # Test backend health
    local max_attempts=30
    local attempt=1
    
    while [ $attempt -le $max_attempts ]; do
        if curl -f -s http://localhost:3001/health > /dev/null 2>&1; then
            log "Backend health check passed"
            break
        else
            if [ $attempt -eq $max_attempts ]; then
                error "Backend health check failed after $max_attempts attempts"
            fi
            log "Health check attempt $attempt/$max_attempts failed, retrying..."
            sleep 2
            ((attempt++))
        fi
    done
    
    # Test Apache configuration
    if sudo $APACHE_SERVICE -t > /dev/null 2>&1; then
        log "Apache configuration is valid"
        sudo systemctl reload $APACHE_SERVICE
    else
        error "Apache configuration test failed"
    fi
    
    # Test frontend access (if domain is configured)
    if [ ! -z "$DOMAIN_NAME" ]; then
        if curl -f -s "http://$DOMAIN_NAME/$SUBDIRECTORY" > /dev/null 2>&1; then
            log "Frontend access test passed"
        else
            warn "Frontend access test failed (may be due to DNS or configuration)"
        fi
    fi
    
    log "Deployment testing completed"
}

# Function to cleanup
cleanup() {
    log "Cleaning up..."
    
    cd $APP_DIR
    
    # Clean npm cache
    sudo -u $APACHE_USER npm cache clean --force 2>/dev/null || true
    
    # Remove temporary files
    rm -rf /tmp/visionvideoke-* 2>/dev/null || true
    
    # Clean old log files (keep last 7 days)
    find /var/log/visionvideoke -name "*.log" -mtime +7 -delete 2>/dev/null || true
    
    log "Cleanup completed"
}

# Function to show deployment status
show_status() {
    log "Deployment Status:"
    echo ""
    
    # PM2 status
    echo "PM2 Status:"
    pm2 list | grep "visionvideoke-$SUBDIRECTORY" || echo "Application not found in PM2"
    echo ""
    
    # Apache status
    echo "Apache Status:"
    sudo systemctl status $APACHE_SERVICE --no-pager -l | head -5
    echo ""
    
    # Application directory
    echo "Application Directory:"
    ls -la $APP_DIR | head -10
    echo ""
    
    # Recent logs
    echo "Recent Application Logs:"
    tail -n 5 /var/log/visionvideoke/combined.log 2>/dev/null || echo "No logs available"
    echo ""
    
    # Access URLs
    echo "Access Information:"
    echo "- Application: http://$(hostname -f)/$SUBDIRECTORY"
    echo "- API: http://$(hostname -f)/$SUBDIRECTORY/api"
    echo "- Health: http://$(hostname -f)/$SUBDIRECTORY/health"
    echo "- Backend: http://localhost:3001/health"
}

# Main deployment function
main() {
    local subdirectory=${1:-music}
    local source_path=${2:-"/tmp/visionvideoke-source"}
    
    log "Starting Vision Videoke deployment to /$subdirectory..."
    
    # Update global variables
    SUBDIRECTORY=$subdirectory
    APP_DIR="/var/www/html/$SUBDIRECTORY"
    
    # Check prerequisites
    check_prerequisites
    
    # Create backup
    create_backup
    
    # Stop application
    stop_application
    
    # Deploy application
    deploy_application
    
    # Configure for subdirectory
    configure_subdirectory
    
    # Install dependencies
    install_dependencies
    
    # Build application
    build_application
    
    # Update PM2 configuration
    update_pm2_config
    
    # Start application
    start_application
    
    # Test deployment
    test_deployment
    
    # Cleanup
    cleanup
    
    # Show status
    show_status
    
    log "Deployment completed successfully!"
    log ""
    log "Application is running at:"
    log "- Subdirectory: /$SUBDIRECTORY"
    log "- Backend Port: 3001"
    log "- Application Directory: $APP_DIR"
    log ""
    log "Management commands:"
    log "- pm2 status                    # Check application status"
    log "- pm2 logs visionvideoke-$SUBDIRECTORY  # View application logs"
    log "- pm2 restart visionvideoke-$SUBDIRECTORY # Restart application"
    log "- sudo systemctl reload $APACHE_SERVICE # Reload Apache"
}

# Script usage
usage() {
    echo "Usage: $0 [subdirectory] [source_path]"
    echo ""
    echo "Parameters:"
    echo "  subdirectory  Subdirectory name (default: music)"
    echo "  source_path   Path to application source (default: /tmp/visionvideoke-source)"
    echo ""
    echo "Examples:"
    echo "  $0 music /tmp/visionvideoke-source"
    echo "  $0 videoke /home/user/visionvideoke-app"
    echo ""
    echo "The application will be deployed to /var/www/html/[subdirectory]"
}

# Handle command line arguments
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
    usage
    exit 0
fi

# Run main function with all arguments
main "$@"

