#!/usr/bin/env bash
# =============================================================================
# Fischer AgentKit — 本地开发环境一键启动
# =============================================================================
#
# 启动：后端服务（+ 可选 Tauri 桌面客户端）
# 停止：Ctrl+C 或运行 scripts/dev-stop.sh
#
# 用法：
#   bash scripts/dev-start.sh              # Web 模式（agentkit gui）
#   bash scripts/dev-start.sh --tauri     # Web + Tauri 桌面客户端
#   bash scripts/dev-start.sh --serve     # 仅后端 API
#   bash scripts/dev-start.sh --init      # 首次运行（初始化 DB）
#   bash scripts/dev-start.sh --help      # 帮助
#
# 依赖：
#   Python >= 3.11, Node.js >= 18, Redis, PostgreSQL (均自动检查)
#   --tauri 需要：Rust 工具链（rustup / brew install rust）
#
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$PROJECT_ROOT"

# ── 颜色 ────────────────────────────────────────────────────────────────────

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

# ── 帮助 ────────────────────────────────────────────────────────────────────

show_help() {
  cat <<-'EOF'
Fischer AgentKit — 本地开发环境启动

用法: bash scripts/dev-start.sh [选项]

选项:
  --tauri    启动 Tauri 桌面客户端（Vite 热重载 + 原生窗口）
  --serve    仅启动后端 API（无前端）
  --init     首次运行，初始化数据库和测试用户
  --help     显示此帮助

模式说明:
  默认        Web 模式：agentkit gui (前后端 + 内置静态服务)
  --tauri     Tauri 模式：后端 API + Vite (:5173) + Tauri 桌面窗口

端口映射:
  8000  — 后端 API
  8002  — Web GUI / 前端静态服务
  5173  — Vite 开发服务器（--tauri 模式）
EOF
}

# ── 参数解析 ────────────────────────────────────────────────────────────────

MODE="gui"
INIT_DB=0

while [[ $# -gt 0 ]]; do
  case $1 in
    --tauri)  MODE="tauri"; shift ;;
    --serve)  MODE="serve"; shift ;;
    --init)   INIT_DB=1;   shift ;;
    --help|-h) show_help; exit 0 ;;
    *) shift ;;
  esac
done

# ── 日志函数 ────────────────────────────────────────────────────────────────

ok()   { echo -e "  ${GREEN}✓${NC}  $*"; }
info() { echo -e "  ${CYAN}→${NC}  $*"; }
warn() { echo -e "  ${YELLOW}!${NC}  $*"; }
fail() { echo -e "  ${RED}✗${NC}  $*" >&2; }

section() {
  echo ""
  echo -e "${CYAN}────────────────────────────────────────${NC}"
  echo -e "${CYAN}  $*${NC}"
  echo -e "${CYAN}────────────────────────────────────────${NC}"
}

# ── 进度状态机 ──────────────────────────────────────────────────────────────

# 0=未开始, 1=进行中, 2=成功, 3=失败
S_DEPS=0 S_ENV=0 S_REDIS=0 S_PG=0 S_BACKEND=0 S_FRONTEND=0 S_TAURI=0

set_status() {
  local step=$1 val=$2
  case $step in
    deps) S_DEPS=$val ;;
    env)  S_ENV=$val ;;
    redis) S_REDIS=$val ;;
    pg)   S_PG=$val ;;
    backend) S_BACKEND=$val ;;
    frontend) S_FRONTEND=$val ;;
    tauri) S_TAURI=$val ;;
  esac
}

print_status() {
  echo ""
  echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
  echo -e "${CYAN}  启动状态总览${NC}"
  echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
  echo -e "$([[ $S_DEPS    -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_DEPS    -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  依赖检查"
  echo -e "$([[ $S_ENV     -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_ENV     -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  环境配置"
  echo -e "$([[ $S_REDIS   -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_REDIS   -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  Redis"
  echo -e "$([[ $S_PG      -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_PG      -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  PostgreSQL"
  echo -e "$([[ $S_BACKEND -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_BACKEND -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  后端服务 (:8000)"
  if [[ $MODE == "gui" || $MODE == "tauri" ]]; then
    echo -e "$([[ $S_FRONTEND -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_FRONTEND -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  前端服务 (:8002)"
  fi
  if [[ $MODE == "tauri" ]]; then
    echo -e "$([[ $S_TAURI   -eq 2 ]] && echo "  ${GREEN}✓${NC}" || [[ $S_TAURI   -eq 3 ]] && echo "  ${RED}✗${NC}" || echo "  ${YELLOW}○${NC}")  Tauri 客户端"
  fi
}

# ── 前置检查 ────────────────────────────────────────────────────────────────

check_deps() {
  section "检查依赖"
  set_status deps 1

  for cmd in python3 node npm; do
    if ! command -v "$cmd" &>/dev/null; then
      fail "缺少依赖: $cmd"
      set_status deps 3
      return 1
    fi
  done
  ok "Python $(python3 --version 2>&1 | awk '{print $2}')"
  ok "Node $(node --version 2>&1)"
  ok "npm $(npm --version 2>&1)"

  # Python 版本 >= 3.11
  if ! python3 -c 'import sys; sys.exit(0 if (sys.version_info.major, sys.version_info.minor) >= (3, 11) else 1)'; then
    fail "Python 版本需 >= 3.11"
    set_status deps 3
    return 1
  fi

  # Tauri 模式需要 Rust
  if [[ $MODE == "tauri" ]]; then
    if ! command -v rustc &>/dev/null; then
      warn "未检测到 Rust（Tauri 需要）：请运行 brew install rust 或 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
    else
      ok "Rust $(rustc --version 2>&1 | awk '{print $2}')"
    fi
  fi

  set_status deps 2
}

check_env() {
  section "检查环境配置"
  set_status env 1

  if [[ ! -f .env ]]; then
    warn "未找到 .env，将使用环境变量默认值"
    if [[ -f .env.example ]]; then
      cp .env.example .env
      ok "已从 .env.example 生成 .env"
    fi
  else
    ok ".env 存在"
  fi

  set_status env 2
}

check_redis() {
  section "检查 Redis"
  set_status redis 1

  if command -v redis-cli &>/dev/null && redis-cli ping 2>/dev/null | grep -q PONG; then
    ok "Redis 运行中"
    set_status redis 2
    return 0
  fi

  # Docker 方式
  local name="fischer-redis-dev"
  if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${name}$"; then
    ok "Redis 容器运行中"
    set_status redis 2
    return 0
  fi

  warn "Redis 未运行，尝试启动 Docker 容器..."
  if docker run -d --name "$name" -p 6379:6379 redis:7-alpine &>/dev/null; then
    sleep 2
    if docker exec "$name" redis-cli ping 2>/dev/null | grep -q PONG; then
      ok "Redis Docker 容器启动成功 (:6379)"
      set_status redis 2
      return 0
    fi
  fi
  fail "Redis 启动失败（请确保 Docker 运行中，或手动启动 Redis）"
  set_status redis 3
  return 1
}

check_postgres() {
  section "检查 PostgreSQL"
  set_status pg 1

  if lsof -i :5432 2>/dev/null | grep -q LISTEN; then
    ok "PostgreSQL 已在 :5432 监听"
    set_status pg 2
    return 0
  fi

  # Docker 方式
  local name="fischer-pg-dev"
  if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${name}$"; then
    ok "PostgreSQL Docker 容器运行中"
    set_status pg 2
    return 0
  fi

  warn "PostgreSQL 未在 :5432 运行，尝试启动 Docker 容器..."
  if docker run -d --name "$name" \
    -p 5432:5432 \
    -e POSTGRES_USER=agentkit \
    -e POSTGRES_PASSWORD=agentkit \
    -e POSTGRES_DB=agentkit \
    pgvector/pgvector:pg15 &>/dev/null; then
    sleep 3
    if docker exec "$name" pg_isready -U agentkit &>/dev/null; then
      ok "PostgreSQL Docker 容器启动成功 (:5432)"
      set_status pg 2
      return 0
    fi
  fi
  warn "PostgreSQL 启动失败（bitable 等功能可能受限，继续启动后端...）"
  set_status pg 2  # 不阻塞，继续
  return 0
}

# ── 安装依赖 ────────────────────────────────────────────────────────────────

install_deps() {
  section "安装依赖"
  info "后端 Python 依赖..."

  # 虚拟环境
  if [[ ! -d .venv ]]; then
    python3 -m venv .venv
    ok "虚拟环境 .venv 创建完成"
  fi

  source .venv/bin/activate
  pip install -q -U pip
  pip install -e ".[dev]" -q
  ok "后端依赖安装完成"

  # 前端 npm 依赖
  local FE_DIR="$PROJECT_ROOT/src/agentkit/server/frontend"
  if [[ ! -d "$FE_DIR/node_modules" ]]; then
    info "前端 npm 依赖..."
    cd "$FE_DIR"
    npm install
    cd "$PROJECT_ROOT"
    ok "前端依赖安装完成"
  else
    ok "前端 node_modules 已存在"
  fi
}

# ── 启动后端 ────────────────────────────────────────────────────────────────

start_backend() {
  section "启动后端服务"
  set_status backend 1

  info "启动后端 API (:8000)..."
  source .venv/bin/activate
  agentkit serve --port 8000 &
  BACKEND_PID=$!

  # 等待健康检查就绪（最多 60 秒）
  info "等待后端就绪..."
  local attempt=0
  while [[ $attempt -lt 60 ]]; do
    if curl -sf http://127.0.0.1:8000/api/v1/health &>/dev/null; then
      ok "后端 API 就绪 (http://127.0.0.1:8000, PID $BACKEND_PID)"
      set_status backend 2
      return 0
    fi
    # 检查进程是否还活着
    if ! kill -0 $BACKEND_PID 2>/dev/null; then
      fail "后端进程意外退出"
      set_status backend 3
      return 1
    fi
    sleep 1
    ((attempt++))
    [[ $((attempt % 10)) -eq 0 ]] && info "等待中... (${attempt}s)"
  done

  fail "后端启动超时（60s 内未响应健康检查）"
  kill $BACKEND_PID 2>/dev/null || true
  set_status backend 3
  return 1
}

# ── 启动 Web GUI ────────────────────────────────────────────────────────────

start_gui() {
  section "启动 Web GUI"
  set_status frontend 1

  info "启动 Web GUI (:8002)..."
  source .venv/bin/activate
  agentkit gui --port 8002 &
  GUI_PID=$!

  # 等待就绪
  info "等待 Web GUI 就绪..."
  local attempt=0
  while [[ $attempt -lt 60 ]]; do
    if curl -sf http://127.0.0.1:8002/api/v1/health &>/dev/null; then
      ok "Web GUI 就绪 (http://127.0.0.1:8002, PID $GUI_PID)"
      set_status frontend 2
      return 0
    fi
    if ! kill -0 $GUI_PID 2>/dev/null; then
      fail "Web GUI 进程意外退出"
      set_status frontend 3
      return 1
    fi
    sleep 1
    ((attempt++))
    [[ $((attempt % 10)) -eq 0 ]] && info "等待中... (${attempt}s)"
  done

  fail "Web GUI 启动超时"
  kill $GUI_PID 2>/dev/null || true
  set_status frontend 3
  return 1
}

# ── 启动 Tauri ─────────────────────────────────────────────────────────────

start_tauri() {
  section "启动 Tauri 桌面客户端"
  set_status tauri 1

  local FE_DIR="$PROJECT_ROOT/src/agentkit/server/frontend"

  if ! command -v tauri &>/dev/null; then
    warn "Tauri CLI 未安装，跳过桌面客户端"
    info "安装方式：npm install -g @tauri-apps/cli"
    set_status tauri 2
    return 0
  fi

  info "启动 Tauri 桌面客户端..."
  info "  (Vite → :5173, 后端 API → :8000)"
  cd "$FE_DIR"
  npm run tauri dev &
  TAURI_PID=$!

  info "Tauri 启动中（首次运行需要编译 Rust，可能需要几分钟）..."
  ok "Tauri 进程已启动 (PID $TAURI_PID)"
  info "桌面窗口将自动打开，如未打开请手动查看终端输出"

  set_status tauri 2
  cd "$PROJECT_ROOT"
}

# ── 数据库初始化 ────────────────────────────────────────────────────────────

init_db() {
  section "初始化数据库"
  info "创建测试用户..."

  local SETUP_SCRIPT="$PROJECT_ROOT/src/agentkit/server/frontend/e2e/setup-test-user.py"
  if [[ -f "$SETUP_SCRIPT" ]]; then
    source .venv/bin/activate
    if python3 "$SETUP_SCRIPT" 2>/dev/null; then
      ok "测试用户创建完成"
    else
      warn "测试用户创建失败（可能已存在或数据库未就绪）"
    fi
  fi
}

# ── 停止服务 ────────────────────────────────────────────────────────────────

stop_services() {
  echo ""
  info "正在停止所有服务..."

  for port in 8000 8001 8002 5173; do
    local pid=$(lsof -ti :$port 2>/dev/null || true)
    if [[ -n "$pid" ]]; then
      kill $pid 2>/dev/null && ok "端口 $port 已停止" || true
    fi
  done

  # Vite 进程
  pkill -f "vite" 2>/dev/null && ok "Vite 进程已停止" || true

  echo ""
  ok "所有服务已停止。感谢使用！"
}

# ── 主流程 ─────────────────────────────────────────────────────────────────

echo ""
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
echo -e "${CYAN}  Fischer AgentKit — 本地开发环境启动${NC}"
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
echo ""

# 检查依赖
if ! check_deps; then
  echo ""
  fail "依赖检查失败，请先安装缺失的依赖"
  exit 1
fi

check_env

# 初始化数据库
[[ $INIT_DB -eq 1 ]] && init_db

# 安装依赖
install_deps

# 检查中间件
check_redis || true
check_postgres || true

echo ""

# ── 启动服务 ────────────────────────────────────────────────────────────────

FAILED=0

case $MODE in
  serve)
    if ! start_backend; then FAILED=1; fi
    ;;
  gui)
    if ! start_backend; then FAILED=1; fi
    if [[ $FAILED -eq 0 ]] && ! start_gui; then FAILED=1; fi
    ;;
  tauri)
    if ! start_backend; then FAILED=1; fi
    if [[ $FAILED -eq 0 ]]; then
      start_tauri
    fi
    ;;
esac

# ── 状态总览 + 启动完成 ──────────────────────────────────────────────────────

print_status

echo ""
echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
if [[ $FAILED -eq 0 ]]; then
  echo -e "${GREEN}  所有服务启动成功！${NC}"
  echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
  echo ""
  if [[ $MODE == "gui" ]]; then
    echo -e "  Web GUI:      ${GREEN}http://localhost:8002${NC}"
    echo "  (在浏览器中打开，或直接在 http://localhost:8002 访问)"
  elif [[ $MODE == "tauri" ]]; then
    echo -e "  后端 API:     ${GREEN}http://localhost:8000${NC}"
    echo -e "  Vite 热重载:  ${GREEN}http://localhost:5173${NC}"
    echo "  Tauri 桌面窗口应已自动打开"
  elif [[ $MODE == "serve" ]]; then
    echo -e "  后端 API:     ${GREEN}http://localhost:8000${NC}"
  fi
  echo ""
  echo -e "  ${YELLOW}按 Ctrl+C 停止所有服务${NC}"
  echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
else
  echo -e "${RED}  服务启动失败，请查看上方错误信息${NC}"
  echo -e "${CYAN}═══════════════════════════════════════════════════${NC}"
  echo ""
  echo -e "  诊断命令："
  echo -e "    查看日志: ${CYAN}curl http://127.0.0.1:8000/api/v1/health${NC}"
  echo -e "    停止服务: ${CYAN}bash scripts/dev-stop.sh${NC}"
fi
echo ""

# 注册退出钩子
trap stop_services EXIT INT TERM

# 保持脚本运行
if [[ $MODE == "tauri" ]]; then
  # Tauri 模式：等待 Tauri 进程
  wait
elif [[ $MODE == "gui" || $MODE == "serve" ]]; then
  # 等待后端进程
  wait $BACKEND_PID 2>/dev/null || true
fi
