#!/bin/bash
# SkillDarbar API - Production Server Stop Script
# Graceful shutdown with proper cleanup

set -e

# ============================================================================
# CONFIGURATION
# ============================================================================
PORT=30015
GRACEFUL_WAIT=30             # Seconds to wait for graceful shutdown
FORCE_WAIT=5                 # Additional seconds before force kill

# ============================================================================
# PATHS
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_DIR="$SCRIPT_DIR/logs"
PID_FILE="$LOG_DIR/gunicorn.pid"

# ============================================================================
# FUNCTIONS
# ============================================================================
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

get_worker_pids() {
    local master_pid=$1
    pgrep -P "$master_pid" 2>/dev/null || true
}

stop_gracefully() {
    local pid=$1
    local name=$2
    
    if ! ps -p "$pid" > /dev/null 2>&1; then
        return 0
    fi
    
    log "Sending SIGTERM to $name (PID: $pid)..."
    kill -TERM "$pid" 2>/dev/null || true
    
    local wait_count=0
    while ps -p "$pid" > /dev/null 2>&1 && [ $wait_count -lt "$GRACEFUL_WAIT" ]; do
        if [ $((wait_count % 5)) -eq 0 ]; then
            log "  Waiting for $name to finish... (${wait_count}s/${GRACEFUL_WAIT}s)"
        fi
        sleep 1
        ((wait_count++))
    done
    
    if ps -p "$pid" > /dev/null 2>&1; then
        return 1  # Still running
    fi
    return 0  # Stopped
}

force_kill() {
    local pid=$1
    local name=$2
    
    if ! ps -p "$pid" > /dev/null 2>&1; then
        return 0
    fi
    
    log "Force killing $name (PID: $pid)..."
    kill -9 "$pid" 2>/dev/null || true
    sleep 1
    
    if ps -p "$pid" > /dev/null 2>&1; then
        return 1
    fi
    return 0
}

cleanup_orphans() {
    log "Checking for orphaned gunicorn processes..."
    
    local orphans=$(pgrep -f "gunicorn.*:$PORT" 2>/dev/null || true)
    if [ -n "$orphans" ]; then
        log "Found orphaned processes: $orphans"
        for pid in $orphans; do
            if ! stop_gracefully "$pid" "orphan"; then
                force_kill "$pid" "orphan"
            fi
        done
    fi
    
    # Also check by app name
    orphans=$(pgrep -f "gunicorn.*app:app" 2>/dev/null || true)
    if [ -n "$orphans" ]; then
        log "Found additional orphans by app name: $orphans"
        for pid in $orphans; do
            if ! stop_gracefully "$pid" "orphan"; then
                force_kill "$pid" "orphan"
            fi
        done
    fi
}

# ============================================================================
# MAIN
# ============================================================================

log "=========================================="
log "SkillDarbar API - Stopping Server"
log "=========================================="

stopped=false

# Method 1: Use PID file (preferred)
if [ -f "$PID_FILE" ]; then
    MASTER_PID=$(cat "$PID_FILE")
    
    if ps -p "$MASTER_PID" > /dev/null 2>&1; then
        log "Found master process (PID: $MASTER_PID)"
        
        # Get worker PIDs before stopping master
        WORKER_PIDS=$(get_worker_pids "$MASTER_PID")
        if [ -n "$WORKER_PIDS" ]; then
            log "Active workers: $WORKER_PIDS"
        fi
        
        # Try graceful shutdown
        if stop_gracefully "$MASTER_PID" "master"; then
            log "Master stopped gracefully"
            stopped=true
        else
            log "Graceful shutdown timed out, forcing..."
            
            # Force kill workers first
            for worker_pid in $WORKER_PIDS; do
                force_kill "$worker_pid" "worker"
            done
            
            # Then force kill master
            if force_kill "$MASTER_PID" "master"; then
                stopped=true
            else
                log "ERROR: Failed to stop master process!"
            fi
        fi
    else
        log "Stale PID file (process not running)"
    fi
    
    rm -f "$PID_FILE"
else
    log "No PID file found"
fi

# Method 2: Cleanup any orphaned processes
cleanup_orphans

# Verify port is free
sleep 1
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null 2>&1; then
    log "⚠️  WARNING: Port $PORT still in use!"
    log "Processes on port:"
    lsof -Pi :$PORT -sTCP:LISTEN
    exit 1
else
    log "✅ API stopped successfully. Port $PORT is free."
fi

# Optional: Show summary
if [ -f "$LOG_DIR/access.log" ]; then
    total_requests=$(wc -l < "$LOG_DIR/access.log" 2>/dev/null || echo 0)
    log "Session stats: ~$total_requests total requests logged"
fi

exit 0
