#!/bin/bash
# ========================================
# Cyrene ethend 启动脚本
# 管理开发环境: 数据库 / 服务编译 / ethend 控制台
# ========================================
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ETHEND_DIR="$SCRIPT_DIR/ethend"
ROOT="$SCRIPT_DIR"
PORT="${ETHEND_PORT:-9090}"
LOG_DIR="$ETHEND_DIR/logs"
LOG_FILE="$LOG_DIR/sh.log"

# 颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# ========== 平台检测 ==========
IS_WIN=false
case "$(uname -s)" in
  MINGW*|MSYS*|CYGWIN*) IS_WIN=true ;;
esac

# ========== 帮助 ==========
show_help() {
  echo -e "${CYAN}Cyrene ethend${NC} — 开发环境管理工具"
  echo ""
  echo -e "${BOLD}用法:${NC} ./ethend.sh [命令] [选项]"
  echo ""
  echo -e "${BOLD}命令:${NC}"
  echo "  (无参数)          启动 ethend 控制台 (默认)"
  echo "  start              启动 ethend 控制台"
  echo "  start --fresh       强制重启全部后端服务后启动"
  echo "  start --build       编译全部服务后启动"
  echo "  stop               停止 ethend 控制台"
  echo "  status             查看所有服务状态"
  echo "  logs [服务ID]       查看服务日志 (默认显示最近 20 行)"
  echo "  build [服务ID]      编译服务 (不指定则编译全部)"
  echo "  db:start           启动数据库容器 (Docker Compose)"
  echo "  db:stop            停止数据库容器"
  echo "  db:status          检查数据库连接状态"
  echo "  help               显示此帮助"
  echo ""
  echo -e "${BOLD}选项:${NC}"
  echo "  --port, -p <端口>   指定 ethend 端口 (默认: 9090)"
  echo "  --fresh             启动前强制重启全部后端服务"
  echo "  --build             启动前编译全部服务"
  echo ""
  echo -e "${BOLD}示例:${NC}"
  echo "  ./ethend.sh                           # 快速启动"
  echo "  ./ethend.sh start --build             # 编译后启动"
  echo "  ./ethend.sh start --fresh             # 全新重启"
  echo "  ./ethend.sh logs gateway              # 查看 Gateway 日志"
  echo "  ./ethend.sh build ai-core             # 仅编译 AI-Core"
  echo "  ./ethend.sh db:status                 # 检查数据库"
  echo ""
  echo -e "${BOLD}Web 控制台:${NC} http://localhost:$PORT"
}

# ========== 依赖检查 ==========
check_deps() {
  local missing=0

  # Node.js
  if ! command -v node &>/dev/null; then
    if [ -x /usr/local/node/bin/node ]; then
      export PATH="/usr/local/node/bin:$PATH"
    else
      echo -e "${RED}✗ Node.js 未安装${NC}"
      missing=1
    fi
  fi

  # Docker (用于数据库)
  if ! command -v docker &>/dev/null; then
    echo -e "${YELLOW}⚠ Docker 未安装 (数据库容器功能不可用)${NC}"
  fi

  # Go (用于编译后端服务)
  if ! command -v go &>/dev/null; then
    if $IS_WIN && [ -f "/c/Program Files/Go/bin/go.exe" ]; then
      export PATH="$PATH:/c/Program Files/Go/bin"
    else
      echo -e "${YELLOW}⚠ Go 未安装 (服务编译功能不可用)${NC}"
    fi
  fi

  return $missing
}

# ========== 加载 .env ==========
load_env() {
  local env_file="$ROOT/.env"
  if [ -f "$env_file" ]; then
    echo -e "${GREEN}✓ 加载环境变量: .env${NC}"
    set -a
    source "$env_file"
    set +a
  else
    echo -e "${YELLOW}⚠ 未找到 .env，使用默认值${NC}"
  fi
}

# ========== 端口工具 (跨平台) ==========
port_in_use() {
  local port=$1
  if $IS_WIN; then
    netstat -ano 2>/dev/null | grep -q ":$port " | grep -q "LISTENING"
  else
    ss -tlnp 2>/dev/null | grep -q ":$port " || netstat -tlnp 2>/dev/null | grep -q ":$port "
  fi
}

kill_port() {
  local port=$1
  if $IS_WIN; then
    local pid=$(netstat -ano 2>/dev/null | grep ":$port " | grep "LISTENING" | awk '{print $NF}' | head -1)
    if [ -n "$pid" ] && [ "$pid" != "0" ]; then
      powershell -Command "Stop-Process -Id $pid -Force" 2>/dev/null || true
    fi
  else
    fuser -k "$port/tcp" 2>/dev/null || true
  fi
  sleep 1
}

# ========== 健康检查 ==========
health_check() {
  local url=$1
  local max_wait=${2:-30}
  local waited=0
  while [ $waited -lt $max_wait ]; do
    if curl -s -o /dev/null -w "%{http_code}" "$url" 2>/dev/null | grep -q "200"; then
      return 0
    fi
    sleep 1
    waited=$((waited + 1))
  done
  return 1
}

# ========== 数据库管理 ==========
DB_COMPOSE_FILE="$ROOT/docker-compose.dev.db.yml"

db_status() {
  if port_in_use 5432; then
    echo -e "${GREEN}✓ PostgreSQL 在线 (端口 5432)${NC}"
    return 0
  else
    echo -e "${RED}✗ PostgreSQL 离线${NC}"
    return 1
  fi
}

db_start() {
  echo -e "${CYAN}启动数据库容器...${NC}"
  if [ ! -f "$DB_COMPOSE_FILE" ]; then
    echo -e "${RED}✗ 未找到 $DB_COMPOSE_FILE${NC}"
    return 1
  fi
  docker compose -f "$DB_COMPOSE_FILE" up -d
  echo -e "${YELLOW}等待数据库就绪...${NC}"
  if health_check "http://localhost:5432" 30; then
    echo -e "${GREEN}✓ 数据库已就绪${NC}"
  else
    echo -e "${YELLOW}⚠ 数据库可能仍在启动中，请稍后检查${NC}"
  fi
}

db_stop() {
  echo -e "${CYAN}停止数据库容器...${NC}"
  if [ ! -f "$DB_COMPOSE_FILE" ]; then
    echo -e "${RED}✗ 未找到 $DB_COMPOSE_FILE${NC}"
    return 1
  fi
  docker compose -f "$DB_COMPOSE_FILE" down
  echo -e "${GREEN}✓ 数据库已停止${NC}"
}

# ========== 服务编译 ==========
SERVICES=(
  "memory-service:backend/memory-service"
  "iot-debug-service:backend/iot-debug-service"
  "voice-service:backend/voice-service"
  "ai-core:backend/ai-core"
  "plugin-manager:backend/cyrene-plugins"
  "platform-bridge:backend/platform-bridge"
  "gateway:backend/gateway"
)

build_service() {
  local id=$1
  local dir=$2
  local label=${3:-$id}

  echo -e "${CYAN}[编译] $label...${NC}"
  local binary="main"
  $IS_WIN && binary="main.exe"

  cd "$ROOT/$dir"
  local build_target="./cmd/main.go"
  if [ "$id" = "plugin-manager" ]; then
    build_target="./cmd/plugin-manager/"
  fi
  if GOWORK=off go build -o "$binary" "$build_target" 2>&1; then
    echo -e "${GREEN}  ✓ $label 编译完成${NC}"
    return 0
  else
    echo -e "${RED}  ✗ $label 编译失败${NC}"
    return 1
  fi
}

build_all() {
  echo -e "${BOLD}编译全部后端服务...${NC}"
  local failed=0
  for entry in "${SERVICES[@]}"; do
    IFS=':' read -r id dir <<< "$entry"
    # 检查目录是否存在
    if [ -d "$ROOT/$dir" ]; then
      build_service "$id" "$dir" "$id" || failed=$((failed + 1))
    fi
  done

  if [ $failed -eq 0 ]; then
    echo -e "${GREEN}✓ 全部编译完成${NC}"
  else
    echo -e "${YELLOW}⚠ $failed 个服务编译失败${NC}"
  fi
  cd "$ROOT"
  return $failed
}

# ========== 查看日志 ==========
show_logs() {
  local service_id=$1
  local lines=${2:-20}
  local log_path="$LOG_DIR/${service_id}.log"

  if [ ! -f "$log_path" ]; then
    echo -e "${YELLOW}日志文件不存在: $log_path${NC}"
    return 1
  fi

  echo -e "${BOLD}=== $service_id 日志 (最近 $lines 行) ===${NC}"
  tail -n "$lines" "$log_path"
}

# ========== 启动 ethend ==========
start_ethend() {
  local do_build=false
  local do_fresh=false

  # 解析参数
  for arg in "$@"; do
    case $arg in
      --build) do_build=true ;;
      --fresh) do_fresh=true ;;
      --port=*) PORT="${arg#*=}" ;;
      -p) shift; PORT="$1" ;;
    esac
  done

  echo ""
  echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
  echo -e "${CYAN}   Cyrene ethend${NC}"
  echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

  # 依赖检查
  check_deps || exit 1

  echo -e "${YELLOW}Node.js:${NC} $(node --version)"
  command -v go &>/dev/null && echo -e "${YELLOW}Go:${NC}      $(go version | cut -d' ' -f3)"
  command -v docker &>/dev/null && echo -e "${YELLOW}Docker:${NC}  $(docker --version | cut -d' ' -f3 | tr -d ',')"

  # 加载环境变量
  load_env

  # 编译 (如果指定)
  if $do_build; then
    build_all
  fi

  # 全新重启 (如果指定)
  if $do_fresh; then
    echo -e "${YELLOW}强制重启全部后端服务...${NC}"
    curl -s -X POST "http://localhost:$PORT/api/services/start-all-fresh" 2>/dev/null || true
  fi

  # 检查并释放端口
  if port_in_use "$PORT"; then
    # 检查是否是已有 ethend 实例
    if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
      echo -e "${GREEN}✓ ethend 已在运行: http://localhost:$PORT${NC}"
      echo -e "${CYAN}  API:        http://localhost:$PORT/api/health${NC}"
      return 0
    fi
    echo -e "${YELLOW}⚠ 端口 $PORT 被占用，正在释放...${NC}"
    kill_port "$PORT"
  fi

  # 切换到 ethend 目录
  cd "$ETHEND_DIR"

  # 安装依赖
  if [ ! -d "node_modules" ] || [ ! -f "node_modules/.package-lock.json" ]; then
    echo -e "${YELLOW}安装依赖...${NC}"
    npm install --silent
  fi

  # 确保日志目录存在
  mkdir -p "$LOG_DIR"

  echo ""
  echo -e "${GREEN}启动 ethend 服务器 (端口: $PORT)...${NC}"
  echo -e "${CYAN}  Web 控制台:  http://localhost:$PORT${NC}"
  echo -e "${CYAN}  API:         http://localhost:$PORT/api/health${NC}"
  echo -e "${CYAN}  WebSocket:   ws://localhost:$PORT/ws${NC}"
  echo ""
  echo -e "${YELLOW}正在后台启动...${NC}"

  # 后台启动 ethend
  nohup node src/index.js > "$LOG_FILE" 2>&1 &
  local pid=$!
  cd "$ROOT"

  # 等待健康检查
  echo -e "${YELLOW}等待服务就绪...${NC}"
  if health_check "http://localhost:$PORT/api/health" 30; then
    echo ""
    echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${GREEN}  ethend 已启动！${NC}"
    echo -e "${GREEN}  PID:        ${pid}${NC}"
    echo -e "${GREEN}  控制台:     http://localhost:$PORT${NC}"
    echo -e "${GREEN}  日志:       ${LOG_FILE}${NC}"
    echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo ""

    # 检查数据库状态
    db_status

    return 0
  fi

  # 超时
  if kill -0 "$pid" 2>/dev/null; then
    echo ""
    echo -e "${YELLOW}⚠ 服务可能仍在启动中 (已等待 30 秒)${NC}"
    echo -e "${CYAN}  请稍后检查 http://localhost:$PORT/api/health${NC}"
  else
    echo ""
    echo -e "${RED}✗ 服务启动失败，请检查日志: ${LOG_FILE}${NC}"
    return 1
  fi
}

# ========== 停止 ethend ==========
stop_ethend() {
  if port_in_use "$PORT"; then
    echo -e "${CYAN}停止 ethend...${NC}"
    if $IS_WIN; then
      kill_port "$PORT"
    else
      fuser -k "$PORT/tcp" 2>/dev/null || true
    fi
    echo -e "${GREEN}✓ ethend 已停止${NC}"
  else
    echo -e "${YELLOW}ethend 未在运行${NC}"
  fi
}

# ========== 查看状态 ==========
show_status() {
  if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
    echo -e "${GREEN}✓ ethend 在线${NC}"

    # 获取服务状态
    local status_json=$(curl -s "http://localhost:$PORT/api/services" 2>/dev/null)
    if [ -n "$status_json" ]; then
      echo ""
      echo -e "${BOLD}服务状态:${NC}"
      local tmpfile="$(mktemp)"
      echo "$status_json" > "$tmpfile"
      node -e "
        const fs = require('fs');
        const data = JSON.parse(fs.readFileSync(process.argv[1], 'utf-8'));
        for (const [id, svc] of Object.entries(data)) {
          const icon = svc.status === 'running' ? '✓' : svc.status === 'stopped' ? '✗' : '○';
          const color = svc.status === 'running' ? '\x1b[32m' : '\x1b[31m';
          const pid = svc.pid ? ' (PID: ' + svc.pid + ')' : '';
          const uptime = svc.uptime ? ' | uptime: ' + Math.round(svc.uptime / 1000) + 's' : '';
          console.log('  ' + color + icon + '\x1b[0m ' + svc.name.padEnd(16) + ' [' + svc.status + ']' + pid + uptime);
        }
      " "$tmpfile"
      rm -f "$tmpfile"
    fi

    # 数据库状态
    echo ""
    db_status
  else
    echo -e "${RED}✗ ethend 离线${NC}"
  fi
}

# ========== 主入口 ==========
CMD="${1:-start}"
shift 2>/dev/null || true

case "$CMD" in
  help|--help|-h)
    show_help
    ;;
  start|"")
    start_ethend "$@"
    ;;
  stop)
    stop_ethend
    ;;
  status)
    show_status
    ;;
  logs)
    if [ -z "$1" ]; then
      echo -e "${YELLOW}用法: ./ethend.sh logs <服务ID>${NC}"
      echo "可用服务: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend"
      exit 1
    fi
    show_logs "$1" "${2:-20}"
    ;;
  build)
    check_deps || exit 1
    load_env
    if [ -n "$1" ]; then
      # 查找服务目录
      for entry in "${SERVICES[@]}"; do
        IFS=':' read -r id dir <<< "$entry"
        if [ "$id" = "$1" ]; then
          build_service "$id" "$dir" "$id"
          exit $?
        fi
      done
      echo -e "${RED}未知服务: $1${NC}"
      echo "可用服务: ${SERVICES[*]}"
      exit 1
    else
      build_all
    fi
    ;;
  db:start)
    db_start
    ;;
  db:stop)
    db_stop
    ;;
  db:status)
    db_status
    ;;
  *)
    echo -e "${RED}未知命令: $CMD${NC}"
    echo ""
    show_help
    exit 1
    ;;
esac
