#!/bin/bash
#
# Genex Backend Services - 部署管理脚本
# =========================================
#
# 用法:
#   ./deploy.sh install           # 首次初始化 (生成密钥、创建 .env)
#   ./deploy.sh up                # 启动全部服务
#   ./deploy.sh down              # 停止全部服务
#   ./deploy.sh restart           # 重启全部服务
#   ./deploy.sh build             # 增量编译全部镜像
#   ./deploy.sh build-no-cache    # 全新编译全部镜像 (无缓存)
#   ./deploy.sh status            # 查看服务状态
#   ./deploy.sh health            # 健康检查
#   ./deploy.sh logs [svc]        # 查看日志 (可指定服务)
#   ./deploy.sh migrate           # 运行数据库迁移
#
# 基础设施:
#   ./deploy.sh infra-up          # 仅启动基础设施 (PG, Redis, Kafka, MinIO, Kong)
#   ./deploy.sh infra-down        # 停止基础设施
#   ./deploy.sh infra-restart     # 重启基础设施
#   ./deploy.sh infra-status      # 基础设施状态
#   ./deploy.sh infra-logs        # 基础设施日志
#   ./deploy.sh infra-clean       # 清理基础设施 (删除数据!)
#   ./deploy.sh infra-reset       # 重置基础设施 (clean + 重新启动)
#
# 单服务操作:
#   ./deploy.sh start-svc <name>                # 启动指定服务
#   ./deploy.sh stop-svc <name>                 # 停止指定服务
#   ./deploy.sh restart-svc <name>              # 重启指定服务
#   ./deploy.sh rebuild-svc <name>              # 增量编译并重启指定服务
#   ./deploy.sh rebuild-svc <name> --no-cache   # 全新编译并重启指定服务
#   ./deploy.sh logs-svc <name>                 # 查看指定服务日志
#

set -e

# ===========================================================================
# 配置
# ===========================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/.env"
COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml"

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

log_info()    { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $1"; }
log_step()    { echo -e "${CYAN}[STEP]${NC} $1"; }

# 基础设施服务列表
INFRA_SERVICES="postgres redis kafka minio minio-init kafka-connect kong"

# 应用服务列表 (NestJS)
NESTJS_SERVICES="auth-service user-service issuer-service clearing-service compliance-service ai-service notification-service telemetry-service admin-service"

# 应用服务列表 (Go)
GO_SERVICES="trading-service translate-service chain-indexer"

# 全部应用服务
APP_SERVICES="$NESTJS_SERVICES $GO_SERVICES"

# ===========================================================================
# 工具函数
# ===========================================================================

generate_random_password() {
    openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32
}

generate_hex_key() {
    openssl rand -hex 32
}

check_docker() {
    if ! command -v docker &> /dev/null; then
        log_error "Docker 未安装，请先安装 Docker"
        exit 1
    fi
    if ! docker compose version &> /dev/null; then
        log_error "Docker Compose 未安装，请先安装 Docker Compose"
        exit 1
    fi
    log_info "Docker: $(docker --version | head -1)"
    log_info "Compose: $(docker compose version --short)"
}

check_env() {
    if [ ! -f "$ENV_FILE" ]; then
        log_error "环境文件不存在。请先运行: ./deploy.sh install"
        exit 1
    fi
}

compose() {
    docker compose -f "$COMPOSE_FILE" "$@"
}

# ===========================================================================
# install — 首次初始化
# ===========================================================================

install() {
    log_step "初始化 Genex Backend Services..."
    check_docker

    if [ ! -f "$ENV_FILE" ]; then
        log_step "生成安全配置..."

        DB_PASSWORD=$(generate_random_password)
        JWT_ACCESS=$(generate_random_password)
        JWT_REFRESH=$(generate_random_password)
        MINIO_SECRET=$(generate_random_password)

        cat > "$ENV_FILE" << EOF
# =============================================================================
# Genex Backend - 生产环境配置
# =============================================================================
# 生成时间: $(date)
# 警告: 请妥善保管此文件！不要提交到版本控制！
# =============================================================================

# 数据库
DB_HOST=postgres
DB_PORT=5432
DB_USERNAME=genex
DB_PASSWORD=${DB_PASSWORD}
DB_NAME=genex

# Redis
REDIS_HOST=redis
REDIS_PORT=6379

# Kafka
KAFKA_BROKERS=kafka:9092

# JWT
JWT_ACCESS_SECRET=${JWT_ACCESS}
JWT_ACCESS_EXPIRY=15m
JWT_REFRESH_SECRET=${JWT_REFRESH}
JWT_REFRESH_EXPIRY=7d

# Kong
KONG_ADMIN_URL=http://kong:8001
KONG_PROXY_PORT=8080

# MinIO
MINIO_ENDPOINT=minio
MINIO_PORT=9000
MINIO_ACCESS_KEY=genex-admin
MINIO_SECRET_KEY=${MINIO_SECRET}

# AI
AI_SERVICE_URL=http://ai-agent-cluster:3006
AI_SERVICE_API_KEY=your-ai-service-api-key
AI_SERVICE_TIMEOUT=30000

# 区块链
CHAIN_RPC_URL=http://localhost:26657
EOF

        chmod 600 "$ENV_FILE"
        log_success "环境文件已创建: $ENV_FILE"
        log_success "密钥已自动生成"
    else
        log_info "环境文件已存在: $ENV_FILE"
    fi

    log_success "初始化完成!"
    echo ""
    log_info "下一步:"
    log_info "  1. 检查并编辑 .env"
    log_info "  2. ./deploy.sh build"
    log_info "  3. ./deploy.sh up"
}

# ===========================================================================
# Docker Compose 全局操作
# ===========================================================================

up() {
    check_env
    log_step "启动 Genex Backend Services..."

    # 先启动基础设施
    log_info "启动基础设施..."
    compose up -d postgres redis kafka minio

    log_info "等待基础设施就绪..."
    sleep 8

    # 启动 MinIO 初始化 + Kafka Connect + Kong
    log_info "启动 MinIO 初始化 / Kafka Connect / Kong..."
    compose up -d minio-init kafka-connect kong

    sleep 5

    # 启动全部应用服务
    log_info "启动应用服务..."
    compose up -d

    log_success "全部服务已启动!"
    echo ""
    log_info "查看状态: ./deploy.sh status"
    log_info "查看日志: ./deploy.sh logs"
}

down() {
    log_step "停止 Genex Backend Services..."
    compose down
    log_success "全部服务已停止"
}

restart() {
    log_step "重启 Genex Backend Services..."
    down
    sleep 3
    up
}

build() {
    check_env
    log_step "增量编译全部 Docker 镜像..."
    compose build --parallel
    log_success "全部镜像编译完成"
}

build_no_cache() {
    check_env
    log_step "全新编译全部 Docker 镜像 (无缓存)..."
    compose build --no-cache --parallel
    log_success "全部镜像编译完成 (无缓存)"
}

# ===========================================================================
# 状态与健康检查
# ===========================================================================

status() {
    echo ""
    echo "============================================"
    echo "  Genex Backend Services 状态"
    echo "============================================"
    echo ""
    compose ps
    echo ""
    health
}

health() {
    echo "============================================"
    echo "  健康检查"
    echo "============================================"
    echo ""

    # NestJS 服务
    local nestjs_checks=(
        "auth-service:3010:/api/v1/health"
        "user-service:3001:/api/v1/health"
        "issuer-service:3002:/api/v1/health"
        "clearing-service:3004:/api/v1/health"
        "compliance-service:3005:/api/v1/health"
        "ai-service:3006:/api/v1/health"
        "notification-service:3008:/api/v1/health"
        "telemetry-service:3011:/api/v1/health"
        "admin-service:3012:/api/v1/health"
    )

    echo "NestJS 服务:"
    for svc in "${nestjs_checks[@]}"; do
        name="${svc%%:*}"
        rest="${svc#*:}"
        port="${rest%%:*}"
        endpoint="${rest#*:}"
        if curl -sf "http://localhost:${port}${endpoint}" > /dev/null 2>&1; then
            echo -e "  ${GREEN}[OK]${NC}   $name (:$port)"
        else
            echo -e "  ${RED}[FAIL]${NC} $name (:$port)"
        fi
    done

    echo ""

    # Go 服务
    local go_checks=(
        "trading-service:3003:/health"
        "translate-service:3007:/health"
        "chain-indexer:3009:/health"
    )

    echo "Go 服务:"
    for svc in "${go_checks[@]}"; do
        name="${svc%%:*}"
        rest="${svc#*:}"
        port="${rest%%:*}"
        endpoint="${rest#*:}"
        if curl -sf "http://localhost:${port}${endpoint}" > /dev/null 2>&1; then
            echo -e "  ${GREEN}[OK]${NC}   $name (:$port)"
        else
            echo -e "  ${RED}[FAIL]${NC} $name (:$port)"
        fi
    done

    echo ""
    echo "基础设施:"

    if docker exec genex-postgres pg_isready -U genex &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   PostgreSQL (:5432)"
    else
        echo -e "  ${RED}[FAIL]${NC} PostgreSQL (:5432)"
    fi

    if docker exec genex-redis redis-cli ping &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   Redis (:6379)"
    else
        echo -e "  ${RED}[FAIL]${NC} Redis (:6379)"
    fi

    if docker exec genex-kafka kafka-broker-api-versions --bootstrap-server localhost:9092 &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   Kafka (:9092)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kafka (:9092)"
    fi

    if curl -sf "http://localhost:9000/minio/health/live" > /dev/null 2>&1; then
        echo -e "  ${GREEN}[OK]${NC}   MinIO (:9000)"
    else
        echo -e "  ${RED}[FAIL]${NC} MinIO (:9000)"
    fi

    if curl -sf "http://localhost:8083/" > /dev/null 2>&1; then
        echo -e "  ${GREEN}[OK]${NC}   Kafka Connect (:8083)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kafka Connect (:8083)"
    fi

    local kong_status
    kong_status=$(curl -so /dev/null -w "%{http_code}" "http://localhost:8080/" 2>/dev/null || echo "000")
    if [ "$kong_status" != "000" ]; then
        echo -e "  ${GREEN}[OK]${NC}   Kong Gateway (:8080)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kong Gateway (:8080)"
    fi

    echo ""
}

logs() {
    local service="$1"
    if [ -n "$service" ]; then
        compose logs -f "$service"
    else
        compose logs -f
    fi
}

# ===========================================================================
# 数据库迁移
# ===========================================================================

migrate() {
    log_step "运行数据库迁移..."

    if [ -d "$SCRIPT_DIR/migrations" ]; then
        local DB_URL="${DATABASE_URL:-postgresql://genex:genex_dev_password@localhost:5432/genex}"
        for f in "$SCRIPT_DIR"/migrations/*.sql; do
            if [ -f "$f" ]; then
                log_info "执行: $(basename "$f")"
                psql "$DB_URL" -f "$f" 2>/dev/null || log_warn "跳过: $(basename "$f")"
            fi
        done
        log_success "迁移完成"
    else
        log_warn "未找到 migrations 目录"
    fi
}

# ===========================================================================
# 基础设施操作
# ===========================================================================

infra_up() {
    log_step "启动基础设施..."
    compose up -d postgres redis kafka minio minio-init kafka-connect kong
    log_success "基础设施已启动"
}

infra_down() {
    log_step "停止基础设施..."
    compose stop postgres redis kafka minio kafka-connect kong
    log_success "基础设施已停止"
}

infra_restart() {
    log_step "重启基础设施..."
    infra_down
    sleep 3
    infra_up
}

infra_status() {
    echo ""
    echo "============================================"
    echo "  基础设施状态"
    echo "============================================"
    echo ""
    compose ps postgres redis kafka minio kafka-connect kong
    echo ""

    echo "健康检查:"
    if docker exec genex-postgres pg_isready -U genex &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   PostgreSQL (:5432)"
    else
        echo -e "  ${RED}[FAIL]${NC} PostgreSQL (:5432)"
    fi

    if docker exec genex-redis redis-cli ping &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   Redis (:6379)"
    else
        echo -e "  ${RED}[FAIL]${NC} Redis (:6379)"
    fi

    if docker exec genex-kafka kafka-broker-api-versions --bootstrap-server localhost:9092 &>/dev/null; then
        echo -e "  ${GREEN}[OK]${NC}   Kafka (:9092)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kafka (:9092)"
    fi

    if curl -sf "http://localhost:9000/minio/health/live" > /dev/null 2>&1; then
        echo -e "  ${GREEN}[OK]${NC}   MinIO (:9000)"
    else
        echo -e "  ${RED}[FAIL]${NC} MinIO (:9000)"
    fi

    if curl -sf "http://localhost:8083/" > /dev/null 2>&1; then
        echo -e "  ${GREEN}[OK]${NC}   Kafka Connect (:8083)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kafka Connect (:8083)"
    fi

    local kong_status
    kong_status=$(curl -so /dev/null -w "%{http_code}" "http://localhost:8080/" 2>/dev/null || echo "000")
    if [ "$kong_status" != "000" ]; then
        echo -e "  ${GREEN}[OK]${NC}   Kong Gateway (:8080)"
    else
        echo -e "  ${RED}[FAIL]${NC} Kong Gateway (:8080)"
    fi
    echo ""
}

infra_logs() {
    compose logs -f postgres redis kafka minio kafka-connect kong
}

infra_clean() {
    log_warn "这将删除基础设施容器和所有数据 (PostgreSQL, Redis, Kafka, MinIO)!"
    read -p "确认操作? (y/N): " confirm
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        log_step "停止基础设施..."
        compose stop postgres redis kafka minio kafka-connect kong
        log_step "移除容器..."
        compose rm -f postgres redis kafka minio kafka-connect kong
        log_step "移除数据卷..."
        docker volume rm -f backend_postgres_data backend_redis_data backend_kafka_data backend_minio_data 2>/dev/null || true
        log_success "基础设施清理完成"
    else
        log_info "已取消"
    fi
}

infra_reset() {
    log_warn "这将重置全部基础设施 (清理 + 重新启动)!"
    log_warn "所有数据库将被删除并重建!"
    read -p "确认操作? (y/N): " confirm
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        compose stop postgres redis kafka minio kafka-connect kong
        compose rm -f postgres redis kafka minio kafka-connect kong
        docker volume rm -f backend_postgres_data backend_redis_data backend_kafka_data backend_minio_data 2>/dev/null || true
        sleep 3
        infra_up
        log_info "等待基础设施就绪..."
        sleep 10
        log_success "基础设施重置完成!"
        echo ""
        log_info "下一步:"
        log_info "  1. 重启应用服务: ./deploy.sh restart"
        log_info "  2. 或全新编译: ./deploy.sh build && ./deploy.sh up"
    else
        log_info "已取消"
    fi
}

# ===========================================================================
# 单服务操作
# ===========================================================================

start_svc() {
    local service="$1"
    if [ -z "$service" ]; then
        log_error "请指定服务名。可用: $APP_SERVICES"
        exit 1
    fi
    log_info "启动 $service..."
    compose up -d "$service"
    log_success "$service 已启动"
}

stop_svc() {
    local service="$1"
    if [ -z "$service" ]; then
        log_error "请指定服务名。可用: $APP_SERVICES"
        exit 1
    fi
    log_info "停止 $service..."
    compose stop "$service"
    log_success "$service 已停止"
}

restart_svc() {
    local service="$1"
    if [ -z "$service" ]; then
        log_error "请指定服务名。可用: $APP_SERVICES"
        exit 1
    fi
    log_info "重启 $service..."
    compose stop "$service"
    compose up -d "$service"
    log_success "$service 已重启"
}

rebuild_svc() {
    local service="$1"
    local flag="$2"
    if [ -z "$service" ]; then
        log_error "请指定服务名。可用: $APP_SERVICES"
        exit 1
    fi

    log_info "编译 $service..."
    if [ "$flag" = "--no-cache" ]; then
        log_info "全新编译 (无缓存)..."
        compose build --no-cache "$service"
    else
        compose build "$service"
    fi
    compose up -d "$service"
    log_success "$service 编译并重启完成"
}

logs_svc() {
    local service="$1"
    if [ -z "$service" ]; then
        log_error "请指定服务名"
        exit 1
    fi
    compose logs -f "$service"
}

# ===========================================================================
# 清理
# ===========================================================================

clean() {
    log_warn "这将移除全部容器、数据卷和镜像!"
    read -p "确认操作? (y/N): " confirm
    if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
        log_step "清理全部资源..."
        compose down -v --rmi all
        log_success "清理完成"
    else
        log_info "已取消"
    fi
}

# ===========================================================================
# 主入口
# ===========================================================================

case "${1:-}" in
    install)
        install
        ;;
    up|start)
        up
        ;;
    down|stop)
        down
        ;;
    restart)
        restart
        ;;
    build)
        build
        ;;
    build-no-cache)
        build_no_cache
        ;;
    status|ps)
        status
        ;;
    health)
        health
        ;;
    logs)
        logs "$2"
        ;;
    migrate)
        migrate
        ;;
    clean)
        clean
        ;;
    # 单服务操作
    start-svc)
        start_svc "$2"
        ;;
    stop-svc)
        stop_svc "$2"
        ;;
    restart-svc)
        restart_svc "$2"
        ;;
    rebuild-svc)
        rebuild_svc "$2" "$3"
        ;;
    logs-svc)
        logs_svc "$2"
        ;;
    # 基础设施操作
    infra-up)
        infra_up
        ;;
    infra-down)
        infra_down
        ;;
    infra-restart)
        infra_restart
        ;;
    infra-status)
        infra_status
        ;;
    infra-logs)
        infra_logs
        ;;
    infra-clean)
        infra_clean
        ;;
    infra-reset)
        infra_reset
        ;;
    *)
        echo "Genex Backend Services 部署管理脚本"
        echo ""
        echo "用法: $0 <命令> [参数]"
        echo ""
        echo "全局命令:"
        echo "  install           首次初始化 (生成密钥、创建 .env)"
        echo "  up/start          启动全部服务"
        echo "  down/stop         停止全部服务"
        echo "  restart           重启全部服务"
        echo "  build             增量编译全部镜像"
        echo "  build-no-cache    全新编译全部镜像 (无缓存)"
        echo "  status/ps         查看服务状态 + 健康检查"
        echo "  health            仅健康检查"
        echo "  logs [svc]        查看日志 (可指定服务)"
        echo "  migrate           运行数据库迁移"
        echo "  clean             移除全部容器、卷和镜像"
        echo ""
        echo "单服务命令:"
        echo "  start-svc <name>                启动指定服务"
        echo "  stop-svc <name>                 停止指定服务"
        echo "  restart-svc <name>              重启指定服务"
        echo "  rebuild-svc <name>              增量编译并重启"
        echo "  rebuild-svc <name> --no-cache   全新编译并重启"
        echo "  logs-svc <name>                 查看指定服务日志"
        echo ""
        echo "基础设施命令:"
        echo "  infra-up           启动基础设施 (PG, Redis, Kafka, MinIO, Kong)"
        echo "  infra-down         停止基础设施"
        echo "  infra-restart      重启基础设施"
        echo "  infra-status       基础设施状态 + 健康检查"
        echo "  infra-logs         基础设施日志"
        echo "  infra-clean        清理基础设施容器和数据卷 (删除数据!)"
        echo "  infra-reset        重置基础设施 (clean + 重新启动)"
        echo ""
        echo "服务列表:"
        echo "  NestJS: auth-service, user-service, issuer-service, clearing-service,"
        echo "          compliance-service, ai-service, notification-service,"
        echo "          telemetry-service, admin-service"
        echo "  Go:     trading-service, translate-service, chain-indexer"
        echo ""
        echo "示例:"
        echo "  $0 install                          # 首次初始化"
        echo "  $0 build                            # 增量编译全部"
        echo "  $0 up                               # 启动全部"
        echo "  $0 rebuild-svc auth-service          # 增量编译 auth"
        echo "  $0 rebuild-svc trading-service --no-cache  # 全新编译 trading"
        echo "  $0 logs user-service                 # 查看 user 日志"
        echo "  $0 infra-status                      # 检查基础设施"
        echo ""
        exit 1
        ;;
esac
