#!/bin/bash

# ThrillWiki VM Deployment Script
# This script runs on the Linux VM to deploy the latest code and restart the server

set -e  # Exit on any error

# Configuration
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOG_DIR="$PROJECT_DIR/logs"
BACKUP_DIR="$PROJECT_DIR/backups"
DEPLOY_LOG="$LOG_DIR/deploy.log"
SERVICE_NAME="thrillwiki"

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

# Logging function
log() {
    local message="[$(date +'%Y-%m-%d %H:%M:%S')] $1"
    echo -e "${BLUE}${message}${NC}"
    echo "$message" >> "$DEPLOY_LOG"
}

log_success() {
    local message="[$(date +'%Y-%m-%d %H:%M:%S')] ✓ $1"
    echo -e "${GREEN}${message}${NC}"
    echo "$message" >> "$DEPLOY_LOG"
}

log_warning() {
    local message="[$(date +'%Y-%m-%d %H:%M:%S')] ⚠ $1"
    echo -e "${YELLOW}${message}${NC}"
    echo "$message" >> "$DEPLOY_LOG"
}

log_error() {
    local message="[$(date +'%Y-%m-%d %H:%M:%S')] ✗ $1"
    echo -e "${RED}${message}${NC}"
    echo "$message" >> "$DEPLOY_LOG"
}

# Create necessary directories
create_directories() {
    log "Creating necessary directories..."
    mkdir -p "$LOG_DIR" "$BACKUP_DIR"
    log_success "Directories created"
}

# Backup current deployment
backup_current() {
    log "Creating backup of current deployment..."
    local timestamp=$(date +'%Y%m%d_%H%M%S')
    local backup_path="$BACKUP_DIR/backup_$timestamp"
    
    # Create backup of current code
    if [ -d "$PROJECT_DIR/.git" ]; then
        local current_commit=$(git -C "$PROJECT_DIR" rev-parse HEAD)
        echo "$current_commit" > "$backup_path.commit"
        log_success "Backup created with commit: ${current_commit:0:8}"
    else
        log_warning "Not a git repository, skipping backup"
    fi
}

# Stop the service
stop_service() {
    log "Stopping ThrillWiki service..."
    
    # Stop systemd service if it exists
    if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
        sudo systemctl stop "$SERVICE_NAME"
        log_success "Systemd service stopped"
    else
        log "Systemd service not running"
    fi
    
    # Kill any remaining Django processes on port 8000
    if lsof -ti :8000 >/dev/null 2>&1; then
        log "Stopping processes on port 8000..."
        lsof -ti :8000 | xargs kill -9 2>/dev/null || true
        log_success "Port 8000 processes stopped"
    fi
    
    # Clean up Python cache
    log "Cleaning Python cache..."
    find "$PROJECT_DIR" -type d -name "__pycache__" -exec rm -r {} + 2>/dev/null || true
    log_success "Python cache cleaned"
}

# Update code from git
update_code() {
    log "Updating code from git repository..."
    
    cd "$PROJECT_DIR"
    
    # Fetch latest changes
    git fetch origin
    log "Fetched latest changes"
    
    # Get current and new commit info
    local old_commit=$(git rev-parse HEAD)
    local new_commit=$(git rev-parse origin/main)
    
    if [ "$old_commit" = "$new_commit" ]; then
        log_warning "No new commits to deploy"
        return 0
    fi
    
    log "Updating from ${old_commit:0:8} to ${new_commit:0:8}"
    
    # Pull latest changes
    git reset --hard origin/main
    log_success "Code updated successfully"
    
    # Show what changed
    log "Changes in this deployment:"
    git log --oneline "$old_commit..$new_commit" || true
}

# Install/update dependencies
update_dependencies() {
    log "Updating dependencies..."
    
    cd "$PROJECT_DIR"
    
    # Check if UV is installed
    if ! command -v uv &> /dev/null; then
        log_error "UV is not installed. Installing UV..."
        curl -LsSf https://astral.sh/uv/install.sh | sh
        source $HOME/.cargo/env
    fi
    
    # Sync dependencies
    uv sync --no-dev || {
        log_error "Failed to sync dependencies"
        return 1
    }
    
    log_success "Dependencies updated"
}

# Run database migrations
run_migrations() {
    log "Running database migrations..."
    
    cd "$PROJECT_DIR"
    
    # Check for pending migrations
    if uv run manage.py showmigrations --plan | grep -q "\[ \]"; then
        log "Applying database migrations..."
        uv run manage.py migrate || {
            log_error "Database migrations failed"
            return 1
        }
        log_success "Database migrations completed"
    else
        log "No pending migrations"
    fi
}

# Collect static files
collect_static() {
    log "Collecting static files..."
    
    cd "$PROJECT_DIR"
    
    uv run manage.py collectstatic --noinput || {
        log_warning "Static file collection failed, continuing..."
    }
    
    log_success "Static files collected"
}

# Start the service
start_service() {
    log "Starting ThrillWiki service..."
    
    cd "$PROJECT_DIR"
    
    # Start systemd service if it exists
    if systemctl list-unit-files | grep -q "^$SERVICE_NAME.service"; then
        sudo systemctl start "$SERVICE_NAME"
        sudo systemctl enable "$SERVICE_NAME"
        
        # Wait for service to start
        sleep 5
        
        if systemctl is-active --quiet "$SERVICE_NAME"; then
            log_success "Systemd service started successfully"
        else
            log_error "Systemd service failed to start"
            return 1
        fi
    else
        log_warning "Systemd service not found, starting manually..."
        
        # Start server in background
        nohup ./scripts/ci-start.sh > "$LOG_DIR/server.log" 2>&1 &
        local server_pid=$!
        
        # Wait for server to start
        sleep 5
        
        if kill -0 $server_pid 2>/dev/null; then
            echo $server_pid > "$LOG_DIR/server.pid"
            log_success "Server started manually with PID: $server_pid"
        else
            log_error "Failed to start server manually"
            return 1
        fi
    fi
}

# Health check
health_check() {
    log "Performing health check..."
    
    local max_attempts=30
    local attempt=1
    
    while [ $attempt -le $max_attempts ]; do
        if curl -f -s http://localhost:8000/health >/dev/null 2>&1; then
            log_success "Health check passed"
            return 0
        fi
        
        log "Health check attempt $attempt/$max_attempts failed, retrying..."
        sleep 2
        ((attempt++))
    done
    
    log_error "Health check failed after $max_attempts attempts"
    return 1
}

# Cleanup old backups
cleanup_backups() {
    log "Cleaning up old backups..."
    
    # Keep only the last 10 backups
    cd "$BACKUP_DIR"
    ls -t backup_*.commit 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null || true
    
    log_success "Old backups cleaned up"
}

# Rollback function
rollback() {
    log_error "Deployment failed, attempting rollback..."
    
    local latest_backup=$(ls -t "$BACKUP_DIR"/backup_*.commit 2>/dev/null | head -n 1)
    
    if [ -n "$latest_backup" ]; then
        local backup_commit=$(cat "$latest_backup")
        log "Rolling back to commit: ${backup_commit:0:8}"
        
        cd "$PROJECT_DIR"
        git reset --hard "$backup_commit"
        
        # Restart service
        stop_service
        start_service
        
        if health_check; then
            log_success "Rollback completed successfully"
        else
            log_error "Rollback failed - manual intervention required"
        fi
    else
        log_error "No backup found for rollback"
    fi
}

# Main deployment function
deploy() {
    log "=== ThrillWiki Deployment Started ==="
    log "Timestamp: $(date)"
    log "User: $(whoami)"
    log "Host: $(hostname)"
    
    # Trap errors for rollback
    trap rollback ERR
    
    create_directories
    backup_current
    stop_service
    update_code
    update_dependencies
    run_migrations
    collect_static
    start_service
    health_check
    cleanup_backups
    
    # Remove error trap
    trap - ERR
    
    log_success "=== Deployment Completed Successfully ==="
    log "Server is now running the latest code"
    log "Check logs at: $LOG_DIR/"
}

# Script execution
case "${1:-deploy}" in
    deploy)
        deploy
        ;;
    stop)
        stop_service
        ;;
    start)
        start_service
        ;;
    restart)
        stop_service
        start_service
        health_check
        ;;
    status)
        if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
            echo "Service is running"
        elif [ -f "$LOG_DIR/server.pid" ] && kill -0 "$(cat "$LOG_DIR/server.pid")" 2>/dev/null; then
            echo "Server is running manually"
        else
            echo "Service is not running"
        fi
        ;;
    health)
        health_check
        ;;
    *)
        echo "Usage: $0 {deploy|stop|start|restart|status|health}"
        exit 1
        ;;
esac