#!/bin/bash
# MCP-ZERO Project Management CLI
# Enterprise-grade management script for the MCP-ZERO infrastructure

set -e

# Color definitions
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m' # No Color

# Base directory detection
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="${BASE_DIR}/config"
LOG_DIR="${BASE_DIR}/logs"

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

# Component paths
DASHBOARD_UI_DIR="${BASE_DIR}/src/dashboard/ui"
API_DIR="${BASE_DIR}/src/api"
RPC_DIR="${BASE_DIR}/src/rpc"
MONITORING_DIR="${BASE_DIR}/src/monitoring"
SDK_DIR="${BASE_DIR}/sdk"

# Environment variables and defaults
export MCP_DASHBOARD_PORT=${MCP_DASHBOARD_PORT:-8080}
export MCP_API_PORT=${MCP_API_PORT:-8081}
export MCP_RPC_PORT=${MCP_RPC_PORT:-9000}
export MCP_MONITORING_ENDPOINT=${MCP_MONITORING_ENDPOINT:-"http://localhost:8081/api/monitoring"}

# Log file for operations
OPERATIONS_LOG="${LOG_DIR}/mcp_operations.log"

# Function to log messages
log_message() {
  local level=$1
  local message=$2
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
  echo -e "${timestamp} [${level}] ${message}" >> "${OPERATIONS_LOG}"
  
  case ${level} in
    INFO) echo -e "${BLUE}[INFO]${NC} ${message}" ;;
    SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} ${message}" ;;
    WARNING) echo -e "${YELLOW}[WARNING]${NC} ${message}" ;;
    ERROR) echo -e "${RED}[ERROR]${NC} ${message}" ;;
    *)  echo -e "${message}" ;;
  esac
}

check_dependencies() {
  log_message "INFO" "Checking dependencies..."
  
  # Check for Node.js and npm
  if ! command -v node &> /dev/null; then
    log_message "ERROR" "Node.js is not installed. Please install Node.js 16+ to continue."
    return 1
  fi
  
  # Check for Go
  if ! command -v go &> /dev/null; then
    log_message "ERROR" "Go is not installed. Please install Go 1.18+ to continue."
    return 1
  fi
  
  # Check for Python
  if ! command -v python3 &> /dev/null; then
    log_message "ERROR" "Python 3 is not installed. Please install Python 3.8+ to continue."
    return 1
  fi
  
  log_message "SUCCESS" "All required dependencies are installed."
  return 0
}

# Check if a component is already running
is_running() {
  local component=$1
  local port=$2
  
  # Check if anything is listening on the specified port
  if netstat -tuln | grep -q ":${port} "; then
    return 0 # True, it's running
  else
    return 1 # False, not running
  fi
}

# Function to handle offline mode detection
check_offline_mode() {
  # Check if the offline lock file exists
  if [ -f "${BASE_DIR}/.offline_lock" ]; then
    log_message "WARNING" "System is running in offline mode (permanent lock file found)"
    export MCP_OFFLINE_MODE=true
    return 0
  fi
  
  # Try to ping the monitoring endpoint
  if curl -s -f "${MCP_MONITORING_ENDPOINT}/health" &> /dev/null; then
    log_message "INFO" "Online mode - External services are reachable"
    export MCP_OFFLINE_MODE=false
    return 1
  else
    log_message "WARNING" "Offline mode - Cannot reach external services"
    export MCP_OFFLINE_MODE=true
    return 0
  fi
}

# Function to create offline lock file
create_offline_lock() {
  local reason=$1
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
  
  echo "{\"created_at\": \"${timestamp}\", \"reason\": \"${reason}\", \"immutable\": true}" > "${BASE_DIR}/.offline_lock"
  log_message "WARNING" "Created permanent offline lock file: ${reason}"
}

# Function to start the dashboard UI
start_dashboard() {
  local port=${MCP_DASHBOARD_PORT}
  
  if is_running "dashboard" "${port}"; then
    log_message "WARNING" "Dashboard is already running on port ${port}"
    return 0
  fi
  
  log_message "INFO" "Starting MCP-ZERO Dashboard UI on port ${port}..."
  
  # Check if we need to build first
  if [ "$1" == "--build" ]; then
    (cd "${DASHBOARD_UI_DIR}" && npm install && npm run build) || {
      log_message "ERROR" "Failed to build dashboard UI"
      return 1
    }
  fi
  
  # Start the dashboard in development mode by default
  (cd "${DASHBOARD_UI_DIR}" && npm run dev > "${LOG_DIR}/dashboard.log" 2>&1 &)
  local pid=$!
  sleep 2
  
  if kill -0 ${pid} 2>/dev/null; then
    echo ${pid} > "${LOG_DIR}/dashboard.pid"
    log_message "SUCCESS" "Dashboard UI started successfully (PID: ${pid})"
    echo -e "${GREEN}Dashboard is now running at:${NC} http://localhost:${port}"
  else
    log_message "ERROR" "Failed to start Dashboard UI. Check ${LOG_DIR}/dashboard.log for details."
    return 1
  fi
}

# Function to start the API server
start_api() {
  local port=${MCP_API_PORT}
  
  if is_running "api" "${port}"; then
    log_message "WARNING" "API server is already running on port ${port}"
    return 0
  fi
  
  log_message "INFO" "Starting MCP-ZERO API server on port ${port}..."
  
  # Check offline mode and set appropriate flags
  check_offline_mode
  local offline_flag=""
  if [ "${MCP_OFFLINE_MODE}" = true ]; then
    offline_flag="--offline-mode"
  fi
  
  # Start the API server
  (cd "${API_DIR}" && go run . --port=${port} ${offline_flag} > "${LOG_DIR}/api.log" 2>&1 &)
  local pid=$!
  sleep 2
  
  if kill -0 ${pid} 2>/dev/null; then
    echo ${pid} > "${LOG_DIR}/api.pid"
    log_message "SUCCESS" "API server started successfully (PID: ${pid})"
    echo -e "${GREEN}API server is now running at:${NC} http://localhost:${port}"
  else
    log_message "ERROR" "Failed to start API server. Check ${LOG_DIR}/api.log for details."
    return 1
  fi
}

# Function to start the RPC server
start_rpc() {
  local port=${MCP_RPC_PORT}
  
  if is_running "rpc" "${port}"; then
    log_message "WARNING" "RPC server is already running on port ${port}"
    return 0
  fi
  
  log_message "INFO" "Starting MCP-ZERO RPC server on port ${port}..."
  
  # Check offline mode and set appropriate flags
  check_offline_mode
  local offline_flag=""
  if [ "${MCP_OFFLINE_MODE}" = true ]; then
    offline_flag="--offline"
  fi
  
  # Start the RPC server
  (cd "${RPC_DIR}" && go run . --port=${port} ${offline_flag} > "${LOG_DIR}/rpc.log" 2>&1 &)
  local pid=$!
  sleep 2
  
  if kill -0 ${pid} 2>/dev/null; then
    echo ${pid} > "${LOG_DIR}/rpc.pid"
    log_message "SUCCESS" "RPC server started successfully (PID: ${pid})"
    echo -e "${GREEN}RPC server is now running at:${NC} localhost:${port}"
  else
    log_message "ERROR" "Failed to start RPC server. Check ${LOG_DIR}/rpc.log for details."
    return 1
  fi
}

# Function to start monitoring service
start_monitoring() {
  log_message "INFO" "Starting MCP-ZERO monitoring services..."
  
  # Start the monitoring services
  (cd "${MONITORING_DIR}" && go run . > "${LOG_DIR}/monitoring.log" 2>&1 &)
  local pid=$!
  sleep 2
  
  if kill -0 ${pid} 2>/dev/null; then
    echo ${pid} > "${LOG_DIR}/monitoring.pid"
    log_message "SUCCESS" "Monitoring services started successfully (PID: ${pid})"
  else
    log_message "ERROR" "Failed to start monitoring services. Check ${LOG_DIR}/monitoring.log for details."
    return 1
  fi
}

# Function to start all services
start_all() {
  log_message "INFO" "Starting all MCP-ZERO services..."
  
  # Check if we're in offline mode
  check_offline_mode
  
  # Start each component
  start_api || log_message "WARNING" "Failed to start API server, continuing with other services"
  start_rpc || log_message "WARNING" "Failed to start RPC server, continuing with other services"
  start_monitoring || log_message "WARNING" "Failed to start monitoring, continuing with other services"
  start_dashboard || log_message "WARNING" "Failed to start dashboard, continuing with other services"
  
  log_message "SUCCESS" "MCP-ZERO system startup complete"
  echo -e "\n${GREEN}MCP-ZERO is running in ${MCP_OFFLINE_MODE:+offline}${MCP_OFFLINE_MODE:+off}${MCP_OFFLINE_MODE:-online} mode${NC}\n"
}

# Function to stop a specific service
stop_service() {
  local service=$1
  local pid_file="${LOG_DIR}/${service}.pid"
  
  if [ -f "${pid_file}" ]; then
    local pid=$(cat "${pid_file}")
    if kill -0 "${pid}" 2>/dev/null; then
      log_message "INFO" "Stopping ${service} service (PID: ${pid})..."
      kill "${pid}" 2>/dev/null || kill -9 "${pid}" 2>/dev/null
      rm "${pid_file}"
      log_message "SUCCESS" "${service} service stopped successfully"
      return 0
    fi
  fi
  
  log_message "WARNING" "${service} service is not running"
  return 1
}

# Function to stop all services
stop_all() {
  log_message "INFO" "Stopping all MCP-ZERO services..."
  
  stop_service "dashboard" || true
  stop_service "api" || true
  stop_service "rpc" || true
  stop_service "monitoring" || true
  
  # Additional cleanup for any stray processes
  pkill -f "npm run dev" || true
  
  log_message "SUCCESS" "All MCP-ZERO services stopped"
}

# Function to show status of all services
show_status() {
  echo -e "\n${BLUE}=== MCP-ZERO System Status ===${NC}\n"
  
  # Check offline mode
  check_offline_mode
  if [ "${MCP_OFFLINE_MODE}" = true ]; then
    echo -e "${YELLOW}System is running in OFFLINE mode${NC}"
    if [ -f "${BASE_DIR}/.offline_lock" ]; then
      echo -e "  ${YELLOW}Permanent offline lock file exists${NC}"
    fi
  else
    echo -e "${GREEN}System is running in ONLINE mode${NC}"
  fi
  
  echo -e "\n${BLUE}Services:${NC}"
  
  # Check Dashboard
  if is_running "dashboard" "${MCP_DASHBOARD_PORT}"; then
    echo -e "  Dashboard UI:      ${GREEN}RUNNING${NC}  (http://localhost:${MCP_DASHBOARD_PORT})"
  else
    echo -e "  Dashboard UI:      ${RED}STOPPED${NC}"
  fi
  
  # Check API
  if is_running "api" "${MCP_API_PORT}"; then
    echo -e "  API Server:        ${GREEN}RUNNING${NC}  (http://localhost:${MCP_API_PORT})"
  else
    echo -e "  API Server:        ${RED}STOPPED${NC}"
  fi
  
  # Check RPC
  if is_running "rpc" "${MCP_RPC_PORT}"; then
    echo -e "  RPC Server:        ${GREEN}RUNNING${NC}  (localhost:${MCP_RPC_PORT})"
  else
    echo -e "  RPC Server:        ${RED}STOPPED${NC}"
  fi
  
  # Check Monitoring
  if [ -f "${LOG_DIR}/monitoring.pid" ] && kill -0 $(cat "${LOG_DIR}/monitoring.pid") 2>/dev/null; then
    echo -e "  Monitoring:        ${GREEN}RUNNING${NC}"
  else
    echo -e "  Monitoring:        ${RED}STOPPED${NC}"
  fi
  
  echo -e "\n${BLUE}Configuration:${NC}"
  echo -e "  Dashboard Port:    ${MCP_DASHBOARD_PORT}"
  echo -e "  API Port:          ${MCP_API_PORT}"
  echo -e "  RPC Port:          ${MCP_RPC_PORT}"
  echo -e "  Monitoring URL:    ${MCP_MONITORING_ENDPOINT}"
  echo -e "  Log Directory:     ${LOG_DIR}"
  
  echo -e ""
}

# Function to run tests
run_tests() {
  local test_type=$1
  local test_path=$2
  
  case "${test_type}" in
    unit)
      log_message "INFO" "Running unit tests..."
      (cd "${BASE_DIR}" && go test ./src/... -v -short) || {
        log_message "ERROR" "Unit tests failed"
        return 1
      }
      ;;
    integration)
      log_message "INFO" "Running integration tests..."
      (cd "${BASE_DIR}" && go test ./tests/... -v) || {
        log_message "ERROR" "Integration tests failed"
        return 1
      }
      ;;
    offline)
      log_message "INFO" "Running offline resilience tests..."
      (cd "${BASE_DIR}/tests/offline_test" && python3 test_offline_resilience.py) || {
        log_message "ERROR" "Offline resilience tests failed"
        return 1
      }
      ;;
    all)
      run_tests unit
      run_tests integration
      run_tests offline
      ;;
    *)
      if [ -n "${test_path}" ]; then
        log_message "INFO" "Running tests in ${test_path}..."
        (cd "${BASE_DIR}" && go test ${test_path} -v) || {
          log_message "ERROR" "Tests in ${test_path} failed"
          return 1
        }
      else
        log_message "ERROR" "Unknown test type: ${test_type}"
        return 1
      fi
      ;;
  esac
  
  log_message "SUCCESS" "Tests completed successfully"
  return 0
}

# Function to build project components
build_component() {
  local component=$1
  
  case "${component}" in
    dashboard)
      log_message "INFO" "Building dashboard UI..."
      (cd "${DASHBOARD_UI_DIR}" && npm install && npm run build) || {
        log_message "ERROR" "Failed to build dashboard UI"
        return 1
      }
      log_message "SUCCESS" "Dashboard UI built successfully"
      ;;
    api)
      log_message "INFO" "Building API server..."
      (cd "${API_DIR}" && go build -o ../../bin/mcp-api) || {
        log_message "ERROR" "Failed to build API server"
        return 1
      }
      log_message "SUCCESS" "API server built successfully"
      ;;
    rpc)
      log_message "INFO" "Building RPC server..."
      (cd "${RPC_DIR}" && go build -o ../../bin/mcp-rpc) || {
        log_message "ERROR" "Failed to build RPC server"
        return 1
      }
      log_message "SUCCESS" "RPC server built successfully"
      ;;
    monitoring)
      log_message "INFO" "Building monitoring service..."
      (cd "${MONITORING_DIR}" && go build -o ../../bin/mcp-monitoring) || {
        log_message "ERROR" "Failed to build monitoring service"
        return 1
      }
      log_message "SUCCESS" "Monitoring service built successfully"
      ;;
    sdk)
      log_message "INFO" "Building SDK..."
      (cd "${SDK_DIR}" && python3 setup.py build) || {
        log_message "ERROR" "Failed to build SDK"
        return 1
      }
      log_message "SUCCESS" "SDK built successfully"
      ;;
    all)
      build_component dashboard
      build_component api
      build_component rpc
      build_component monitoring
      build_component sdk
      log_message "SUCCESS" "All components built successfully"
      ;;
    *)
      log_message "ERROR" "Unknown component: ${component}"
      return 1
      ;;
  esac
  
  return 0
}

# Display help message
show_help() {
  echo -e "\n${BLUE}MCP-ZERO Project Management CLI${NC}\n"
  echo -e "Usage: $0 [command] [options]\n"
  
  echo -e "${BLUE}Commands:${NC}"
  echo -e "  ${GREEN}start${NC} [component]   Start a specific component or all components"
  echo -e "                      Components: dashboard, api, rpc, monitoring, all"
  echo -e "  ${GREEN}stop${NC} [component]    Stop a specific component or all components"
  echo -e "                      Components: dashboard, api, rpc, monitoring, all"
  echo -e "  ${GREEN}restart${NC} [component] Restart a specific component or all components"
  echo -e "  ${GREEN}status${NC}             Display the status of all components"
  echo -e "  ${GREEN}build${NC} [component]   Build a specific component or all components"
  echo -e "                      Components: dashboard, api, rpc, monitoring, sdk, all"
  echo -e "  ${GREEN}test${NC} [type]         Run tests (unit, integration, offline, all)"
  echo -e "  ${GREEN}offline${NC} [reason]    Create permanent offline lock with reason"
  echo -e "  ${GREEN}help${NC}               Display this help message"
  
  echo -e "\n${BLUE}Examples:${NC}"
  echo -e "  $0 start all            # Start all MCP-ZERO components"
  echo -e "  $0 start dashboard      # Start only the dashboard UI"
  echo -e "  $0 status               # Check status of all components"
  echo -e "  $0 build all            # Build all components"
  echo -e "  $0 offline \"network failure\"  # Create permanent offline lock"
  
  echo -e "\n${BLUE}Environment Variables:${NC}"
  echo -e "  MCP_DASHBOARD_PORT      Dashboard UI port (default: 8080)"
  echo -e "  MCP_API_PORT            API server port (default: 8081)"
  echo -e "  MCP_RPC_PORT            RPC server port (default: 9000)"
  echo -e "  MCP_MONITORING_ENDPOINT Monitoring endpoint URL"
  
  echo -e ""
}

# Main command processing
case "$1" in
  start)
    component=${2:-"all"}
    case "${component}" in
      dashboard) start_dashboard ;;
      api) start_api ;;
      rpc) start_rpc ;;
      monitoring) start_monitoring ;;
      all) start_all ;;
      *) log_message "ERROR" "Unknown component: ${component}"; show_help; exit 1 ;;
    esac
    ;;
  stop)
    component=${2:-"all"}
    case "${component}" in
      dashboard) stop_service dashboard ;;
      api) stop_service api ;;
      rpc) stop_service rpc ;;
      monitoring) stop_service monitoring ;;
      all) stop_all ;;
      *) log_message "ERROR" "Unknown component: ${component}"; show_help; exit 1 ;;
    esac
    ;;
  restart)
    component=${2:-"all"}
    case "${component}" in
      dashboard) 
        stop_service dashboard
        sleep 1
        start_dashboard 
        ;;
      api) 
        stop_service api
        sleep 1
        start_api 
        ;;
      rpc) 
        stop_service rpc
        sleep 1
        start_rpc 
        ;;
      monitoring) 
        stop_service monitoring
        sleep 1
        start_monitoring 
        ;;
      all) 
        stop_all
        sleep 1
        start_all 
        ;;
      *) log_message "ERROR" "Unknown component: ${component}"; show_help; exit 1 ;;
    esac
    ;;
  status)
    show_status
    ;;
  build)
    component=${2:-"all"}
    build_component "${component}"
    ;;
  test)
    test_type=${2:-"all"}
    test_path=$3
    run_tests "${test_type}" "${test_path}"
    ;;
  offline)
    reason=${2:-"Manual offline mode activation"}
    create_offline_lock "${reason}"
    ;;
  help|--help|-h)
    show_help
    ;;
  *)
    show_help
    exit 1
    ;;
esac

exit 0
