#!/usr/bin/env bash

set -Eeuo pipefail

# =================配置参数=================
DEFAULT_MAX_DEPTH=3
DEFAULT_IGNORE_DIR="compose-ignore"
# =========================================

# 变量初始化
: "${MAX_DEPTH:=$DEFAULT_MAX_DEPTH}"
: "${IGNORE_DIR:=$DEFAULT_IGNORE_DIR}"
COMPOSE_CMD=""
SCRIPT_START_TIME=$(date +%s)

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

# 状态图标
ICON_SUCCESS="✅"
ICON_FAIL="❌"
ICON_WARN="⚠️"
ICON_INFO="ℹ️"
ICON_PKG="📦"
ICON_TIME="⏱️"

# 捕获中断信号
trap 'echo -e "\n${RED}[!] 用户取消操作，正在退出...${NC}"; exit 1' SIGINT SIGTERM

# 辅助函数：打印带颜色的消息
print_info() { echo -e "${BLUE}${ICON_INFO} [INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}${ICON_SUCCESS} [SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}${ICON_WARN} [WARNING]${NC} $1"; }
print_error() { echo -e "${RED}${ICON_FAIL} [ERROR]${NC} $1"; }
print_header() { echo -e "\n${MAGENTA}${BOLD}$1${NC}"; }
print_line() { echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; print_line_end; }
print_line_end() { echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; }

# 显示帮助信息
show_help() {
    print_header "🐳 Docker Compose 自动管理工具"
    echo -e "${BOLD}用法:${NC}"
    echo "  $0 [命令]"
    echo ""
    echo -e "${BOLD}命令:${NC}"
    printf "  %-15s - %s\n" "update" "更新所有服务 (pull + down + up)"
    printf "  %-15s - %s\n" "down" "停止所有服务"
    printf "  %-15s - %s\n" "up" "启动所有服务 (up -d)"
    printf "  %-15s - %s\n" "list" "列出所有compose文件"
    printf "  %-15s - %s\n" "help" "显示此帮助信息"
    printf "  %-15s - %s\n" "alias-setup" "配置别名 'cpman' 以简化调用"
    printf "  %-15s - %s\n" "(无参数)" "进入交互式菜单"
    echo ""
    echo -e "${BOLD}环境变量:${NC}"
    echo "  MAX_DEPTH=N      - 设置搜索深度(默认:$DEFAULT_MAX_DEPTH)"
    echo "  IGNORE_DIR=name  - 设置忽略目录(默认:$DEFAULT_IGNORE_DIR)"
    echo ""
    echo -e "${BOLD}示例:${NC}"
    local script_url="https://www.mgrsc.top/http/linux/sh/cpman.sh"
    echo "  # 交互模式"
    echo "  bash <(curl -fsSL $script_url)"
    echo ""
    echo "  # 直接更新"
    echo "  bash <(curl -fsSL $script_url) update"
    echo ""
    echo "  # 自定义深度和忽略目录"
    echo "  MAX_DEPTH=5 bash <(curl -fsSL $script_url) update"
    echo ""
    echo "  # 配置别名"
    echo "  bash <(curl -fsSL $script_url) alias-setup"
    echo ""
}

# 计算耗时
format_time() {
    local duration=$1
    if (( duration < 60 )); then
        echo "${duration}s"
    else
        echo "$((duration / 60))m $((duration % 60))s"
    fi
}

# 检测 Compose 命令
detect_compose_command() {
    if command -v docker &> /dev/null && docker compose version &> /dev/null; then
        COMPOSE_CMD="docker compose"
    elif command -v docker-compose &> /dev/null; then
        COMPOSE_CMD="docker-compose"
    elif command -v podman &> /dev/null && podman compose version &> /dev/null; then
        COMPOSE_CMD="podman compose"
    else
        print_error "未找到可用的 Compose 命令 (docker compose / docker-compose / podman compose)"
        exit 1
    fi
    # 不再打印检测信息，保持清爽，除非出错
}

# 查找 Compose 文件
find_compose_files() {
    local search_dir="${1:-.}"
    local -n result=$2

    print_info "正在搜索 Compose 文件 (深度: $MAX_DEPTH)..."

    # 使用 mapfile 提高效率 (Bash 4.0+)
    # 排除 IGNORE_DIR
    if mapfile -d $'\0' result < <(find "$search_dir" -maxdepth "$MAX_DEPTH" -type f \
        \( -name "compose.yaml" -o -name "compose.yml" -o \
           -name "docker-compose.yaml" -o -name "docker-compose.yml" \) \
        -not -path "*/$IGNORE_DIR/*" -print0 2>/dev/null); then
        : # Success
    else
        # Fallback for older bash
        while IFS= read -r -d '' file; do
            result+=("$file")
        done < <(find "$search_dir" -maxdepth "$MAX_DEPTH" -type f \
            \( -name "compose.yaml" -o -name "compose.yml" -o \
            -name "docker-compose.yaml" -o -name "docker-compose.yml" \) \
            -not -path "*/$IGNORE_DIR/*" -print0 2>/dev/null)
    fi

    if [ ${#result[@]} -eq 0 ]; then
        print_warning "未找到任何 Compose 文件"
        return 0
    fi

    print_success "找到 ${#result[@]} 个服务配置文件"
}

# 显示文件列表
show_files() {
    local -n files=$1
    print_header "📋 服务列表:"
    local idx=1
    for file in "${files[@]}"; do
        printf "  ${CYAN}%-3s${NC} %s\n" "$idx." "$file"
        ((idx++))
    done
    echo ""
}

# 核心：执行更新
update_all() {
    local -n files=$1
    local -a report_success=()
    local -a report_failed=()
    local total=${#files[@]}
    local current=1

    print_header "🚀 开始更新所有服务..."

    for file in "${files[@]}"; do
        local start_t
        start_t=$(date +%s)
        local dir
        dir=$(dirname "$file")
        local filename
        filename=$(basename "$file")

        print_line
        echo -e "${BOLD}${ICON_PKG} [$current/$total] 正在处理: ${BLUE}$dir${NC}"

        local step_failed=false
        local err_msg=""

        # 1. Pull (关键修复：添加 < /dev/null)
        echo -n "  🔹 拉取镜像... "
        if output=$(cd "$dir" && $COMPOSE_CMD -f "$filename" pull 2>&1 < /dev/null); then
            echo -e "${GREEN}完成${NC}"
        else
            echo -e "${RED}失败${NC}"
            echo -e "${YELLOW}--- 错误日志 ---${NC}"
            echo "$output"
            echo -e "${YELLOW}----------------${NC}"
            step_failed=true
            err_msg="镜像拉取失败"
        fi

        # 2. Down (如果拉取没严重错误)
        if [ "$step_failed" = false ]; then
            echo -n "  🔹 停止服务... "
            if (cd "$dir" && $COMPOSE_CMD -f "$filename" down 2>&1 < /dev/null) >/dev/null; then
                echo -e "${GREEN}完成${NC}"
            else
                echo -e "${RED}失败${NC}"
                step_failed=true
                err_msg="停止服务失败"
            fi
        fi

        # 3. Up
        if [ "$step_failed" = false ]; then
            echo -n "  🔹 启动服务... "
            if (cd "$dir" && $COMPOSE_CMD -f "$filename" up -d 2>&1 < /dev/null) >/dev/null; then
                echo -e "${GREEN}完成${NC}"
            else
                echo -e "${RED}失败${NC}"
                step_failed=true
                err_msg="启动服务失败"
            fi
        fi

        local end_t
        end_t=$(date +%s)
        local duration=$((end_t - start_t))

        if [ "$step_failed" = false ]; then
            report_success+=("$dir ($(format_time $duration))")
        else
            report_failed+=("$dir - $err_msg")
        fi

        ((current++))
    done

    print_summary report_success report_failed
}

# 停止所有
down_all() {
    local -n files=$1
    local -a report_success=()
    local -a report_failed=()

    for file in "${files[@]}"; do
        local dir
        dir=$(dirname "$file")
        local filename
        filename=$(basename "$file")

        echo -n "🛑 停止 $dir ... "
        if (cd "$dir" && $COMPOSE_CMD -f "$filename" down 2>&1 < /dev/null) >/dev/null; then
            echo -e "${GREEN}成功${NC}"
            report_success+=("$dir")
        else
            echo -e "${RED}失败${NC}"
            report_failed+=("$dir")
        fi
    done

    # 简易汇总
    echo ""
    print_line
    echo -e "停止完成: ${GREEN}${ICON_SUCCESS} ${#report_success[@]}${NC} | ${RED}${ICON_FAIL} ${#report_failed[@]}${NC}"
}

# 启动所有
up_all() {
    local -n files=$1
    local -a report_success=()
    local -a report_failed=()

    for file in "${files[@]}"; do
        local dir
        dir=$(dirname "$file")
        local filename
        filename=$(basename "$file")

        echo -n "🚀 启动 $dir ... "
        if (cd "$dir" && $COMPOSE_CMD -f "$filename" up -d 2>&1 < /dev/null) >/dev/null; then
            echo -e "${GREEN}成功${NC}"
            report_success+=("$dir")
        else
            echo -e "${RED}失败${NC}"
            report_failed+=("$dir")
        fi
    done
}

# 打印精美汇总表
print_summary() {
    local -n success=$1
    local -n failed=$2
    local total_time=$(($(date +%s) - SCRIPT_START_TIME))

    echo ""
    print_header "📊 执行报告"
    print_line
    printf "${BOLD}%-35s %-10s${NC}\n" "服务路径" "状态"
    print_line

    for item in "${success[@]}"; do
        printf "%-35s ${GREEN}✅ 成功${NC}\n" "$item"
    done

    for item in "${failed[@]}"; do
        printf "%-35s ${RED}❌ 失败${NC}\n" "$item"
    done

    print_line
    echo -e "总耗时: ${ICON_TIME} ${YELLOW}$(format_time $total_time)${NC} | 成功: ${GREEN}${#success[@]}${NC} | 失败: ${RED}${#failed[@]}${NC}"
    print_line
    echo ""
}

# 配置别名
setup_alias() {
    local alias_name="cpman"
    local script_url="https://www.mgrsc.top/http/linux/sh/cpman.sh"
    local alias_cmd="alias $alias_name='bash <(curl -fsSL $script_url)'"
    local config_file=""

    print_header "⚙️ 配置别名: $alias_name"

    # 1. 确定 Shell 配置文件
    if [[ "$SHELL" =~ "zsh" ]]; then
        config_file="$HOME/.zshrc"
    elif [[ "$SHELL" =~ "bash" ]]; then
        # 如果存在 .bash_profile 且 .bashrc 不存在，则使用 .bash_profile
        if [ -f "$HOME/.bash_profile" ] && [ ! -f "$HOME/.bashrc" ]; then
            config_file="$HOME/.bash_profile"
        else
            config_file="$HOME/.bashrc"
        fi
    else
        print_error "不支持或无法识别您的 Shell ($SHELL)。请手动将别名添加到您的配置文件中。"
        echo "别名命令: $alias_cmd"
        return 1
    fi

    print_info "检测到 Shell: $SHELL"
    print_info "目标配置文件: $config_file"

    if [ ! -f "$config_file" ]; then
        print_warning "配置文件 $config_file 不存在，将创建它。"
        touch "$config_file"
    fi

    # 2. 检查是否已存在别名
    if grep -q "alias $alias_name=" "$config_file"; then
        # 如果存在，则更新
        sed -i "/alias $alias_name=/c\\$alias_cmd" "$config_file"
        print_success "别名 '$alias_name' 已在 $config_file 中更新。"
    else
        # 如果不存在，则追加
        echo -e "\n# Docker Compose Manager Alias" >> "$config_file"
        echo "$alias_cmd" >> "$config_file"
        print_success "别名 '$alias_name' 已添加到 $config_file。"
    fi

    print_line
    print_info "请执行以下命令使别名立即生效:"
    echo -e "${YELLOW}source $config_file${NC}"
    print_line

    return 0
}

# 菜单
show_menu() {
    print_header "🐳 Docker Compose 批量管理工具"
    echo "1. 🔄 更新 (Pull -> Down -> Up)"
    echo "2. 🛑 停止 (Down)"
    echo "3. 🚀 启动 (Up -d)"
    echo "4. 🔍 重新扫描"
    echo "5. 🚪 退出"
    echo -n "请输入选项 [1-5]: "
}

# 主逻辑
main() {
    local compose_files=()
    local command="${1:-interactive}"

    # 1. 立即处理非操作命令 (help, alias-setup)
    case "$command" in
        help)
            show_help
            exit 0
            ;;
        alias-setup)
            setup_alias
            exit 0
            ;;
        *)
            # 对于需要操作的命令，继续执行初始化
            ;;
    esac

    # 2. 检查 Docker Compose 命令
    detect_compose_command

    # 3. 查找 Compose 文件
    find_compose_files "." compose_files

    if [ ${#compose_files[@]} -eq 0 ] && [[ "$command" != "interactive" ]]; then
        print_warning "未找到任何 Compose 文件，且未进入交互模式，脚本退出。"
        exit 0
    fi

    # 4. 执行操作命令
    case "$command" in
        update)
            show_files compose_files
            update_all compose_files
            ;;
        down)
            show_files compose_files
            down_all compose_files
            ;;
        up)
            show_files compose_files
            up_all compose_files
            ;;
        list)
            show_files compose_files
            ;;
        interactive)
            show_files compose_files
            while true; do
                show_menu
                read -r choice
                case $choice in
                    1) update_all compose_files ;;
                    2) down_all compose_files ;;
                    3) up_all compose_files ;;
                    4)
                       compose_files=()
                       find_compose_files "." compose_files
                       show_files compose_files
                       ;;
                    5) exit 0 ;;
                    *) print_error "无效输入" ;;
                esac
            done
            ;;
        *)
            print_error "无效命令: $command"
            echo "请使用 '$0 help' 查看完整用法。"
            exit 1
            ;;
    esac
}

main "$@"

