#!/bin/bash

# ==================================================
# OCDP Backend - 三种模式测试脚本
# ==================================================
# 测试三种部署模式：
# 1. Mock 模式（无 docker compose，backend 热重载）
# 2. Production 模式（docker compose 仅依赖服务，backend 热重载）
# 3. Production 模式（docker compose 包含 backend）
# ==================================================

set -e  # 遇到错误立即退出

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

log_success() {
    echo -e "${GREEN}✅ $1${NC}"
}

log_error() {
    echo -e "${RED}❌ $1${NC}"
}

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

log_section() {
    echo ""
    echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${BLUE}  $1${NC}"
    echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo ""
}

# 等待服务启动
wait_for_service() {
    local url=$1
    local max_attempts=30
    local attempt=1

    log_info "等待服务启动: $url"

    while [ $attempt -le $max_attempts ]; do
        if curl -s -f "$url" > /dev/null 2>&1; then
            log_success "服务已启动！"
            return 0
        fi
        echo -n "."
        sleep 1
        attempt=$((attempt + 1))
    done

    log_error "服务启动超时"
    return 1
}

# 测试健康检查
test_health() {
    local mode=$1
    log_info "测试健康检查..."
    
    response=$(curl -s http://localhost:8080/health)
    if echo "$response" | grep -q "healthy"; then
        log_success "$mode 模式健康检查通过"
        return 0
    else
        log_error "$mode 模式健康检查失败"
        echo "响应: $response"
        return 1
    fi
}

# 测试 API
test_api() {
    local mode=$1
    log_info "测试 API..."
    
    # 测试注册
    local test_username="testuser$RANDOM"
    local test_password="test123"
    register_response=$(curl -s -X POST http://localhost:8080/api/v1/auth/register \
        -H "Content-Type: application/json" \
        -d '{"username":"'"$test_username"'","password":"'"$test_password"'","email":"test@example.com"}')
    
    if echo "$register_response" | grep -q "id"; then
        log_success "$mode 模式 API 注册测试通过"
    else
        log_warning "$mode 模式 API 注册测试失败（可能用户已存在）"
    fi
    
    # 测试登录
    login_response=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
        -H "Content-Type: application/json" \
        -d '{"username":"'"$test_username"'","password":"'"$test_password"'"}')
    
    if echo "$login_response" | grep -q "accessToken"; then
        log_success "$mode 模式 API 登录测试通过"
        return 0
    else
        log_error "$mode 模式 API 登录测试失败"
        echo "响应: $login_response"
        return 1
    fi
}

# 清理环境
cleanup() {
    log_info "清理环境..."
    
    # 停止所有容器
    docker compose down --remove-orphans > /dev/null 2>&1 || true
    docker compose --profile backend down --remove-orphans > /dev/null 2>&1 || true
    docker compose --profile mock down --remove-orphans > /dev/null 2>&1 || true
    
    # 停止可能在运行的本地进程
    pkill -f "tmp/main" > /dev/null 2>&1 || true
    pkill -f "cmd/api/main.go" > /dev/null 2>&1 || true
    
    sleep 2
    log_success "清理完成"
}

# ==================================================
# 测试 1: Mock 模式（无 docker compose，backend 热重载）
# ==================================================
test_mode_1() {
    log_section "测试模式 1: Mock 模式（本地运行，热重载）"
    
    log_info "配置:"
    log_info "  • 运行方式: 本地 Go"
    log_info "  • 适配器: Mock（内存存储）"
    log_info "  • 数据库: 无需"
    log_info "  • 热重载: 支持（Air）"
    
    # 检查 Air 是否安装
    if ! command -v air &> /dev/null; then
        log_error "Air 未安装，跳过热重载测试"
        log_info "安装命令: go install github.com/air-verse/air@latest"
        return 1
    fi
    
    # 启动 Mock 模式（后台）
    log_info "启动 Mock 模式..."
    export ADAPTER_MODE=mock
    export PORT=8080
    export JWT_SECRET=test-secret
    
    # 在后台启动
    nohup air -c .air.toml > /tmp/ocdp-mock.log 2>&1 &
    local pid=$!
    log_info "进程 PID: $pid"
    
    # 等待服务启动
    if wait_for_service "http://localhost:8080/health"; then
        # 测试服务
        test_health "Mock"
        test_api "Mock"
        
        # 停止服务
        log_info "停止服务..."
        kill $pid 2>/dev/null || true
        pkill -f "tmp/main" 2>/dev/null || true
        sleep 2
        
        log_success "模式 1 测试完成"
        return 0
    else
        log_error "服务启动失败，查看日志: /tmp/ocdp-mock.log"
        kill $pid 2>/dev/null || true
        return 1
    fi
}

# ==================================================
# 测试 2: Production 模式（docker compose 仅依赖，backend 热重载）
# ==================================================
test_mode_2() {
    log_section "测试模式 2: Docker Compose 仅依赖服务（本地 backend 热重载）"
    
    log_info "配置:"
    log_info "  • 数据库: Docker (PostgreSQL)"
    log_info "  • Backend: 本地 Go"
    log_info "  • 适配器: Production"
    log_info "  • 热重载: 支持（Air）"
    
    # 检查 Air 是否安装
    if ! command -v air &> /dev/null; then
        log_error "Air 未安装，跳过热重载测试"
        return 1
    fi
    
    # 启动 PostgreSQL
    log_info "启动 PostgreSQL 容器..."
    docker compose up -d postgres
    
    # 等待数据库就绪
    log_info "等待 PostgreSQL 启动..."
    sleep 10
    
    # 检查数据库健康状态
    if ! docker compose exec -T postgres pg_isready -U postgres > /dev/null 2>&1; then
        log_error "PostgreSQL 未就绪"
        docker compose logs postgres
        return 1
    fi
    log_success "PostgreSQL 已启动"
    
    # 启动 Backend（后台）
    log_info "启动 Backend (本地)..."
    export ADAPTER_MODE=production
    export PORT=8080
    export JWT_SECRET=test-secret
    export ENCRYPTION_KEY=12345678901234567890123456789012
    export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/ocdp?sslmode=disable"
    
    # 在后台启动
    nohup air -c .air.toml > /tmp/ocdp-real.log 2>&1 &
    local pid=$!
    log_info "进程 PID: $pid"
    
    # 等待服务启动
    if wait_for_service "http://localhost:8080/health"; then
        # 测试服务
        test_health "Production (本地 backend)"
        test_api "Production (本地 backend)"
        
        # 停止服务
        log_info "停止 backend..."
        kill $pid 2>/dev/null || true
        pkill -f "tmp/main" 2>/dev/null || true
        sleep 2
        
        # 停止数据库
        log_info "停止 PostgreSQL..."
        docker compose down
        
        log_success "模式 2 测试完成"
        return 0
    else
        log_error "服务启动失败，查看日志: /tmp/ocdp-real.log"
        kill $pid 2>/dev/null || true
        docker compose down
        return 1
    fi
}

# ==================================================
# 测试 3: Production 模式（docker compose 包含 backend）
# ==================================================
test_mode_3() {
    log_section "测试模式 3: Docker Compose 完整服务（包含 backend）"
    
    log_info "配置:"
    log_info "  • 数据库: Docker (PostgreSQL)"
    log_info "  • Backend: Docker 容器"
    log_info "  • 适配器: Production"
    log_info "  • 热重载: 不支持"
    
    # 确保 .env 文件存在
    if [ ! -f .env ]; then
        log_info "创建 .env 文件..."
        cp env.example .env
    fi
    
    # 启动完整服务
    log_info "启动完整服务（PostgreSQL + Backend）..."
    docker compose --profile backend up -d
    
    # 等待服务启动
    log_info "等待服务启动（可能需要构建镜像，请耐心等待）..."
    
    # 检查容器状态
    sleep 15
    if ! docker compose ps | grep -q "ocdp-backend"; then
        log_error "Backend 容器未启动"
        docker compose logs backend
        return 1
    fi
    
    # 等待健康检查通过
    if wait_for_service "http://localhost:8080/health"; then
        # 测试服务
        test_health "Production (Docker)"
        test_api "Production (Docker)"
        
        # 查看容器状态
        log_info "容器状态:"
        docker compose ps
        
        # 停止服务
        log_info "停止服务..."
        docker compose --profile backend down
        
        log_success "模式 3 测试完成"
        return 0
    else
        log_error "服务启动失败"
        log_info "Backend 日志:"
        docker compose logs backend
        docker compose --profile backend down
        return 1
    fi
}

# ==================================================
# 主函数
# ==================================================
main() {
    log_section "OCDP Backend - 三种模式自动化测试"
    
    log_info "项目目录: $(pwd)"
    log_info "测试时间: $(date)"
    
    # 检查是否在项目根目录
    if [ ! -f "docker-compose.yml" ]; then
        log_error "请在项目根目录运行此脚本"
        exit 1
    fi
    
    # 初始清理
    cleanup
    
    # 运行测试
    local failed=0
    
    # 测试模式 1
    if test_mode_1; then
        log_success "✅ 模式 1 测试通过"
    else
        log_error "❌ 模式 1 测试失败"
        failed=$((failed + 1))
    fi
    
    cleanup
    sleep 3
    
    # 测试模式 2
    if test_mode_2; then
        log_success "✅ 模式 2 测试通过"
    else
        log_error "❌ 模式 2 测试失败"
        failed=$((failed + 1))
    fi
    
    cleanup
    sleep 3
    
    # 测试模式 3
    if test_mode_3; then
        log_success "✅ 模式 3 测试通过"
    else
        log_error "❌ 模式 3 测试失败"
        failed=$((failed + 1))
    fi
    
    cleanup
    
    # 总结
    log_section "测试总结"
    
    if [ $failed -eq 0 ]; then
        log_success "🎉 所有测试通过！"
        log_info ""
        log_info "三种部署模式总结:"
        log_info ""
        log_info "1️⃣  Mock 模式（开发）"
        log_info "   命令: make dev-mock"
        log_info "   特点: 无需数据库，快速启动，热重载"
        log_info ""
        log_info "2️⃣  Real 模式（开发 + 数据库）"
        log_info "   命令: docker compose up -d && make dev-real"
        log_info "   特点: PostgreSQL 容器，Backend 本地热重载"
        log_info ""
        log_info "3️⃣  Production 模式（生产）"
        log_info "   命令: docker compose --profile backend up -d"
        log_info "   特点: 完全容器化，适合生产环境"
        exit 0
    else
        log_error "❌ $failed 个测试失败"
        exit 1
    fi
}

# 执行主函数
main
