#!/bin/bash
# 主构建脚本 - 若依框架Docker部署方案
# 实现一键构建所有镜像、代码拉取更新和环境配置切换功能
# Requirements: 5.1, 5.2, 5.3

set -e

# ===========================================
# 脚本配置
# ===========================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
DOCKER_DIR="$SCRIPT_DIR"

# 默认配置
DEFAULT_ENVIRONMENT="development"
DEFAULT_TAG="latest"
BUILD_ALL=false
PULL_CODE=false
NO_CACHE=false
CLEAN_BUILD=false
VERBOSE=false

# 镜像配置
FRONTEND_IMAGE="anxin-frontend"
BACKEND_IMAGE="anxin-backend"
MYSQL_IMAGE="mysql:8.0.36"

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

# ===========================================
# 日志函数
# ===========================================
log_info() {
    echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_debug() {
    if [[ "$VERBOSE" == "true" ]]; then
        echo -e "${PURPLE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    fi
}

log_step() {
    echo -e "${CYAN}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

# ===========================================
# 帮助信息
# ===========================================
show_help() {
    cat << EOF
若依框架Docker部署 - 主构建脚本

用法: $0 [选项] [命令]

命令:
    build           构建指定组件的Docker镜像
    build-all       构建所有Docker镜像 (默认)
    pull            拉取最新代码
    deploy          构建并部署到指定环境
    clean           清理构建缓存和临时文件
    status          查看当前构建状态
    help            显示此帮助信息

选项:
    -e, --env ENV           指定环境 (development|staging|production) [默认: development]
    -t, --tag TAG           指定镜像标签 [默认: latest]
    -c, --component COMP    指定构建组件 (frontend|backend|all) [默认: all]
    --pull                  构建前拉取最新代码
    --no-cache              不使用Docker构建缓存
    --clean                 构建前清理缓存
    --verbose               显示详细日志
    -h, --help              显示此帮助信息

环境配置:
    development (dev)       开发环境 - 启用调试模式，使用开发配置
    staging     (stage)     测试环境 - 接近生产的测试配置
    production  (prod)      生产环境 - 优化的生产配置

示例:
    $0                                  # 构建所有镜像 (开发环境)
    $0 build-all -e production         # 构建所有镜像 (生产环境)
    $0 build -c frontend -t v1.0.0     # 构建前端镜像并标记为v1.0.0
    $0 deploy -e staging --pull        # 拉取代码并部署到测试环境
    $0 pull                            # 仅拉取最新代码
    $0 clean                           # 清理构建缓存

Requirements Coverage:
    5.1 - 一键构建所有镜像功能
    5.2 - 代码拉取和更新功能  
    5.3 - 环境配置切换功能

EOF
}

# ===========================================
# 参数解析
# ===========================================
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            build)
                COMMAND="build"
                shift
                ;;
            build-all)
                COMMAND="build-all"
                BUILD_ALL=true
                shift
                ;;
            pull)
                COMMAND="pull"
                shift
                ;;
            deploy)
                COMMAND="deploy"
                BUILD_ALL=true
                shift
                ;;
            clean)
                COMMAND="clean"
                shift
                ;;
            status)
                COMMAND="status"
                shift
                ;;
            -e|--env)
                ENVIRONMENT="$2"
                shift 2
                ;;
            -t|--tag)
                TAG="$2"
                shift 2
                ;;
            -c|--component)
                COMPONENT="$2"
                shift 2
                ;;
            --pull)
                PULL_CODE=true
                shift
                ;;
            --no-cache)
                NO_CACHE=true
                shift
                ;;
            --clean)
                CLEAN_BUILD=true
                shift
                ;;
            --verbose)
                VERBOSE=true
                shift
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                log_error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
    done

    # 设置默认值
    COMMAND=${COMMAND:-"build-all"}
    ENVIRONMENT=${ENVIRONMENT:-$DEFAULT_ENVIRONMENT}
    TAG=${TAG:-$DEFAULT_TAG}
    COMPONENT=${COMPONENT:-"all"}
    
    # 如果没有指定组件但命令是build，则构建所有组件
    if [[ "$COMMAND" == "build" && "$COMPONENT" == "all" ]]; then
        BUILD_ALL=true
    fi
}

# ===========================================
# 环境验证和配置
# ===========================================
validate_environment() {
    case $ENVIRONMENT in
        development|dev)
            ENVIRONMENT="development"
            ;;
        staging|stage)
            ENVIRONMENT="staging"
            ;;
        production|prod)
            ENVIRONMENT="production"
            ;;
        *)
            log_error "无效的环境: $ENVIRONMENT"
            log_info "支持的环境: development, staging, production"
            exit 1
            ;;
    esac
    
    log_debug "环境验证通过: $ENVIRONMENT"
}

# 加载环境配置
load_environment_config() {
    local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
    
    if [[ ! -f "$env_file" ]]; then
        log_error "环境配置文件不存在: $env_file"
        exit 1
    fi
    
    log_info "加载环境配置: $ENVIRONMENT"
    source "$env_file"
    
    # 导出关键环境变量
    export ENVIRONMENT
    export COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-"anxin-${ENVIRONMENT}"}
    export SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-"docker"}
    
    log_debug "环境配置加载完成"
    log_debug "项目名称: $COMPOSE_PROJECT_NAME"
    log_debug "Spring配置: $SPRING_PROFILES_ACTIVE"
}

# ===========================================
# 系统检查
# ===========================================
check_prerequisites() {
    log_step "检查系统依赖..."
    
    # 检查Docker
    if ! command -v docker &> /dev/null; then
        log_error "Docker未安装或不在PATH中"
        exit 1
    fi
    
    # 检查Docker Compose
    if ! command -v docker-compose &> /dev/null; then
        log_error "Docker Compose未安装或不在PATH中"
        exit 1
    fi
    
    # 检查Docker守护进程
    if ! docker info &> /dev/null; then
        log_error "Docker守护进程未运行"
        exit 1
    fi
    
    # 检查Git (如果需要拉取代码)
    if [[ "$PULL_CODE" == "true" ]] && ! command -v git &> /dev/null; then
        log_error "Git未安装或不在PATH中，无法拉取代码"
        exit 1
    fi
    
    log_success "系统依赖检查通过"
}

# ===========================================
# 代码拉取和更新功能 (Requirement 5.2)
# ===========================================
pull_latest_code() {
    log_step "拉取最新代码..."
    
    cd "$PROJECT_ROOT"
    
    # 检查是否为Git仓库
    if [[ ! -d ".git" ]]; then
        log_warn "当前目录不是Git仓库，跳过代码拉取"
        return 0
    fi
    
    # 获取当前分支
    local current_branch=$(git branch --show-current)
    log_info "当前分支: $current_branch"
    
    # 检查是否有未提交的更改
    if ! git diff-index --quiet HEAD --; then
        log_warn "检测到未提交的更改"
        read -p "是否继续拉取代码? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "取消代码拉取"
            return 1
        fi
    fi
    
    # 拉取最新代码
    log_info "从远程仓库拉取最新代码..."
    if git pull origin "$current_branch"; then
        log_success "代码拉取成功"
        
        # 检查是否有子模块
        if [[ -f ".gitmodules" ]]; then
            log_info "更新Git子模块..."
            git submodule update --init --recursive
        fi
        
        # 显示最新提交信息
        log_info "最新提交信息:"
        git log --oneline -5
        
    else
        log_error "代码拉取失败"
        return 1
    fi
}

# ===========================================
# 构建准备
# ===========================================
prepare_build() {
    log_step "准备构建环境..."
    
    # 从环境变量获取路径，如果没有则使用默认值
    local mysql_data_path=${MYSQL_DATA_PATH:-"./data/${ENVIRONMENT}/mysql"}
    local mysql_log_path=${MYSQL_LOG_PATH:-"./data/${ENVIRONMENT}/mysql-logs"}
    local backend_log_path=${BACKEND_LOG_PATH:-"./data/${ENVIRONMENT}/backend-logs"}
    local backend_upload_path=${BACKEND_UPLOAD_PATH:-"./data/${ENVIRONMENT}/uploads"}
    local frontend_log_path=${FRONTEND_LOG_PATH:-"./data/${ENVIRONMENT}/nginx-logs"}
    
    local data_dirs=(
        "$mysql_data_path"
        "$mysql_log_path"
        "$backend_log_path"
        "$backend_upload_path"
        "$frontend_log_path"
    )
    
    # 创建必要的目录
    for dir in "${data_dirs[@]}"; do
        # 转换相对路径为绝对路径
        local abs_dir="${DOCKER_DIR}/${dir#./}"
        if [[ ! -d "$abs_dir" ]]; then
            log_debug "创建目录: $abs_dir"
            mkdir -p "$abs_dir"
        fi
    done
    
    # 设置目录权限
    local base_data_dir="${DOCKER_DIR}/data/${ENVIRONMENT}"
    if [[ -d "$base_data_dir" ]]; then
        chmod -R 755 "$base_data_dir"
    fi
    
    # 清理构建缓存 (如果指定)
    if [[ "$CLEAN_BUILD" == "true" ]]; then
        clean_build_cache
    fi
    
    log_success "构建环境准备完成"
}

# 清理构建缓存
clean_build_cache() {
    log_info "清理构建缓存..."
    
    # 清理Docker构建缓存
    log_debug "清理Docker构建缓存..."
    docker builder prune -f
    
    # 清理Maven缓存 (如果存在)
    if command -v mvn &> /dev/null; then
        log_debug "清理Maven缓存..."
        cd "$PROJECT_ROOT"
        mvn clean -q
    fi
    
    # 清理npm缓存 (如果存在)
    if command -v npm &> /dev/null; then
        log_debug "清理npm缓存..."
        cd "${PROJECT_ROOT}/RuoYi-Vue3"
        if [[ -d "node_modules" ]]; then
            rm -rf node_modules
        fi
        if [[ -f "package-lock.json" ]]; then
            rm -f package-lock.json
        fi
    fi
    
    log_success "构建缓存清理完成"
}

# ===========================================
# 镜像构建功能 (Requirement 5.1)
# ===========================================
build_frontend_image() {
    log_step "构建前端镜像..."
    
    # 根据环境设置镜像标签
    local env_tag
    case $ENVIRONMENT in
        production) env_tag="prod" ;;
        staging) env_tag="staging" ;;
        development) env_tag="dev" ;;
    esac
    
    local image_name="${FRONTEND_IMAGE}:${env_tag}"
    local dockerfile_path="${DOCKER_DIR}/frontend/Dockerfile"
    local build_args=""
    
    # 根据环境设置构建参数
    case $ENVIRONMENT in
        production)
            build_args="--build-arg NODE_ENV=production --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080} --build-arg ENVIRONMENT=prod"
            ;;
        staging)
            build_args="--build-arg NODE_ENV=production --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080} --build-arg ENVIRONMENT=staging"
            ;;
        development)
            build_args="--build-arg NODE_ENV=development --build-arg API_BASE_URL=${API_BASE_URL:-http://localhost:8080} --build-arg ENVIRONMENT=dev"
            ;;
    esac
    
    # 构建命令
    local build_cmd="docker build -f $dockerfile_path -t $image_name $build_args"
    
    if [[ "$NO_CACHE" == "true" ]]; then
        build_cmd="$build_cmd --no-cache"
    fi
    
    build_cmd="$build_cmd $PROJECT_ROOT"
    
    log_info "构建前端镜像: $image_name"
    log_debug "构建命令: $build_cmd"
    
    if eval "$build_cmd"; then
        # 如果指定了自定义标签，也打上自定义标签
        if [[ "$TAG" != "latest" && "$TAG" != "$env_tag" ]]; then
            local custom_image_name="${FRONTEND_IMAGE}:${TAG}"
            log_info "添加自定义标签: $custom_image_name"
            docker tag "$image_name" "$custom_image_name"
        fi
        
        log_success "前端镜像构建成功: $image_name"
        
        # 显示镜像信息
        local image_size=$(docker images --format "table {{.Size}}" "$image_name" | tail -n 1)
        log_info "镜像大小: $image_size"
        
        return 0
    else
        log_error "前端镜像构建失败"
        return 1
    fi
}

build_backend_image() {
    log_step "构建后端镜像..."
    
    # 根据环境设置镜像标签
    local env_tag
    case $ENVIRONMENT in
        production) env_tag="prod" ;;
        staging) env_tag="staging" ;;
        development) env_tag="dev" ;;
    esac
    
    local image_name="${BACKEND_IMAGE}:${env_tag}"
    local dockerfile_path="${DOCKER_DIR}/backend/Dockerfile"
    local build_args=""
    
    # 根据环境设置构建参数
    case $ENVIRONMENT in
        production)
            build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,prod"
            ;;
        staging)
            build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,staging"
            ;;
        development)
            build_args="--build-arg SPRING_PROFILES_ACTIVE=docker,dev"
            ;;
    esac
    
    # 构建命令
    local build_cmd="docker build -f $dockerfile_path -t $image_name $build_args"
    
    if [[ "$NO_CACHE" == "true" ]]; then
        build_cmd="$build_cmd --no-cache"
    fi
    
    build_cmd="$build_cmd $PROJECT_ROOT"
    
    log_info "构建后端镜像: $image_name"
    log_debug "构建命令: $build_cmd"
    
    if eval "$build_cmd"; then
        # 如果指定了自定义标签，也打上自定义标签
        if [[ "$TAG" != "latest" && "$TAG" != "$env_tag" ]]; then
            local custom_image_name="${BACKEND_IMAGE}:${TAG}"
            log_info "添加自定义标签: $custom_image_name"
            docker tag "$image_name" "$custom_image_name"
        fi
        
        log_success "后端镜像构建成功: $image_name"
        
        # 显示镜像信息
        local image_size=$(docker images --format "table {{.Size}}" "$image_name" | tail -n 1)
        log_info "镜像大小: $image_size"
        
        return 0
    else
        log_error "后端镜像构建失败"
        return 1
    fi
}

# 构建所有镜像
build_all_images() {
    log_step "开始构建所有镜像..."
    
    local build_start_time=$(date +%s)
    local failed_builds=()
    
    # 构建前端镜像
    if ! build_frontend_image; then
        failed_builds+=("frontend")
    fi
    
    # 构建后端镜像
    if ! build_backend_image; then
        failed_builds+=("backend")
    fi
    
    # 拉取MySQL镜像
    log_info "拉取MySQL镜像: $MYSQL_IMAGE"
    if docker pull "$MYSQL_IMAGE"; then
        log_success "MySQL镜像拉取成功"
    else
        log_warn "MySQL镜像拉取失败，将使用本地镜像"
    fi
    
    local build_end_time=$(date +%s)
    local build_duration=$((build_end_time - build_start_time))
    
    # 构建结果汇总
    if [[ ${#failed_builds[@]} -eq 0 ]]; then
        log_success "所有镜像构建成功! 耗时: ${build_duration}秒"
        show_build_summary
        return 0
    else
        log_error "以下镜像构建失败: ${failed_builds[*]}"
        return 1
    fi
}

# 显示构建摘要
show_build_summary() {
    log_info "构建摘要:"
    echo "----------------------------------------"
    docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}" | grep -E "(anxin-|REPOSITORY)"
    echo "----------------------------------------"
}

# ===========================================
# 部署功能
# ===========================================
deploy_to_environment() {
    log_step "部署到 $ENVIRONMENT 环境..."
    
    local compose_file="${DOCKER_DIR}/docker-compose.${ENVIRONMENT}.yml"
    local env_file="${DOCKER_DIR}/environments/.env.${ENVIRONMENT}"
    
    # 检查文件是否存在
    if [[ ! -f "$compose_file" ]]; then
        log_error "Docker Compose文件不存在: $compose_file"
        return 1
    fi
    
    if [[ ! -f "$env_file" ]]; then
        log_error "环境配置文件不存在: $env_file"
        return 1
    fi
    
    # 停止现有服务
    log_info "停止现有服务..."
    cd "$DOCKER_DIR"
    docker-compose -f "$compose_file" --env-file "$env_file" down --remove-orphans || true
    
    # 启动新服务
    log_info "启动服务..."
    if docker-compose -f "$compose_file" --env-file "$env_file" up -d; then
        log_success "服务启动成功"
        
        # 等待服务就绪
        log_info "等待服务就绪..."
        sleep 15
        
        # 检查服务状态
        check_deployment_status "$compose_file" "$env_file"
        
        return 0
    else
        log_error "服务启动失败"
        return 1
    fi
}

# 检查部署状态
check_deployment_status() {
    local compose_file="$1"
    local env_file="$2"
    
    log_info "检查服务状态..."
    
    cd "$DOCKER_DIR"
    docker-compose -f "$compose_file" --env-file "$env_file" ps
    
    # 健康检查
    local services=("anxin-mysql" "anxin-backend" "anxin-frontend")
    local healthy_count=0
    
    for service in "${services[@]}"; do
        local container_name="${service}-${ENVIRONMENT}"
        if docker ps --format "{{.Names}}" | grep -q "$service"; then
            local health=$(docker inspect --format='{{.State.Health.Status}}' "$service" 2>/dev/null || echo "no-healthcheck")
            case $health in
                "healthy"|"no-healthcheck")
                    log_success "✓ $service: 运行正常"
                    ((healthy_count++))
                    ;;
                "starting")
                    log_warn "⚠ $service: 正在启动中..."
                    ;;
                *)
                    log_error "✗ $service: 健康检查失败 ($health)"
                    ;;
            esac
        else
            log_error "✗ $service: 容器未运行"
        fi
    done
    
    if [[ $healthy_count -eq ${#services[@]} ]]; then
        log_success "所有服务运行正常"
        show_access_info
    else
        log_warn "部分服务可能存在问题，请检查日志"
    fi
}

# 显示访问信息
show_access_info() {
    log_info "服务访问信息:"
    echo "----------------------------------------"
    echo "前端应用: http://localhost:${FRONTEND_PORT:-80}"
    echo "后端API:  http://localhost:${BACKEND_PORT:-8080}"
    echo "数据库:   localhost:${DB_PORT:-3306}"
    echo "----------------------------------------"
    echo "查看日志: docker-compose -f docker-compose.${ENVIRONMENT}.yml logs -f"
    echo "停止服务: docker-compose -f docker-compose.${ENVIRONMENT}.yml down"
    echo "----------------------------------------"
}

# ===========================================
# 状态检查
# ===========================================
show_status() {
    log_info "当前构建状态:"
    echo "----------------------------------------"
    echo "环境: $ENVIRONMENT"
    echo "标签: $TAG"
    echo "项目根目录: $PROJECT_ROOT"
    echo "Docker目录: $DOCKER_DIR"
    echo "----------------------------------------"
    
    log_info "Docker镜像:"
    docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedAt}}\t{{.Size}}" | grep -E "(anxin-|REPOSITORY)" || echo "未找到相关镜像"
    
    log_info "运行中的容器:"
    docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep -E "(anxin-|NAMES)" || echo "未找到相关容器"
}

# ===========================================
# 清理功能
# ===========================================
clean_all() {
    log_step "清理所有构建产物和缓存..."
    
    # 停止所有相关容器
    log_info "停止相关容器..."
    docker ps -a --format "{{.Names}}" | grep "anxin-" | xargs -r docker stop
    docker ps -a --format "{{.Names}}" | grep "anxin-" | xargs -r docker rm
    
    # 删除相关镜像
    log_info "删除相关镜像..."
    docker images --format "{{.Repository}}:{{.Tag}}" | grep "anxin-" | xargs -r docker rmi -f
    
    # 清理构建缓存
    clean_build_cache
    
    # 清理数据目录 (谨慎操作)
    read -p "是否清理数据目录? 这将删除所有持久化数据 (y/N): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        log_warn "清理数据目录..."
        rm -rf "${DOCKER_DIR}/data"
        mkdir -p "${DOCKER_DIR}/data"
    fi
    
    log_success "清理完成"
}

# ===========================================
# 主函数
# ===========================================
main() {
    # 显示脚本信息
    log_info "若依框架Docker部署 - 主构建脚本"
    log_info "脚本版本: 1.0.0"
    log_info "执行时间: $(date '+%Y-%m-%d %H:%M:%S')"
    
    # 解析参数
    parse_args "$@"
    
    # 验证环境
    validate_environment
    
    # 加载环境配置
    load_environment_config
    
    # 检查系统依赖
    check_prerequisites
    
    # 根据命令执行相应操作
    case $COMMAND in
        pull)
            pull_latest_code
            ;;
        build)
            if [[ "$PULL_CODE" == "true" ]]; then
                pull_latest_code
            fi
            prepare_build
            
            case $COMPONENT in
                frontend)
                    build_frontend_image
                    ;;
                backend)
                    build_backend_image
                    ;;
                all)
                    build_all_images
                    ;;
                *)
                    log_error "无效的组件: $COMPONENT"
                    exit 1
                    ;;
            esac
            ;;
        build-all)
            if [[ "$PULL_CODE" == "true" ]]; then
                pull_latest_code
            fi
            prepare_build
            build_all_images
            ;;
        deploy)
            if [[ "$PULL_CODE" == "true" ]]; then
                pull_latest_code
            fi
            prepare_build
            build_all_images
            if [[ $? -eq 0 ]]; then
                deploy_to_environment
            else
                log_error "构建失败，取消部署"
                exit 1
            fi
            ;;
        status)
            show_status
            ;;
        clean)
            clean_all
            ;;
        *)
            log_error "未知命令: $COMMAND"
            show_help
            exit 1
            ;;
    esac
    
    log_success "脚本执行完成!"
}

# ===========================================
# 错误处理
# ===========================================
trap 'log_error "脚本执行被中断"; exit 1' INT TERM

# 执行主函数
main "$@"