#!/bin/bash

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

# Configuration
BACKEND_PORT=8000
FRONTEND_PORT=3000
BACKEND_DIR="backend"
FRONTEND_DIR="frontend"
LOG_DIR="logs"

# Create logs directory if it doesn't exist
mkdir -p "$LOG_DIR"

# Log files
BACKEND_LOG="$LOG_DIR/backend.log"
FRONTEND_LOG="$LOG_DIR/frontend.log"

# Function to print colored messages
print_info() {
    echo -e "${BLUE}ℹ${NC} $1"
}

print_success() {
    echo -e "${GREEN}✓${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}⚠${NC} $1"
}

print_error() {
    echo -e "${RED}✗${NC} $1"
}

# Function to kill background processes on exit
cleanup() {
    echo ""
    print_info "Stopping all services..."
    
    # Kill all background jobs
    jobs -p | xargs -r kill 2>/dev/null
    
    # Wait a moment for graceful shutdown
    sleep 1
    
    # Force kill if still running
    jobs -p | xargs -r kill -9 2>/dev/null
    
    print_success "All services stopped"
    exit 0
}

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

# Function to check prerequisites
check_prerequisites() {
    print_info "Checking prerequisites..."
    
    local missing_deps=()
    
    # Check for required commands
    if ! command_exists "uv"; then
        missing_deps+=("uv (Python package manager)")
    fi
    
    if ! command_exists "node"; then
        missing_deps+=("node (Node.js)")
    fi
    
    if ! command_exists "pnpm"; then
        missing_deps+=("pnpm (Node package manager)")
    fi
    
    if ! command_exists "curl"; then
        missing_deps+=("curl")
    fi
    
    if ! command_exists "lsof"; then
        print_warning "lsof not found, port checking will be limited"
    fi
    
    if [ ${#missing_deps[@]} -gt 0 ]; then
        print_error "Missing required dependencies:"
        for dep in "${missing_deps[@]}"; do
            echo "  - $dep"
        done
        echo ""
        echo "Please install missing dependencies and try again."
        exit 1
    fi
    
    print_success "All prerequisites satisfied"
}

# Function to check and free port
check_and_free_port() {
    local port=$1
    local name=$2
    
    if ! command_exists "lsof"; then
        return 0
    fi
    
    # Check if port is in use
    if lsof -i :$port >/dev/null 2>&1; then
        print_warning "Port $port ($name) is in use"
        
        # Get PIDs using the port
        local pids=$(lsof -ti :$port)
        
        # Ask user for confirmation
        read -p "Kill processes on port $port? (y/N): " -n 1 -r
        echo
        
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            for pid in $pids; do
                print_info "Killing process $pid on port $port..."
                kill -9 $pid 2>/dev/null
            done
            sleep 1
            
            # Verify if port is still in use
            if lsof -i :$port >/dev/null 2>&1; then
                print_error "Failed to free port $port. Please free it manually."
                exit 1
            else
                print_success "Port $port freed successfully"
            fi
        else
            print_error "Cannot start service on port $port. Exiting."
            exit 1
        fi
    fi
}

# Function to check if directory exists
check_directory() {
    local dir=$1
    local name=$2
    
    if [ ! -d "$dir" ]; then
        print_error "$name directory not found: $dir"
        exit 1
    fi
}

# Function to start backend
start_backend() {
    print_info "Starting Backend on port $BACKEND_PORT..."
    
    cd "$BACKEND_DIR" || exit 1
    
    # Check if .env file exists
    if [ ! -f ".env" ]; then
        print_warning "Backend .env file not found. Using default configuration."
    fi
    
    # Set PYTHONPATH
    export PYTHONPATH=$PYTHONPATH:$(pwd)
    
    # Start backend with logging
    uv run uvicorn src.main:app --reload --port $BACKEND_PORT > "../$BACKEND_LOG" 2>&1 &
    BACKEND_PID=$!
    
    cd ..
    
    print_info "Backend PID: $BACKEND_PID (logs: $BACKEND_LOG)"
}

# Function to wait for backend to be ready
wait_for_backend() {
    print_info "Waiting for backend to be ready..."
    
    local max_retries=30
    local retry_count=0
    local health_url="http://localhost:$BACKEND_PORT/health"
    
    while [ $retry_count -lt $max_retries ]; do
        if curl -s "$health_url" > /dev/null 2>&1; then
            print_success "Backend is ready!"
            return 0
        fi
        
        # Check if backend process is still running
        if ! kill -0 $BACKEND_PID 2>/dev/null; then
            print_error "Backend process died. Check logs: $BACKEND_LOG"
            tail -n 20 "$BACKEND_LOG"
            return 1
        fi
        
        retry_count=$((retry_count + 1))
        
        # Show progress
        printf "\r  Attempt %d/%d..." $retry_count $max_retries
        
        sleep 1
    done
    
    echo ""
    print_error "Backend failed to start after $max_retries seconds"
    print_info "Last 20 lines of backend log:"
    tail -n 20 "$BACKEND_LOG"
    return 1
}

# Function to start frontend
start_frontend() {
    print_info "Starting Frontend on port $FRONTEND_PORT..."
    
    cd "$FRONTEND_DIR" || exit 1
    
    # Check if node_modules exists
    if [ ! -d "node_modules" ]; then
        print_warning "node_modules not found. Running pnpm install..."
        pnpm install
    fi
    
    # Start frontend with logging
    pnpm dev > "../$FRONTEND_LOG" 2>&1 &
    FRONTEND_PID=$!
    
    cd ..
    
    print_info "Frontend PID: $FRONTEND_PID (logs: $FRONTEND_LOG)"
}

# Function to wait for frontend to be ready
wait_for_frontend() {
    print_info "Waiting for frontend to be ready..."
    
    local max_retries=30
    local retry_count=0
    
    while [ $retry_count -lt $max_retries ]; do
        if curl -s "http://localhost:$FRONTEND_PORT" > /dev/null 2>&1; then
            print_success "Frontend is ready!"
            return 0
        fi
        
        # Check if frontend process is still running
        if ! kill -0 $FRONTEND_PID 2>/dev/null; then
            print_error "Frontend process died. Check logs: $FRONTEND_LOG"
            tail -n 20 "$FRONTEND_LOG"
            return 1
        fi
        
        retry_count=$((retry_count + 1))
        
        # Show progress
        printf "\r  Attempt %d/%d..." $retry_count $max_retries
        
        sleep 1
    done
    
    echo ""
    print_error "Frontend failed to start after $max_retries seconds"
    print_info "Last 20 lines of frontend log:"
    tail -n 20 "$FRONTEND_LOG"
    return 1
}

# Function to display service information
display_info() {
    echo ""
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    print_success "All services started successfully!"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    echo "  📡 Backend API:      http://localhost:$BACKEND_PORT"
    echo "  📚 API Docs:         http://localhost:$BACKEND_PORT/docs"
    echo "  📖 ReDoc:            http://localhost:$BACKEND_PORT/redoc"
    echo "  🏥 Health Check:     http://localhost:$BACKEND_PORT/health"
    echo "  📊 Metrics:          http://localhost:$BACKEND_PORT/metrics"
    echo ""
    echo "  🎨 Frontend:         http://localhost:$FRONTEND_PORT"
    echo ""
    echo "  📝 Backend Logs:     $BACKEND_LOG"
    echo "  📝 Frontend Logs:    $FRONTEND_LOG"
    echo ""
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
    print_info "Press Ctrl+C to stop all services"
    echo ""
}

# Main execution
main() {
    echo ""
    echo "╔═══════════════════════════════════════════════════════╗"
    echo "║         Pixel Development Environment Startup         ║"
    echo "╚═══════════════════════════════════════════════════════╝"
    echo ""
    
    # Trap SIGINT (Ctrl+C) and call cleanup
    trap cleanup SIGINT SIGTERM
    
    # Check prerequisites
    check_prerequisites
    
    # Check directories
    check_directory "$BACKEND_DIR" "Backend"
    check_directory "$FRONTEND_DIR" "Frontend"
    
    # Check and free ports
    check_and_free_port $BACKEND_PORT "Backend"
    check_and_free_port $FRONTEND_PORT "Frontend"
    
    # Start backend
    start_backend
    
    # Wait for backend to be ready
    if ! wait_for_backend; then
        cleanup
        exit 1
    fi
    
    # Start frontend
    start_frontend
    
    # Wait for frontend to be ready
    if ! wait_for_frontend; then
        cleanup
        exit 1
    fi
    
    # Display service information
    display_info
    
    # Wait for processes
    wait
}

# Run main function
main
