#!/bin/bash
#
# ThrillWiki Template-Based Deployment Script
# Optimized for VMs deployed from templates that already have basic setup
#

# Function to log messages with timestamp
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a /home/ubuntu/thrillwiki-deploy.log
}

# Function to check if a command exists
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# Function to wait for network connectivity
wait_for_network() {
    log "Waiting for network connectivity..."
    local max_attempts=20  # Reduced from 30 since template VMs boot faster
    local attempt=1
    while [ $attempt -le $max_attempts ]; do
        if curl -s --connect-timeout 5 https://github.com >/dev/null 2>&1; then
            log "Network connectivity confirmed"
            return 0
        fi
        log "Network attempt $attempt/$max_attempts failed, retrying in 5 seconds..."
        sleep 5  # Reduced from 10 since template VMs should have faster networking
        attempt=$((attempt + 1))
    done
    log "WARNING: Network connectivity check failed after $max_attempts attempts"
    return 1
}

# Function to update system packages (lighter since template should be recent)
update_system() {
    log "Updating system packages..."
    
    # Quick update - template should already have most packages
    sudo apt update || log "WARNING: apt update failed"
    
    # Only upgrade security packages to save time
    sudo apt list --upgradable 2>/dev/null | grep -q security && {
        log "Installing security updates..."
        sudo apt upgrade -y --with-new-pkgs -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" || log "WARNING: Security updates failed"
    } || log "No security updates needed"
}

# Function to setup Python environment with template optimizations
setup_python_env() {
    log "Setting up Python environment..."
    
    # Check if uv is already available (should be in template)
    export PATH="/home/ubuntu/.cargo/bin:$PATH"
    
    if command_exists uv; then
        log "Using existing uv installation from template"
        uv --version
    else
        log "Installing uv (not found in template)..."
        if wait_for_network; then
            curl -LsSf --connect-timeout 30 --retry 2 --retry-delay 5 https://astral.sh/uv/install.sh | sh
            export PATH="/home/ubuntu/.cargo/bin:$PATH"
        else
            log "WARNING: Network not available, falling back to pip"
        fi
    fi
    
    # Setup virtual environment
    if command_exists uv; then
        log "Creating virtual environment with uv..."
        if uv venv .venv && source .venv/bin/activate; then
            if uv sync; then
                log "Successfully set up environment with uv"
                return 0
            else
                log "uv sync failed, falling back to pip"
            fi
        else
            log "uv venv failed, falling back to pip"
        fi
    fi
    
    # Fallback to pip with venv
    log "Setting up environment with pip and venv"
    if python3 -m venv .venv && source .venv/bin/activate; then
        pip install --upgrade pip || log "WARNING: Failed to upgrade pip"
        
        # Try different dependency installation methods
        if [ -f pyproject.toml ]; then
            log "Installing dependencies from pyproject.toml"
            if pip install -e . || pip install .; then
                log "Successfully installed dependencies from pyproject.toml"
                return 0
            else
                log "Failed to install from pyproject.toml"
            fi
        fi
        
        if [ -f requirements.txt ]; then
            log "Installing dependencies from requirements.txt"
            if pip install -r requirements.txt; then
                log "Successfully installed dependencies from requirements.txt"
                return 0
            else
                log "Failed to install from requirements.txt"
            fi
        fi
        
        # Last resort: install common Django packages
        log "Installing basic Django packages as fallback"
        pip install django psycopg2-binary gunicorn || log "WARNING: Failed to install basic packages"
    else
        log "ERROR: Failed to create virtual environment"
        return 1
    fi
}

# Function to setup database (should already exist in template)
setup_database() {
    log "Setting up PostgreSQL database..."
    
    # Check if PostgreSQL is already running (should be in template)
    if sudo systemctl is-active --quiet postgresql; then
        log "PostgreSQL is already running"
    else
        log "Starting PostgreSQL service..."
        sudo systemctl start postgresql || {
            log "Failed to start PostgreSQL, trying alternative methods"
            sudo service postgresql start || {
                log "ERROR: Could not start PostgreSQL"
                return 1
            }
        }
    fi
    
    # Check if database and user already exist (may be in template)
    if sudo -u postgres psql -lqt | cut -d \| -f 1 | grep -qw thrillwiki_production; then
        log "Database 'thrillwiki_production' already exists"
    else
        log "Creating database 'thrillwiki_production'..."
        sudo -u postgres createdb thrillwiki_production || {
            log "ERROR: Failed to create database"
            return 1
        }
    fi
    
    # Create/update database user
    if sudo -u postgres psql -c "SELECT 1 FROM pg_user WHERE usename = 'ubuntu'" | grep -q 1; then
        log "Database user 'ubuntu' already exists"
    else
        sudo -u postgres createuser ubuntu || log "WARNING: Failed to create user (may already exist)"
    fi
    
    # Grant permissions
    sudo -u postgres psql -c "ALTER USER ubuntu WITH SUPERUSER;" || {
        log "WARNING: Failed to grant superuser privileges, trying alternative permissions"
        sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE thrillwiki_production TO ubuntu;" || log "WARNING: Failed to grant database privileges"
    }
    
    log "Database setup completed"
}

# Function to run Django commands with fallbacks
run_django_commands() {
    log "Running Django management commands..."
    
    # Ensure we're in the virtual environment
    if [ ! -d ".venv" ] || ! source .venv/bin/activate; then
        log "WARNING: Virtual environment not found or failed to activate"
        # Try to run without venv activation
    fi
    
    # Function to run a Django command with fallbacks
    run_django_cmd() {
        local cmd="$1"
        local description="$2"
        
        log "Running: $description"
        
        # Try uv run first
        if command_exists uv && uv run manage.py $cmd; then
            log "Successfully ran '$cmd' with uv"
            return 0
        fi
        
        # Try python in venv
        if python manage.py $cmd; then
            log "Successfully ran '$cmd' with python"
            return 0
        fi
        
        # Try python3
        if python3 manage.py $cmd; then
            log "Successfully ran '$cmd' with python3"
            return 0
        fi
        
        log "WARNING: Failed to run '$cmd'"
        return 1
    }
    
    # Run migrations
    run_django_cmd "migrate" "Database migrations" || log "WARNING: Database migration failed"
    
    # Collect static files
    run_django_cmd "collectstatic --noinput" "Static files collection" || log "WARNING: Static files collection failed"
    
    # Build Tailwind CSS (if available)
    if run_django_cmd "tailwind build" "Tailwind CSS build"; then
        log "Tailwind CSS built successfully"
    else
        log "Tailwind CSS build not available or failed - this is optional"
    fi
}

# Function to setup systemd services (may already exist in template)
setup_services() {
    log "Setting up systemd services..."
    
    # Check if systemd service files exist
    if [ -f scripts/systemd/thrillwiki.service ]; then
        log "Copying ThrillWiki systemd service..."
        sudo cp scripts/systemd/thrillwiki.service /etc/systemd/system/ || {
            log "Failed to copy thrillwiki.service, creating basic service"
            create_basic_service
        }
    else
        log "Systemd service file not found, creating basic service"
        create_basic_service
    fi
    
    # Copy webhook service if available
    if [ -f scripts/systemd/thrillwiki-webhook.service ]; then
        sudo cp scripts/systemd/thrillwiki-webhook.service /etc/systemd/system/ || {
            log "Failed to copy webhook service, skipping"
        }
    else
        log "Webhook service file not found, skipping"
    fi
    
    # Update service files with correct paths
    if [ -f /etc/systemd/system/thrillwiki.service ]; then
        sudo sed -i "s|/opt/thrillwiki|/home/ubuntu/thrillwiki|g" /etc/systemd/system/thrillwiki.service
        sudo sed -i "s|User=thrillwiki|User=ubuntu|g" /etc/systemd/system/thrillwiki.service
    fi
    
    if [ -f /etc/systemd/system/thrillwiki-webhook.service ]; then
        sudo sed -i "s|/opt/thrillwiki|/home/ubuntu/thrillwiki|g" /etc/systemd/system/thrillwiki-webhook.service
        sudo sed -i "s|User=thrillwiki|User=ubuntu|g" /etc/systemd/system/thrillwiki-webhook.service
    fi
    
    # Reload systemd and start services
    sudo systemctl daemon-reload
    
    # Enable and start main service
    if sudo systemctl enable thrillwiki 2>/dev/null; then
        log "ThrillWiki service enabled"
        if sudo systemctl start thrillwiki; then
            log "ThrillWiki service started successfully"
        else
            log "WARNING: Failed to start ThrillWiki service"
            sudo systemctl status thrillwiki --no-pager || true
        fi
    else
        log "WARNING: Failed to enable ThrillWiki service"
    fi
    
    # Try to start webhook service if it exists
    if [ -f /etc/systemd/system/thrillwiki-webhook.service ]; then
        sudo systemctl enable thrillwiki-webhook 2>/dev/null && sudo systemctl start thrillwiki-webhook || {
            log "WARNING: Failed to start webhook service"
        }
    fi
}

# Function to create a basic systemd service if none exists
create_basic_service() {
    log "Creating basic systemd service..."
    
    sudo tee /etc/systemd/system/thrillwiki.service > /dev/null << 'SERVICE_EOF'
[Unit]
Description=ThrillWiki Django Application
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=exec
User=ubuntu
Group=ubuntu
[AWS-SECRET-REMOVED]
[AWS-SECRET-REMOVED]/.venv/bin:/home/ubuntu/.cargo/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/ubuntu/thrillwiki/.venv/bin/python manage.py runserver 0.0.0.0:8000
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
SERVICE_EOF
    
    log "Basic systemd service created"
}

# Function to setup web server (may already be configured in template)
setup_webserver() {
    log "Setting up web server..."
    
    # Check if nginx is installed and running
    if command_exists nginx; then
        if ! sudo systemctl is-active --quiet nginx; then
            log "Starting nginx..."
            sudo systemctl start nginx || log "WARNING: Failed to start nginx"
        fi
        
        # Create basic nginx config if none exists
        if [ ! -f /etc/nginx/sites-available/thrillwiki ]; then
            log "Creating nginx configuration..."
            sudo tee /etc/nginx/sites-available/thrillwiki > /dev/null << 'NGINX_EOF'
server {
    listen 80;
    server_name _;
    
    location /static/ {
        alias /home/ubuntu/thrillwiki/staticfiles/;
    }
    
    location /media/ {
        alias /home/ubuntu/thrillwiki/media/;
    }
    
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
NGINX_EOF
            
            # Enable the site
            sudo ln -sf /etc/nginx/sites-available/thrillwiki /etc/nginx/sites-enabled/ || log "WARNING: Failed to enable nginx site"
            sudo nginx -t && sudo systemctl reload nginx || log "WARNING: nginx configuration test failed"
        else
            log "nginx configuration already exists"
        fi
    else
        log "nginx not installed, ThrillWiki will run on port 8000 directly"
    fi
}

# Main deployment function
main() {
    log "Starting ThrillWiki template-based deployment..."
    
    # Shorter wait time since template VMs boot faster
    log "Waiting for system to be ready..."
    sleep 10
    
    # Wait for network
    wait_for_network || log "WARNING: Network check failed, continuing anyway"
    
    # Clone or update repository
    log "Setting up ThrillWiki repository..."
    export GITHUB_TOKEN=$(cat /home/ubuntu/.github-token 2>/dev/null || echo "")
    
    # Get the GitHub repository from environment or parameter
    GITHUB_REPO="${1:-}"
    if [ -z "$GITHUB_REPO" ]; then
        log "ERROR: GitHub repository not specified"
        return 1
    fi
    
    if [ -d "/home/ubuntu/thrillwiki" ]; then
        log "ThrillWiki directory already exists, updating..."
        cd /home/ubuntu/thrillwiki
        git pull || log "WARNING: Failed to update repository"
    else
        if [ -n "$GITHUB_TOKEN" ]; then
            log "Cloning with GitHub token..."
            git clone https://$GITHUB_TOKEN@github.com/$GITHUB_REPO /home/ubuntu/thrillwiki || {
                log "Failed to clone with token, trying without..."
                git clone https://github.com/$GITHUB_REPO /home/ubuntu/thrillwiki || {
                    log "ERROR: Failed to clone repository"
                    return 1
                }
            }
        else
            log "Cloning without GitHub token..."
            git clone https://github.com/$GITHUB_REPO /home/ubuntu/thrillwiki || {
                log "ERROR: Failed to clone repository"
                return 1
            }
        fi
        cd /home/ubuntu/thrillwiki
    fi
    
    # Update system (lighter for template VMs)
    update_system
    
    # Setup Python environment
    setup_python_env || {
        log "ERROR: Failed to set up Python environment"
        return 1
    }
    
    # Setup environment file
    log "Setting up environment configuration..."
    if [ -f ***REMOVED***.example ]; then
        cp ***REMOVED***.example ***REMOVED*** || log "WARNING: Failed to copy ***REMOVED***.example"
    fi
    
    # Update ***REMOVED*** with production settings
    {
        echo "DEBUG=False"
        echo "DATABASE_URL=postgresql://ubuntu@localhost/thrillwiki_production"
        echo "ALLOWED_HOSTS=*"
        echo "STATIC_[AWS-SECRET-REMOVED]"
    } >> ***REMOVED***
    
    # Setup database
    setup_database || {
        log "ERROR: Database setup failed"
        return 1
    }
    
    # Run Django commands
    run_django_commands
    
    # Setup systemd services
    setup_services
    
    # Setup web server
    setup_webserver
    
    log "ThrillWiki template-based deployment completed!"
    log "Application should be available at http://$(hostname -I | awk '{print $1}'):8000"
    log "Logs are available at /home/ubuntu/thrillwiki-deploy.log"
}

# Run main function and capture any errors
main "$@" 2>&1 | tee -a /home/ubuntu/thrillwiki-deploy.log
exit_code=${PIPESTATUS[0]}

if [ $exit_code -eq 0 ]; then
    log "Template-based deployment completed successfully!"
else
    log "Template-based deployment completed with errors (exit code: $exit_code)"
fi

exit $exit_code
