#!/bin/bash
stty erase ^? 2>/dev/null || true
stty erase ^H 2>/dev/null || true
set -e

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'
BLUE='\033[0;34m'; PURPLE='\033[0;35m'; CYAN='\033[0;36m'
BOLD='\033[1m'; NC='\033[0m'

SSL_DIR="/etc/nginx/ssl"
SSL_OUT_DIR="$(dirname "$(readlink -f "$0")")/ssl_out"

detect_nginx_user() {
    if [ -f /etc/debian_version ]; then
        NGINX_USER="www-data"
    else
        NGINX_USER="nginx"
    fi
}

ensure_nginx() {
    if ! command -v nginx >/dev/null 2>&1; then
        echo -e "${YELLOW}[+] 未检测到 Nginx，正在安装...${NC}"
        if command -v apt-get >/dev/null 2>&1; then
            apt-get update -y >/dev/null 2>&1 && apt-get install -y nginx >/dev/null 2>&1
        elif command -v yum >/dev/null 2>&1; then
            yum install -y nginx >/dev/null 2>&1
        elif command -v dnf >/dev/null 2>&1; then
            dnf install -y nginx >/dev/null 2>&1
        else
            echo -e "${RED}[-] 未安装 Nginx 且无法自动安装${NC}"
            exit 1
        fi
        if ! command -v nginx >/dev/null 2>&1; then
            echo -e "${RED}[-] Nginx 安装失败，请手动安装后重试${NC}"
            exit 1
        fi
        echo -e "${GREEN}[✔] Nginx 安装完成${NC}"
    fi
    mkdir -p /etc/nginx/conf.d
}

deploy_certs() {
    local domain="$1"
    local src="${SSL_OUT_DIR}/${domain}"
    local dst="${SSL_DIR}/${domain}"

    if [ ! -f "$src/fullchain.pem" ] || [ ! -f "$src/privkey.pem" ]; then
        echo -e "${RED}[-] 证书文件不存在: ${src}/${NC}"
        return 1
    fi

    detect_nginx_user
    mkdir -p "$dst"
    cp -f "$src/fullchain.pem" "$dst/fullchain.pem"
    cp -f "$src/privkey.pem" "$dst/privkey.pem"
    chown -R "${NGINX_USER}:${NGINX_USER}" "$dst"
    chmod 644 "$dst/fullchain.pem"
    chmod 600 "$dst/privkey.pem"

    if command -v nginx >/dev/null 2>&1; then
        nginx -t >/tmp/nginx_test.log 2>&1 || {
            echo -e "${RED}[-] nginx 配置测试失败，证书已复制但未重载${NC}"
            tail -n 3 /tmp/nginx_test.log | sed 's/^/    /'
            return 0
        }
        nginx -s reload >/dev/null 2>&1
    fi
    echo -e "${GREEN}[✔] 证书已部署: ${dst}/ （已生效）${NC}"
    return 0
}

# 确保 /data 对 nginx 可遍历与读取（目录 setgid + setfacl 默认 ACL 继承）
# 让脚本可脱离 nginx.sh 独立工作，今后新增文件/目录自动对 nginx 可读
ensure_data_perms() {
    mkdir -p /data
    detect_nginx_user
    chown -R "${NGINX_USER}:${NGINX_USER}" /data 2>/dev/null || true
    find /data -type d -exec chmod 2755 {} + 2>/dev/null || true
    find /data -type f -exec chmod 644 {} + 2>/dev/null || true
    if command -v setfacl >/dev/null 2>&1; then
        setfacl -R -m u:"${NGINX_USER}":rwx /data 2>/dev/null || true
        setfacl -d -m u:"${NGINX_USER}":rwx /data 2>/dev/null || true
        setfacl -d -m g::r-x /data 2>/dev/null || true
        setfacl -d -m o::r-x /data 2>/dev/null || true
    fi
}

create_static_site() {
    local domain="$1"
    local conf="/etc/nginx/conf.d/${domain}.conf"
    local bak=""

    ensure_nginx
    mkdir -p /data
    ensure_data_perms

    if [ -f "$conf" ]; then
        bak="${conf}.bak.$(date +%Y%m%d_%H%M%S)"
        cp -a "$conf" "$bak"
    fi

    cat > "$conf" << EOF
# ssltool: static
server {
    listen 80;
    listen [::]:80;
    server_name ${domain};
    return 301 https://\$host\$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name ${domain};

    ssl_certificate     ${SSL_DIR}/${domain}/fullchain.pem;
    ssl_certificate_key ${SSL_DIR}/${domain}/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;

    root /data;

    index index.html index.htm;

    location / {
        try_files \$uri \$uri/ =404;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        charset utf-8;

        if (\$request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|mp4|mp3|avi|mkv|mov|flv|wmv|wav|flac|aac|iso|img)\$) {
            add_header Content-Disposition attachment;
        }

        index none;
    }
}
EOF

    if command -v nginx >/dev/null 2>&1; then
        nginx -t >/tmp/nginx_test.log 2>&1 || {
            echo -e "${RED}[-] nginx 配置测试失败，已回滚${NC}"
            tail -n 3 /tmp/nginx_test.log | sed 's/^/    /'
            rm -f "$conf"
            [ -n "$bak" ] && cp -a "$bak" "$conf"
            return 1
        }
        nginx -s reload >/dev/null 2>&1
    fi
    echo -e "${GREEN}[✔] 站点已创建: https://${domain}/ （/data 静态下载站，一台服务器可挂多个域名证书）${NC}"
    return 0
}

# ==========================================
# 命令行模式：--deploy <域名> / --site <域名>
# --deploy: acme.sh 续期成功后自动调用，重新部署证书
# --site:   创建该域名的静态下载站点（/data）
# ==========================================
if [ "$1" = "--deploy" ] && [ -n "$2" ]; then
    deploy_certs "$2"
    exit $?
fi
if [ "$1" = "--site" ] && [ -n "$2" ]; then
    create_static_site "$2"
    exit $?
fi

CF_ROOT_DOMAIN="anwing.me"
ALI_ROOT_DOMAIN="mbvpn.cn"
CF_TOKEN="cfat_g74NHibtCYbD8pJWbD5rB5Mf1jRO0k7DRKkZ1eZY8e9fc9e3"
ALI_KEY="LTAI5t61Lv6i66p8j6UCAe32"
ALI_SECRET="BSWR46pJ7EdKXAVpnuvVEWaQspnJyT"

ACME=""

# ==========================================
# 通用函数
# ==========================================

install_acme() {
    local _mail="admin@$(date +%s).com"
    local tmp="$(mktemp)"

    # 本机已有 acme.sh 则直接复用，不重复下载
    local cand=""
    for cand in "$HOME/.acme.sh/acme.sh" "/data/ssl/.acme.sh/acme.sh"; do
        if [ -x "$cand" ]; then
            ACME="$cand"
            echo -e "${GREEN}[✔] 检测到本机已有 acme.sh，跳过下载${NC}"
            return 0
        fi
    done

    # 国内机器：igz 域名(https) → igz IP(http，IP 直连不查 Host/SNI) → 海外 ipan 兜底
    local mirrors=(
        "https://igz.mbvpn.cn/ssl/acme.sh.tar.gz"
        "http://8.134.160.125/ssl/acme.sh.tar.gz"
        "https://ipan.mbvpn.cn/ssl/acme.sh.tar.gz"
    )
    local m_url=""
    for m_url in "${mirrors[@]}"; do
        echo -e "${CYAN}[+] 尝试从镜像拉取 acme.sh: ${m_url}${NC}"
        rm -f "$tmp"
        if curl -fL -k --connect-timeout 8 --max-time 60 "$m_url" -o "$tmp" 2>/dev/null && [ -s "$tmp" ]; then
            rm -rf "$HOME/.acme.sh"
            mkdir -p "$HOME/.acme.sh"
            if tar -xzf "$tmp" --strip-components=1 -C "$HOME/.acme.sh" 2>/dev/null && [ -x "$HOME/.acme.sh/acme.sh" ]; then
                chmod +x "$HOME/.acme.sh/acme.sh"
                rm -f "$tmp"
                ACME="$HOME/.acme.sh/acme.sh"
                echo -e "${GREEN}[✔] acme.sh 已从镜像安装: ${m_url}${NC}"
                return 0
            fi
            rm -rf "$HOME/.acme.sh"
        fi
        rm -f "$tmp"
        echo -e "${YELLOW}[!] ${m_url} 拉取失败，换下一个源...${NC}"
    done

    # 镜像不可用时：已有 acme.sh 则直接复用，不重新在线安装
    if [ -f "$HOME/.acme.sh/acme.sh" ]; then
        ACME="$HOME/.acme.sh/acme.sh"
        echo -e "${GREEN}[✔] 镜像不可用，复用本机已有 acme.sh${NC}"
        return 0
    fi

    # 镜像不可用且本机无 acme.sh 时回退官方在线安装
    _try() {
        local url="$1" mode="$2" label="$3"
        rm -f "$tmp"
        echo -e "${CYAN}[+] 尝试安装源: ${label}${NC}"
        if curl -fsSL --connect-timeout 8 --max-time 60 "$url" -o "$tmp" && [ -s "$tmp" ]; then
            if [ "$mode" = "bootstrap" ]; then
                sh "$tmp" email="$_mail" --nocron 2>/dev/null
            else
                sh "$tmp" --install -m "$_mail" --nocron 2>/dev/null
            fi
            [ -f "$HOME/.acme.sh/acme.sh" ]
            return $?
        fi
        echo -e "${YELLOW}[!] ${label} 下载失败，换下一个源...${NC}"
        return 1
    }

    if curl -fsI --connect-timeout 3 --max-time 5 "https://gitee.com" >/dev/null 2>&1; then
        _try "https://gitee.com/neilpang/acme.sh/raw/master/acme.sh" raw "Gitee" || \
        _try "https://get.acme.sh" bootstrap "get.acme.sh" || \
        _try "https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh" raw "GitHub" || true
    else
        _try "https://get.acme.sh" bootstrap "get.acme.sh" || \
        _try "https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh" raw "GitHub" || \
        _try "https://gitee.com/neilpang/acme.sh/raw/master/acme.sh" raw "Gitee" || true
    fi

    rm -f "$tmp"
    if [ -f "$HOME/.acme.sh/acme.sh" ]; then
        ACME="$HOME/.acme.sh/acme.sh"
        return 0
    fi
    return 1
}

ensure_acme() {
    # 一律先走镜像拉取更新；镜像不可用且本机已有时自动复用
    install_acme || {
        echo -e "${RED}[-] acme.sh 安装失败${NC}"; exit 1
    }
    if [ -z "$ACME" ]; then
        if [ -f "$HOME/.acme.sh/acme.sh" ]; then
            ACME="$HOME/.acme.sh/acme.sh"
        elif [ -f "/data/ssl/.acme.sh/acme.sh" ]; then
            ACME="/data/ssl/.acme.sh/acme.sh"
        elif command -v acme.sh >/dev/null 2>&1; then
            ACME="acme.sh"
        fi
    fi
    echo -e "${GREEN}[✔] acme.sh 就绪: ${ACME}${NC}"
    "$ACME" --set-default-ca --server letsencrypt >/dev/null 2>&1 || true
    setup_renewal
}

# ==========================================
# 证书自动续期
# ==========================================

setup_renewal() {
    "$ACME" --install-cronjob >/dev/null 2>&1 || true
    if crontab -l 2>/dev/null | grep -q "acme.sh.*--cron"; then
        echo -e "${GREEN}[✔] 已启用自动续期：每日检测，到期前自动续签并重新部署${NC}"
    else
        echo -e "${YELLOW}[!] 自动续期 cron 未生效，请手动执行: ${ACME} --install-cronjob${NC}"
    fi
}

detect_provider() {
    local domain="$1"
    case "$domain" in
        *.$CF_ROOT_DOMAIN|$CF_ROOT_DOMAIN)
            ROOT_DOMAIN="$CF_ROOT_DOMAIN"
            DNS_MODE="dns_cf"
            export CF_Token="$CF_TOKEN"
            PLATFORM_NAME="Cloudflare"
            SUB_DOMAIN=$(echo "$domain" | sed "s/\.${CF_ROOT_DOMAIN}$//")
            [ "$SUB_DOMAIN" = "$domain" ] && SUB_DOMAIN="@"
            return 0
            ;;
        *.$ALI_ROOT_DOMAIN|$ALI_ROOT_DOMAIN)
            ROOT_DOMAIN="$ALI_ROOT_DOMAIN"
            DNS_MODE="dns_ali"
            export Ali_Key="$ALI_KEY"
            export Ali_Secret="$ALI_SECRET"
            PLATFORM_NAME="阿里云 DNS"
            SUB_DOMAIN=$(echo "$domain" | sed "s/\.${ALI_ROOT_DOMAIN}$//")
            [ "$SUB_DOMAIN" = "$domain" ] && SUB_DOMAIN="@"
            return 0
            ;;
    esac
    return 1
}

select_provider() {
    # $1 = 调用方模式：cert（模式1） / proxy（模式2），用于区分删除行为
    # 返回 0 = 已选择服务商（设置 DNS_MODE/ROOT_DOMAIN/PLATFORM_NAME 并导出凭据）
    # 返回 1 = 选择返回上级菜单
    local caller_mode="${1:-cert}"
    while true; do
        echo -e "\n${BOLD}请选择域名解析服务商：${NC}"
        echo -e "  ${GREEN}[1]${NC} Cloudflare   ${CYAN}${CF_ROOT_DOMAIN}${NC}"
        echo -e "  ${GREEN}[2]${NC} 阿里云 DNS   ${CYAN}${ALI_ROOT_DOMAIN}${NC}"
        local _cnt; _cnt=$(config_count "$caller_mode")
        if [ "$caller_mode" = "proxy" ]; then
            echo -e "  ${GREEN}[3]${NC} 查看/删除配置    ${GREEN}已代理 ${_cnt}${NC}"
        else
            echo -e "  ${GREEN}[3]${NC} 查看/删除配置    ${GREEN}已有证书 ${_cnt}${NC}"
        fi
        echo -e "  ${YELLOW}[0]${NC} 返回上级菜单"
        printf '%b' "${BOLD}请输入选项数字 [0/1/2/3]: ${NC}"
        read -r CHOICE
        case "$CHOICE" in
            1) DNS_MODE="dns_cf"; ROOT_DOMAIN="$CF_ROOT_DOMAIN"; export CF_Token="$CF_TOKEN"; PLATFORM_NAME="Cloudflare"; return 0 ;;
            2) DNS_MODE="dns_ali"; ROOT_DOMAIN="$ALI_ROOT_DOMAIN"; export Ali_Key="$ALI_KEY"; export Ali_Secret="$ALI_SECRET"; PLATFORM_NAME="阿里云 DNS"; return 0 ;;
            3) manage_config "$caller_mode" ;;
            0) return 1 ;;
            *) echo -e "${RED}[-] 输入错误，请重新选择${NC}" ;;
        esac
    done
}

issue_cert() {
    local domain="$1"
    local dns_mode="$2"
    local log="/tmp/acme_issue_${domain}.log"
    rm -f "$log"

    # 国内网络访问 Let's Encrypt 不稳定，失败自动回退 ZeroSSL
    local try_ca rc=0 ca_label="Let's Encrypt"
    for try_ca in letsencrypt zerossl; do
        if [ "$try_ca" = "zerossl" ]; then
            echo -e "${YELLOW}[!] Let's Encrypt 失败，回退到 ZeroSSL 申请...${NC}"
            "$ACME" --register-account -m "admin@${domain}" --server zerossl >/dev/null 2>&1 || true
        fi
        echo -e "${YELLOW}[+] 正在通过 ${dns_mode} 验证并申请证书（CA: ${try_ca}）...${NC}"
        set +e
        if [ "$try_ca" = "zerossl" ]; then
            "$ACME" --issue --dns "$dns_mode" -d "$domain" --server zerossl >"$log" 2>&1
        else
            "$ACME" --issue --dns "$dns_mode" -d "$domain" >"$log" 2>&1
        fi
        rc=$?
        set -e
        if [ "$rc" -eq 0 ] || [ "$rc" -eq 2 ]; then
            ca_label="$try_ca"
            break
        fi
        echo -e "${RED}[-] ${try_ca} 申请失败（退出码: ${rc}）${NC}"
        [ -f "$log" ] && tail -n 5 "$log" | sed 's/^/    /'
    done

    if [ "$rc" -ne 0 ] && [ "$rc" -ne 2 ]; then
        echo -e "${RED}[-] 证书申请失败（Let's Encrypt 与 ZeroSSL 均已尝试）${NC}"
        return 1
    fi

    [ "$rc" -eq 2 ] && echo -e "${GREEN}[✔] 证书仍在有效期内，跳过重新签发（CA: ${ca_label}）${NC}"
    [ "$rc" -eq 0 ] && echo -e "${GREEN}[✔] 证书申请成功（CA: ${ca_label}）${NC}"

    local outdir="${SSL_OUT_DIR}/${domain}"
    local me; me=$(readlink -f "$0")
    mkdir -p "$outdir"
    if [ "$ca_label" = "zerossl" ]; then
        "$ACME" --install-cert -d "$domain" --server zerossl \
            --key-file "${outdir}/privkey.pem" \
            --fullchain-file "${outdir}/fullchain.pem" \
            --reloadcmd "bash ${me} --deploy ${domain}" >/dev/null 2>&1
    else
        "$ACME" --install-cert -d "$domain" \
            --key-file "${outdir}/privkey.pem" \
            --fullchain-file "${outdir}/fullchain.pem" \
            --reloadcmd "bash ${me} --deploy ${domain}" >/dev/null 2>&1
    fi

    if [ ! -f "${outdir}/privkey.pem" ] || [ ! -f "${outdir}/fullchain.pem" ]; then
        echo -e "${RED}[-] 证书导出失败${NC}"
        return 1
    fi

    FULLCHAIN="${outdir}/fullchain.pem"
    PRIVKEY="${outdir}/privkey.pem"
    echo -e "${GREEN}[✔] 证书已导出: ${outdir}/${NC}"

    if ! deploy_certs "$domain"; then
        echo -e "${RED}[-] 证书自动部署失败，可稍后手动部署${NC}"
        return 1
    fi
    return 0
}

configure_nginx() {
    local domain="$1" target_url="$2" fullchain="$3" privkey="$4" use_ssl="$5" tag="${6:-proxy}"
    local target_host
    target_host=$(echo "$target_url" | sed -e 's|^[^/]*//||' -e 's|/.*$||')
    local conf_file="/etc/nginx/conf.d/${domain}.conf"
    local bak=""

    ensure_nginx

    if [ -f "$conf_file" ]; then
        bak="${conf_file}.bak.$(date +%Y%m%d_%H%M%S)"
        cp -a "$conf_file" "$bak"
    fi

    if [ "$use_ssl" -eq 1 ]; then
        cat > "$conf_file" << EOF
# ssltool: ${tag}
server {
    listen 80;
    server_name ${domain};
    return 301 https://\$host\$request_uri;
}

server {
    listen 443 ssl;
    server_name ${domain};

    ssl_certificate     ${fullchain};
    ssl_certificate_key ${privkey};

    location / {
        proxy_pass ${target_url};
        proxy_set_header Host ${target_host};
        proxy_ssl_server_name on;
        proxy_buffering off;
    }
}
EOF
    else
        cat > "$conf_file" << EOF
# ssltool: ${tag}
server {
    listen 80;
    server_name ${domain};

    location / {
        proxy_pass ${target_url};
        proxy_set_header Host ${target_host};
        proxy_ssl_server_name on;
        proxy_buffering off;
    }
}
EOF
    fi

    set +e
    nginx -t >/tmp/nginx_test.log 2>&1
    local rc=$?
    set -e

    if [ "$rc" -eq 0 ]; then
        nginx -s reload >/dev/null 2>&1
        echo -e "\n${GREEN}${BOLD}=========================================================="
        echo "  部署完成！"
        [ "$use_ssl" -eq 1 ] && echo -e "  HTTPS: https://${domain}"
        echo -e "  HTTP:  http://${domain}"
        echo -e "  目标:  ${target_url}"
        echo -e "==========================================================${NC}"
    else
        echo -e "${RED}[-] Nginx 配置测试失败，已回滚${NC}"
        cat /tmp/nginx_test.log | sed 's/^/    /'
        rm -f "$conf_file"
        [ -n "$bak" ] && cp -a "$bak" "$conf_file"
        return 1
    fi
}

# ==========================================
# 自动检测本机已有域名：扫描脚本默认配置位置
# （/root/ssl_out 与 /etc/nginx/ssl），取最近修改的一个
# ==========================================

LAST_DOMAIN=""
LAST_SUB=""
LAST_PROVIDER=""

detect_existing_domain() {
    LAST_DOMAIN=""
    LAST_SUB=""
    LAST_PROVIDER=""
    local newest="" newest_mtime=0 d name m
    for d in "${SSL_OUT_DIR}"/*/ "${SSL_DIR}"/*/; do
        [ -d "$d" ] || continue
        name="$(basename "$d")"
        case "$name" in .*) continue ;; esac
        [ -f "$d/fullchain.pem" ] && [ -f "$d/privkey.pem" ] || continue
        m="$(stat -c %Y "$d" 2>/dev/null || stat -f %m "$d" 2>/dev/null || echo 0)"
        if [ "$m" -gt "$newest_mtime" ]; then
            newest_mtime="$m"
            newest="$name"
        fi
    done
    [ -n "$newest" ] || return 0
    LAST_DOMAIN="$newest"
    case "$LAST_DOMAIN" in
        *.$CF_ROOT_DOMAIN) LAST_SUB="${LAST_DOMAIN%.$CF_ROOT_DOMAIN}"; LAST_PROVIDER=1 ;;
        *.$ALI_ROOT_DOMAIN) LAST_SUB="${LAST_DOMAIN%.$ALI_ROOT_DOMAIN}"; LAST_PROVIDER=2 ;;
    esac
}

# 判断证书是否仍然有效（剩余有效期 > 10 天）
cert_valid() {
    local f="${SSL_OUT_DIR}/${1}/fullchain.pem"
    [ -f "$f" ] || return 1
    if command -v openssl >/dev/null 2>&1; then
        openssl x509 -noout -checkend 864000 -in "$f" >/dev/null 2>&1
    else
        [ -f "${SSL_OUT_DIR}/${1}/privkey.pem" ]
    fi
}

# ==========================================
# 查看 / 删除配置
# ==========================================

# 按模式收集域名到全局数组 DOMAINS（去重）
#   cert  ：模式1 管理的实体 = 拥有证书的域名 + 非代理的站点配置（静态站）
#   proxy ：模式2 管理的实体 = 实际配置了反向代理的域名（conf 含 proxy_pass）
# 以 conf 实际内容为准，兼容本次改版前已存在的旧配置
collect_domains() {
    local mode="${1:-cert}"
    DOMAINS=()
    local d f name
    if [ "$mode" = "proxy" ]; then
        for f in /etc/nginx/conf.d/*.conf; do
            [ -f "$f" ] || continue
            name="$(basename "$f" .conf)"
            case "$name" in .*|default) continue ;; esac
            grep -q 'proxy_pass' "$f" || continue
            if ! printf '%s\n' "${DOMAINS[@]}" | grep -qx "$name"; then
                DOMAINS+=("$name")
            fi
        done
    else
        for d in "${SSL_OUT_DIR}"/*/ "${SSL_DIR}"/*/; do
            [ -d "$d" ] || continue
            name="$(basename "$d")"
            case "$name" in .*) continue ;; esac
            [ -f "$d/fullchain.pem" ] || continue
            if ! printf '%s\n' "${DOMAINS[@]}" | grep -qx "$name"; then
                DOMAINS+=("$name")
            fi
        done
        for f in /etc/nginx/conf.d/*.conf; do
            [ -f "$f" ] || continue
            name="$(basename "$f" .conf)"
            case "$name" in .*|default) continue ;; esac
            grep -q 'proxy_pass' "$f" && continue
            if ! printf '%s\n' "${DOMAINS[@]}" | grep -qx "$name"; then
                DOMAINS+=("$name")
            fi
        done
    fi
}

# 统计当前已有配置数量（按模式区分）
config_count() {
    collect_domains "${1:-cert}"
    echo "${#DOMAINS[@]}"
}

# 打印配置列表（证书目录 + nginx conf.d，去重）
print_config_list() {
    local n=0 name flag_cert flag_conf
    for name in "$@"; do
        n=$((n+1))
        flag_cert="无"; flag_conf="无"
        [ -f "${SSL_OUT_DIR}/${name}/fullchain.pem" ] || [ -f "${SSL_DIR}/${name}/fullchain.pem" ] && flag_cert="有"
        [ -f "/etc/nginx/conf.d/${name}.conf" ] && flag_conf="有"
        echo -e "  ${GREEN}[${n}]${NC} ${name}    证书:${flag_cert}  站点:${flag_conf}"
    done
}

show_domain_config() {
    local name="$1"
    echo -e "\n${BOLD}========== 配置详情: ${name} ==========${NC}"
    if [ -f "/etc/nginx/conf.d/${name}.conf" ]; then
        echo -e "${CYAN}--- Nginx 配置 (${name}.conf) ---${NC}"
        cat "/etc/nginx/conf.d/${name}.conf"
    else
        echo -e "${YELLOW}[-] 无 Nginx 站点配置${NC}"
    fi
    local cert=""
    if [ -f "${SSL_OUT_DIR}/${name}/fullchain.pem" ]; then
        cert="${SSL_OUT_DIR}/${name}/fullchain.pem"
    elif [ -f "${SSL_DIR}/${name}/fullchain.pem" ]; then
        cert="${SSL_DIR}/${name}/fullchain.pem"
    fi
    if [ -n "$cert" ]; then
        echo -e "${CYAN}--- 证书信息 ---${NC}"
        if command -v openssl >/dev/null 2>&1; then
            openssl x509 -in "$cert" -noout -subject -dates -issuer 2>/dev/null | sed 's/^/    /'
        fi
        if cert_valid "$name"; then
            echo -e "    状态: ${GREEN}有效${NC}"
        else
            echo -e "    状态: ${YELLOW}已过期/无效${NC}"
        fi
    else
        echo -e "${YELLOW}[-] 无本地证书文件${NC}"
    fi
    echo -e "${BOLD}==============================${NC}"
}

delete_domain_config() {
    local name="$1" mode="${2:-cert}"
    if [ "$mode" = "proxy" ]; then
        # 模式2删除：仅删除代理站点配置，保留证书（1 的内容不被同步删除）
        if [ -f "/etc/nginx/conf.d/${name}.conf" ]; then
            rm -f "/etc/nginx/conf.d/${name}.conf"
        else
            echo -e "${YELLOW}[!] ${name} 无代理配置可删，证书保持不变${NC}"
        fi
        if command -v nginx >/dev/null 2>&1; then
            if nginx -t >/tmp/nginx_test.log 2>&1; then
                nginx -s reload >/dev/null 2>&1
            fi
        fi
        echo -e "${GREEN}[✔] 已删除 ${name} 的代理站点配置（证书已保留）${NC}"
        return 0
    fi
    # 模式1删除：完整删除（证书 + 站点 + acme.sh 注册），同步清除模式2的依赖
    rm -f "/etc/nginx/conf.d/${name}.conf"
    rm -rf "${SSL_DIR}/${name}" "${SSL_OUT_DIR}/${name}"
    if [ -n "$ACME" ] && [ -x "$ACME" ]; then
        "$ACME" --remove -d "$name" >/dev/null 2>&1 || true
    fi
    if command -v nginx >/dev/null 2>&1; then
        if nginx -t >/tmp/nginx_test.log 2>&1; then
            nginx -s reload >/dev/null 2>&1
        fi
    fi
    echo -e "${GREEN}[✔] 已删除 ${name} 的站点配置与证书${NC}"
}

manage_config() {
    local caller_mode="${1:-cert}"
    local sel IDX
    while true; do
        collect_domains "$caller_mode"

        if [ ${#DOMAINS[@]} -eq 0 ]; then
            echo -e "${YELLOW}[-] 暂无已配置的域名或证书${NC}"
            read -r -p "按回车返回上级菜单..." _
            return 0
        fi

        echo -e "\n${BOLD}当前配置列表：${NC}"
        print_config_list "${DOMAINS[@]}"
        local del_opt=$(( ${#DOMAINS[@]} + 1 ))
        echo -e "  ${GREEN}[${del_opt}]${NC} 删除配置"
        echo -e "  ${YELLOW}[0]${NC} 返回上级菜单"
        printf '%b' "${BOLD}请输入选项数字: ${NC}"
        read -r ACT
        case "$ACT" in
            "${del_opt}")
                echo -e "\n${BOLD}请选择要删除的配置序号：${NC}"
                print_config_list "${DOMAINS[@]}"
                echo -e "  ${YELLOW}[0]${NC} 取消"
                printf '%b' "${BOLD}请输入要删除的序号: ${NC}"
                read -r IDX
                if [ -z "$IDX" ] || ! [[ "$IDX" =~ ^[0-9]+$ ]]; then
                    echo -e "${RED}[-] 输入错误${NC}"; continue
                fi
                if [ "$IDX" -eq 0 ]; then continue; fi
                if [ "$IDX" -gt "${#DOMAINS[@]}" ]; then
                    echo -e "${RED}[-] 序号超出范围${NC}"; continue
                fi
                sel="${DOMAINS[$((IDX-1))]}"
                if [ "$caller_mode" = "proxy" ]; then
                    printf '%b' "${RED}确认删除 ${sel} 的代理配置？（仅删代理，证书保留，不可恢复）(y/n): ${NC}"
                else
                    printf '%b' "${RED}确认删除 ${sel}？（站点 + 证书，不可恢复）(y/n): ${NC}"
                fi
                read -r CONFIRM
                if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
                    delete_domain_config "$sel" "$caller_mode"
                else
                    echo -e "${YELLOW}[-] 已取消删除${NC}"
                fi
                ;;
            0) return 0 ;;
            *) echo -e "${RED}[-] 输入错误${NC}" ;;
        esac
    done
}

# ==========================================
# 模式 1：仅申请证书
# ==========================================

mode_cert_only() {
    detect_existing_domain
    if [ -n "$LAST_DOMAIN" ]; then
        echo -e "${CYAN}[✔] 检测到本机已有证书域名: ${LAST_DOMAIN}${NC}"
    fi

    if ! select_provider "cert"; then
        echo -e "${YELLOW}[-] 已返回上级菜单${NC}"
        return 0
    fi

    printf '%b' "${BOLD}请输入子域名前缀 (如输入 ${GREEN}isz${NC} 自动申请 ${GREEN}isz${NC}.${ROOT_DOMAIN}): ${NC}"
    read -r SUB
    SUB="$(echo "$SUB" | tr -d ' ' | sed 's/^\.//;s/\.$//')"
    if [ -z "$SUB" ]; then
        echo -e "${RED}[-] 前缀不能为空${NC}"
        return 0
    fi
    FULL_DOMAIN="${SUB}.${ROOT_DOMAIN}"
    echo -e "${PURPLE}[+] 目标域名: ${FULL_DOMAIN}${NC}"

    # 若该域名已有有效证书，则跳过申请，直接进入站点创建
    if cert_valid "$FULL_DOMAIN"; then
        echo -e "${GREEN}[✔] 检测到 ${FULL_DOMAIN} 已有有效证书，跳过申请${NC}"
        deploy_certs "$FULL_DOMAIN"
        echo -e "\n${GREEN}${BOLD}=========================================================="
        echo -e "  证书已就绪: ${FULL_DOMAIN}"
        echo -e "  证书目录: ${SSL_OUT_DIR}/${FULL_DOMAIN}/"
        echo -e "  已自动部署: ${SSL_DIR}/${FULL_DOMAIN}/"
        echo -e "==========================================================${NC}"
    else
        ensure_acme
        issue_cert "$FULL_DOMAIN" "$DNS_MODE" || {
            echo -e "${RED}[-] 证书申请失败，中止${NC}"
            read -r -p "按回车返回上级菜单..." _
            return 0
        }
        echo -e "\n${GREEN}${BOLD}=========================================================="
        echo -e "  证书申请完成: ${FULL_DOMAIN}"
        echo -e "  证书目录: ${SSL_OUT_DIR}/${FULL_DOMAIN}/"
        echo -e "  已自动部署: ${SSL_DIR}/${FULL_DOMAIN}/"
        echo -e "==========================================================${NC}"
    fi

    echo -e "\n${BOLD}是否为该域名创建 Nginx 站点？（一台服务器可挂多个域名证书）${NC}"
    echo -e "  ${GREEN}[1]${NC} 静态下载站（root /data，目录列表 + 递归下载）"
    echo -e "  ${GREEN}[2]${NC} 反向代理（需输入目标地址）"
    echo -e "  ${GREEN}[3]${NC} 不创建，仅申请证书"
    echo -e "  ${YELLOW}[0]${NC} 返回主菜单"
    printf '%b' "${BOLD}请输入选项数字 [0/1/2/3，回车默认 1]: ${NC}"
    read -r SITE_OPT
    SITE_OPT="${SITE_OPT:-1}"
    case "$SITE_OPT" in
        0) echo -e "${YELLOW}[-] 已返回主菜单${NC}"; return 0 ;;
        1) create_static_site "$FULL_DOMAIN" ;;
        2)
            printf '%b' "${BOLD}请输入目标域名 (如 https://api.yisu.com): ${NC}"
            read -r TARGET_URL
            [ -z "$TARGET_URL" ] && { echo -e "${RED}[-] 目标域名不能为空${NC}"; return 0; }
            [[ "$TARGET_URL" != http* ]] && TARGET_URL="https://$TARGET_URL"
            configure_nginx "$FULL_DOMAIN" "$TARGET_URL" "${SSL_DIR}/${FULL_DOMAIN}/fullchain.pem" "${SSL_DIR}/${FULL_DOMAIN}/privkey.pem" 1 "static-proxy"
            ;;
        3) echo -e "${YELLOW}[-] 已跳过站点创建，稍后由 HTTPS 同步补齐${NC}" ;;
        *) echo -e "${RED}[-] 输入错误，已跳过站点创建${NC}" ;;
    esac
    # 规则：ssl.sh 管理的域名统一补齐 HTTPS 静态下载站（代理域名已有配置则跳过）
    sync_https_sites
    read -r -p "按回车返回上级菜单..." _
}

# ==========================================
# 模式 2：域名代理
# ==========================================

mode_proxy() {
    if ! select_provider "proxy"; then
        echo -e "${YELLOW}[-] 已返回上级菜单${NC}"
        return 0
    fi

    printf '%b' "${BOLD}请输入子域名前缀 (如输入 ${GREEN}api${NC} 自动代理 ${GREEN}api${NC}.${ROOT_DOMAIN}): ${NC}"
    read -r SUB
    SUB="$(echo "$SUB" | tr -d ' ' | sed 's/^\.//;s/\.$//')"
    if [ -z "$SUB" ]; then
        echo -e "${RED}[-] 前缀不能为空${NC}"
        return 0
    fi
    PROXY_DOMAIN="${SUB}.${ROOT_DOMAIN}"
    echo -e "${PURPLE}[+] 代理域名: ${PROXY_DOMAIN}${NC}"

    printf '%b' "${BOLD}请输入目标域名 (如 https://api.yisu.com): ${NC}"
    read -r TARGET_URL
    [ -z "$TARGET_URL" ] && { echo -e "${RED}[-] 目标域名不能为空${NC}"; return 0; }
    [[ "$TARGET_URL" != http* ]] && TARGET_URL="https://$TARGET_URL"

    # 自动识别平台（域名由所选服务商根域拼出，必定匹配）
    detect_provider "$PROXY_DOMAIN"
    echo -e "${GREEN}[✔] 平台: ${PLATFORM_NAME}${NC}"

    # 检查是否有现有证书
    CERT_DIR="${SSL_OUT_DIR}/${PROXY_DOMAIN}"
    USE_SSL=0
    FULLCHAIN=""
    PRIVKEY=""
    if [ -f "${SSL_DIR}/${PROXY_DOMAIN}/fullchain.pem" ] && [ -f "${SSL_DIR}/${PROXY_DOMAIN}/privkey.pem" ]; then
        echo -e "${GREEN}[✔] 检测到已部署的 SSL 证书${NC}"
        FULLCHAIN="${SSL_DIR}/${PROXY_DOMAIN}/fullchain.pem"
        PRIVKEY="${SSL_DIR}/${PROXY_DOMAIN}/privkey.pem"
        USE_SSL=1
    elif [ -f "${CERT_DIR}/fullchain.pem" ] && [ -f "${CERT_DIR}/privkey.pem" ]; then
        echo -e "${GREEN}[✔] 检测到已有 SSL 证书，正在部署...${NC}"
        deploy_certs "$PROXY_DOMAIN" || { echo -e "${RED}[-] 证书部署失败，中止${NC}"; return 0; }
        FULLCHAIN="${SSL_DIR}/${PROXY_DOMAIN}/fullchain.pem"
        PRIVKEY="${SSL_DIR}/${PROXY_DOMAIN}/privkey.pem"
        USE_SSL=1
    else
        printf '%b' "${BOLD}未检测到 SSL 证书，是否申请并启用 HTTPS？(y/n): ${NC}"
        read -r SSL_YN
        if [ "$SSL_YN" = "y" ] || [ "$SSL_YN" = "Y" ]; then
            ensure_acme
            if issue_cert "$PROXY_DOMAIN" "$DNS_MODE"; then
                USE_SSL=1
            else
                echo -e "${RED}[-] 证书申请失败，中止部署（避免覆盖原有配置）${NC}"
                return 0
            fi
        else
            echo -e "${YELLOW}[-] 使用 HTTP 代理${NC}"
        fi
    fi

    # 配置 Nginx
    ensure_nginx
    configure_nginx "$PROXY_DOMAIN" "$TARGET_URL" "$FULLCHAIN" "$PRIVKEY" "$USE_SSL" "proxy"
    read -r -p "按回车返回上级菜单..." _
}

# ==========================================
# 为所有 ssl.sh 已管理（拥有证书）的域名补齐 HTTPS 静态下载站
# 规则：ssl.sh 包含的域名 → HTTPS 下载；已有站点配置（含代理）不覆盖
# ==========================================

sync_https_sites() {
    local d name conf
    for d in "${SSL_DIR}"/*/; do
        [ -d "$d" ] || continue
        name="$(basename "$d")"
        case "$name" in .*) continue ;; esac
        [ -f "$d/fullchain.pem" ] || continue
        conf="/etc/nginx/conf.d/${name}.conf"
        # 已有该域名的站点配置（静态站或代理）则不重复生成
        [ -f "$conf" ] && continue
        echo -e "${CYAN}[+] 为已管理域名 ${name} 生成 HTTPS 静态下载站${NC}"
        create_static_site "$name" || echo -e "${YELLOW}[!] ${name} 静态站生成失败，可稍后重试${NC}"
    done
}

# ==========================================
# 模式 3：开启默认静态下载站（裸 IP / 任意域名走 80 的 /data 下载通道）
# ==========================================

open_default_site() {
    ensure_nginx
    ensure_data_perms
    local conf="/etc/nginx/conf.d/default.conf"
    local bak=""

    if [ -f "$conf" ]; then
        bak="${conf}.bak.$(date +%Y%m%d_%H%M%S)"
        cp -a "$conf" "$bak"
    fi

    cat > "$conf" << EOF
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /data;

    index index.html index.htm;

    server_name _;

    location / {
        try_files \$uri \$uri/ =404;
        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        charset utf-8;

        if (\$request_filename ~* ^.*?\.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|mp4|mp3|avi|mkv|mov|flv|wmv|wav|flac|aac|iso|img)\$) {
            add_header Content-Disposition attachment;
        }

        index none;
    }
}
EOF

    set +e
    nginx -t >/tmp/nginx_test.log 2>&1
    local rc=$?
    set -e

    if [ "$rc" -eq 0 ]; then
        nginx -s reload >/dev/null 2>&1
        echo -e "${GREEN}[✔] 默认静态下载站已开启：${NC}"
        echo -e "    目录：/data/"
        echo -e "    访问：http://<服务器IP>/  或  http://<任意解析到本机的域名>/"
        echo -e "    支持目录列表与递归下载（wget -r --no-parent http://IP/目录名/）"
        echo -e "    ${YELLOW}注：此为 80 端口 HTTP 通道；ssl.sh 管理的域名自动走 HTTPS 下载${NC}"
        echo -e "${CYAN}[+] 为已管理域名补齐 HTTPS 静态下载站...${NC}"
        sync_https_sites
    else
        echo -e "${RED}[-] Nginx 配置测试失败，已回滚${NC}"
        cat /tmp/nginx_test.log | sed 's/^/    /'
        rm -f "$conf"
        [ -n "$bak" ] && cp -a "$bak" "$conf"
        return 1
    fi
    read -r -p "按回车返回主菜单..." _
}

# ==========================================
# 主菜单循环
# ==========================================

while true; do
    clear
    echo -e "${CYAN}${BOLD}"
    echo "=========================================================="
    echo "    SSL 证书申请 & 域名代理部署工具"
    echo "=========================================================="
    echo -e "${NC}"
    echo -e "${BOLD}请选择模式：${NC}"
    echo -e "  ${GREEN}[1]${NC} 仅申请证书"
    echo -e "  ${GREEN}[2]${NC} 域名代理"
    echo -e "  ${GREEN}[3]${NC} 开启默认静态下载站"
    echo -e "  ${YELLOW}[0]${NC} 退出"
    printf '%b' "${BOLD}请输入选项数字 [0-3]: ${NC}"
    read -r MODE
    case "$MODE" in
        1) mode_cert_only ;;
        2) mode_proxy ;;
        3) open_default_site ;;
        0) echo -e "${GREEN}再见${NC}"; exit 0 ;;
        *) echo -e "${RED}[-] 无效选项，请重新输入${NC}"; sleep 1 ;;
    esac
done