#!/bin/bash

set -euo pipefail

# 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() {
    echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
}

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

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

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

# Wait for service to be available
wait_for_service() {
    local host=$1
    local port=$2
    local service_name=$3
    local timeout=${4:-30}
    
    info "Waiting for $service_name to be available at $host:$port..."
    
    for i in $(seq 1 $timeout); do
        if nc -z "$host" "$port" 2>/dev/null; then
            log "$service_name is available!"
            return 0
        fi
        sleep 1
    done
    
    error "$service_name is not available after ${timeout}s"
    return 1
}

# Check database connectivity
check_database() {
    if [ -n "${OPENCRATES_DATABASE_URL:-}" ]; then
        info "Checking database connectivity..."
        
        # Extract host and port from DATABASE_URL
        # Format: postgresql://user:pass@host:port/db
        local db_info=$(echo "$OPENCRATES_DATABASE_URL" | sed -n 's|postgresql://[^@]*@\([^:]*\):\([^/]*\)/.*|\1 \2|p')
        if [ -n "$db_info" ]; then
            local db_host=$(echo $db_info | cut -d' ' -f1)
            local db_port=$(echo $db_info | cut -d' ' -f2)
            wait_for_service "$db_host" "$db_port" "PostgreSQL" 60
        fi
    fi
}

# Check Redis connectivity
check_redis() {
    if [ -n "${OPENCRATES_REDIS_URL:-}" ]; then
        info "Checking Redis connectivity..."
        
        # Extract host and port from REDIS_URL
        # Format: redis://host:port
        local redis_info=$(echo "$OPENCRATES_REDIS_URL" | sed -n 's|redis://\([^:]*\):\([^/]*\).*|\1 \2|p')
        if [ -n "$redis_info" ]; then
            local redis_host=$(echo $redis_info | cut -d' ' -f1)
            local redis_port=$(echo $redis_info | cut -d' ' -f2)
            wait_for_service "$redis_host" "$redis_port" "Redis" 30
        fi
    fi
}

# Initialize application
init_app() {
    log "Initializing OpenCrates..."
    
    # Create necessary directories
    mkdir -p /app/logs /app/storage /app/tmp
    
    # Set permissions
    chmod 755 /app/logs /app/storage /app/tmp
    
    # Check environment
    if [ -z "${OPENCRATES_OPENAI_API_KEY:-}" ]; then
        warn "OPENCRATES_OPENAI_API_KEY is not set. AI features will be disabled."
    fi
    
    # Check configuration
    if [ -f "/app/config/production.toml" ]; then
        info "Using configuration file: /app/config/production.toml"
    else
        warn "Configuration file not found, using defaults"
    fi
    
    log "OpenCrates initialization complete"
}

# Run database migrations
run_migrations() {
    if [ -n "${OPENCRATES_DATABASE_URL:-}" ] && [ "${OPENCRATES_RUN_MIGRATIONS:-true}" = "true" ]; then
        info "Running database migrations..."
        
        # Wait for database to be ready
        check_database
        
        # Run migrations (this would be implemented in the actual application)
        if command -v opencrates >/dev/null 2>&1; then
            opencrates migrate --non-interactive || {
                error "Failed to run migrations"
                exit 1
            }
        fi
        
        log "Database migrations completed"
    fi
}

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

# Graceful shutdown handler
shutdown() {
    log "Received shutdown signal, gracefully stopping OpenCrates..."
    
    # Send SIGTERM to the main process
    if [ -n "${APP_PID:-}" ]; then
        kill -TERM "$APP_PID" 2>/dev/null || true
        
        # Wait for graceful shutdown
        local timeout=30
        while [ $timeout -gt 0 ] && kill -0 "$APP_PID" 2>/dev/null; do
            sleep 1
            ((timeout--))
        done
        
        # Force kill if still running
        if kill -0 "$APP_PID" 2>/dev/null; then
            warn "Forcing shutdown..."
            kill -KILL "$APP_PID" 2>/dev/null || true
        fi
    fi
    
    log "OpenCrates stopped"
    exit 0
}

# Set up signal handlers
trap shutdown SIGTERM SIGINT

# Main execution
main() {
    log "Starting OpenCrates entrypoint..."
    
    # Parse command line arguments
    local command=${1:-serve}
    shift || true
    
    # Initialize
    init_app
    
    case "$command" in
        "serve")
            info "Starting OpenCrates server..."
            
            # Check dependencies
            check_database
            check_redis
            
            # Run migrations
            run_migrations
            
            # Start the application
            exec opencrates serve \
                --host "${OPENCRATES_HOST:-0.0.0.0}" \
                --port "${OPENCRATES_PORT:-8080}" \
                --config "${OPENCRATES_CONFIG_PATH:-/app/config/production.toml}" \
                "$@" &
            
            APP_PID=$!
            
            # Wait for app to start
            sleep 5
            
            # Perform health check
            if [ "${OPENCRATES_SKIP_HEALTH_CHECK:-false}" != "true" ]; then
                health_check
            fi
            
            log "OpenCrates is running (PID: $APP_PID)"
            
            # Wait for the application to finish
            wait $APP_PID
            ;;
            
        "migrate")
            info "Running database migrations..."
            check_database
            exec opencrates migrate "$@"
            ;;
            
        "create")
            info "Creating crate..."
            exec opencrates create "$@"
            ;;
            
        "test")
            info "Running tests..."
            exec opencrates test "$@"
            ;;
            
        "config")
            info "Managing configuration..."
            exec opencrates config "$@"
            ;;
            
        "shell"|"bash")
            info "Starting shell..."
            exec /bin/bash "$@"
            ;;
            
        "help"|"--help"|"-h")
            log "OpenCrates Docker Entrypoint"
            echo ""
            echo "Usage: $0 [COMMAND] [OPTIONS]"
            echo ""
            echo "Commands:"
            echo "  serve     Start the OpenCrates server (default)"
            echo "  migrate   Run database migrations"
            echo "  create    Create a new crate"
            echo "  test      Run test suite"
            echo "  config    Manage configuration"
            echo "  shell     Start a shell session"
            echo "  help      Show this help message"
            echo ""
            echo "Environment Variables:"
            echo "  OPENCRATES_OPENAI_API_KEY    OpenAI API key"
            echo "  OPENCRATES_DATABASE_URL      Database connection URL"
            echo "  OPENCRATES_REDIS_URL         Redis connection URL"
            echo "  OPENCRATES_HOST              Server host (default: 0.0.0.0)"
            echo "  OPENCRATES_PORT              Server port (default: 8080)"
            echo "  OPENCRATES_CONFIG_PATH       Configuration file path"
            echo "  OPENCRATES_RUN_MIGRATIONS    Run migrations on startup (default: true)"
            echo "  OPENCRATES_SKIP_HEALTH_CHECK Skip health check (default: false)"
            echo ""
            ;;
            
        *)
            info "Executing custom command: $command $*"
            exec "$command" "$@"
            ;;
    esac
}

# Run main function
main "$@" 