#!/bin/bash

red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
cyan='\033[0;36m'
bold='\033[1m'
plain='\033[0m'

# --- 预设配置参数 ---
AUTO_INSTALL=true
DEFAULT_ACCOUNT="admin"
DEFAULT_PASSWORD="66668888"
DEFAULT_PORT="6688"
DEFAULT_LANGUAGE="zh-CN"

# 证书绑定状态（签发成功后强制按 https 展示面板地址）
PANEL_SSL=false
PANEL_CERT_FILE=""
PANEL_KEY_FILE=""

# 分流：大陆 → igz；港澳台+海外 → ipan（另一侧作备用）
MIRROR_MAINLAND="igz.mbvpn.cn"
MIRROR_MAINLAND_IP="8.134.160.125"
MIRROR_OVERSEAS="ipan.mbvpn.cn"
PRIMARY_URL=""
BACKUP_URL=""
ACME_MIRROR=""
ACME_MIRROR_BACKUP=""
MIRROR_REGION=""

cur_dir=$(pwd)

[[ $EUID -ne 0 ]] && echo -e "${red}致命错误: ${plain} 请以root权限运行此脚本 \n " && exit 1

if [[ -f /etc/os-release ]]; then
    source /etc/os-release
    release=$ID
elif [[ -f /usr/lib/os-release ]]; then
    source /usr/lib/os-release
    release=$ID
else
    echo "检查系统操作系统失败，请联系作者!" >&2
    exit 1
fi
echo -e "${green}操作系统: ${release}${plain}"

arch() {
    case "$(uname -m)" in
    x86_64 | x64 | amd64) echo 'amd64' ;;
    i*86 | x86) echo '386' ;;
    armv8* | armv8 | arm64 | aarch64) echo 'arm64' ;;
    armv7* | armv7 | arm) echo 'armv7' ;;
    armv6* | armv6) echo 'armv6' ;;
    armv5* | armv5) echo 'armv5' ;;
    s390x) echo 's390x' ;;
    *) echo -e "${red}不支持的 CPU 架构!${plain}" && rm -f install.sh && exit 1 ;;
    esac
}

echo -e "${green}CPU 架构: $(arch)${plain}"

os_version=""
os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1)

if [[ "${release}" == "ubuntu" ]]; then
    if [[ ${os_version} -lt 20 ]]; then
        echo -e "${red} 请使用Ubuntu 20或更高版本!${plain}\n" && exit 1
    fi
elif [[ "${release}" == "debian" ]]; then
    if [[ ${os_version} -lt 11 ]]; then
        echo -e "${red} 请使用Debian 11或更高版本 ${plain}\n" && exit 1
    fi
fi

install_base() {
    echo -e "${yellow}[+] 正在检查基础依赖...${plain}"
    local missing=""
    local cmd=""
    for cmd in curl wget tar python3; do
        if ! command -v "${cmd}" >/dev/null 2>&1; then
            missing="${missing} ${cmd}"
        fi
    done
    if [[ -z "${missing}" ]]; then
        echo -e "${green}[✔] 基础依赖已就绪${plain}"
        return 0
    fi
    echo -e "${yellow}[+] 缺少依赖:${missing}，正在安装...${plain}"
    case "${release}" in
    ubuntu | debian | armbian)
        apt-get update -qq >/dev/null 2>&1
        apt-get install -y -qq wget curl tar tzdata python3 >/dev/null 2>&1
        ;;
    centos | almalinux | rocky | oracle | ctyunos | alinux | anolis | opencloudos | opencloud)
        yum -y -q install wget curl tar tzdata python3 >/dev/null 2>&1
        ;;
    fedora)
        dnf -y -q install wget curl tar tzdata python3 >/dev/null 2>&1
        ;;
    *)
        apt-get update -qq >/dev/null 2>&1
        apt-get install -y -qq wget curl tar tzdata python3 >/dev/null 2>&1
        ;;
    esac
    if ! command -v curl >/dev/null 2>&1 || ! command -v wget >/dev/null 2>&1; then
        echo -e "${red}[-] curl/wget 安装失败，请手动安装后重试${plain}"
        exit 1
    fi
    echo -e "${green}[✔] 基础依赖已就绪${plain}"
}

# 根据公网归属选择镜像：港澳台/海外→ipan，大陆→igz
select_download_mirrors() {
    local geo_text=""
    local country=""
    local primary_host=""
    local backup_host=""

    geo_text=$(curl -s4 --connect-timeout 3 -m 5 https://myip.ipip.net 2>/dev/null || true)
    if [[ -z "${geo_text}" ]]; then
        geo_text=$(curl -s4 --connect-timeout 3 -m 5 https://cip.cc 2>/dev/null || true)
    fi
    country=$(curl -s4 --connect-timeout 3 -m 5 https://ipinfo.io/country 2>/dev/null | tr -d ' \r\n' || true)

    if echo "${geo_text}" | grep -qiE '香港|澳门|台灣|台湾|Hong Kong|Macau|Macao|Taiwan'; then
        MIRROR_REGION="overseas"
    elif [[ "${country}" =~ ^(HK|MO|TW)$ ]]; then
        MIRROR_REGION="overseas"
    elif echo "${geo_text}" | grep -qiE '中国|China' || [[ "${country}" == "CN" ]]; then
        MIRROR_REGION="mainland"
    elif [[ -n "${country}" && "${country}" != "CN" ]]; then
        MIRROR_REGION="overseas"
    else
        # 定位失败时默认大陆源（国内机器更常见）
        MIRROR_REGION="mainland"
        echo -e "${yellow}[-] 地区定位失败，默认使用大陆镜像${plain}"
    fi

    if [[ "${MIRROR_REGION}" == "mainland" ]]; then
        primary_host="${MIRROR_MAINLAND}"
        backup_host="${MIRROR_OVERSEAS}"
        echo -e "${green}[+] 检测到大陆地区，主源: ${primary_host} ，备用: ${backup_host}${plain}"
    else
        primary_host="${MIRROR_OVERSEAS}"
        backup_host="${MIRROR_MAINLAND}"
        echo -e "${green}[+] 检测到港澳台/海外，主源: ${primary_host} ，备用: ${backup_host}${plain}"
    fi

    # 必须用 https：http 在港澳台/海外常被阿里云「未备案」拦成 403 HTML
    PRIMARY_URL="${primary_host}/3xui"
    BACKUP_URL="${backup_host}/3xui"
    ACME_MIRROR="https://${primary_host}/ssl/acme.sh.tar.gz"
    ACME_MIRROR_BACKUP="https://${backup_host}/ssl/acme.sh.tar.gz"

    echo -e "${green}下载主地址: https://${PRIMARY_URL}${plain}"
    echo -e "${green}下载备用地址: https://${BACKUP_URL}${plain}"
}

get_public_ip() {
    local ip=""
    local raw=""
    raw=$(curl -s4 --connect-timeout 3 -m 4 https://myip.ipip.net 2>/dev/null || true)
    ip=$(echo "${raw}" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 || true)
    if [[ -z "${ip}" ]]; then
        ip=$(curl -s4 --connect-timeout 2 -m 3 https://ipv4.icanhazip.com 2>/dev/null | tr -d ' \r\n' || true)
    fi
    if [[ -z "${ip}" ]]; then
        ip=$(curl -s4 --connect-timeout 2 -m 3 https://api.ipify.org 2>/dev/null | tr -d ' \r\n' || true)
    fi
    echo "${ip}"
}

open_port() {
    local port=$1
    echo -e "${yellow}正在放行 TCP 端口: ${port}...${plain}"
    if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "active"; then
        ufw allow ${port}/tcp >/dev/null 2>&1 || true
    fi
    if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
        firewall-cmd --permanent --add-port=${port}/tcp >/dev/null 2>&1 || true
        firewall-cmd --reload >/dev/null 2>&1 || true
    fi
    if command -v iptables >/dev/null 2>&1; then
        iptables -I INPUT -p tcp --dport ${port} -j ACCEPT >/dev/null 2>&1 || true
    fi
}

ssl_cert_issue_for_ip_auto() {
    echo -e "${yellow}[+] 正在初始化官方标准的 IP 证书自动签发流程...${plain}"

    # 每次运行清除历史 IP 证书：删除证书文件并解除面板绑定，从全新状态开始（失败则干净回退 HTTP，不再残留旧证书）
    rm -rf /root/cert/ip
    mkdir -p /root/cert/ip
    /usr/local/x-ui/x-ui setting -webCert "" -webCertKey "" >/dev/null 2>&1 || true

    # 大陆网络直连 LE 常被墙：5 秒预检，不可达立即跳过（避免干等 180s 超时重试）
    if ! curl -fsS -m 5 -o /dev/null "https://acme-v02.api.letsencrypt.org/directory" 2>/dev/null; then
        echo -e "${yellow}[-] Let's Encrypt 不可达（大陆直连常被墙），跳过证书申请，面板使用 HTTP 模式${plain}"
        return 1
    fi

    local acme=""
    if [[ -x "$HOME/.acme.sh/acme.sh" ]]; then
        acme="$HOME/.acme.sh/acme.sh"
    elif [[ -x "/root/.acme.sh/acme.sh" ]]; then
        acme="/root/.acme.sh/acme.sh"
    else
        local plugin_dir="$HOME/.acme.sh"
        mkdir -p "$plugin_dir"
        cd "$plugin_dir" || return 1
        local acme_ok=false
        local acme_url=""
        local acme_urls=()
        if [[ "${MIRROR_REGION}" == "mainland" ]]; then
            acme_urls=("${ACME_MIRROR}" "http://${MIRROR_MAINLAND_IP}/ssl/acme.sh.tar.gz" "${ACME_MIRROR_BACKUP}")
        else
            acme_urls=("${ACME_MIRROR}" "${ACME_MIRROR_BACKUP}")
        fi
        for acme_url in "${acme_urls[@]}"; do
            if curl -fL -k --connect-timeout 8 --max-time 60 "${acme_url}" -o "acme_pkg.tar.gz" >/dev/null 2>&1; then
                acme_ok=true
                break
            fi
        done
        if [[ "${acme_ok}" != "true" ]]; then
            echo -e "${yellow}[-] 镜像源暂时无法连通，已跳过证书申请，使用标准 HTTP 模式${plain}"
            return 1
        fi
        tar -zxvf acme_pkg.tar.gz --strip-components=1 >/dev/null 2>&1 || true
        rm -f acme_pkg.tar.gz
        chmod +x acme.sh
        acme="$HOME/.acme.sh/acme.sh"
    fi

    if [[ ! -x "$acme" ]]; then
        echo -e "${yellow}[-] 未找到 acme.sh，跳过证书申请${plain}"
        return 1
    fi

    "$acme" --set-default-ca --server letsencrypt --insecure >/dev/null 2>&1 || true

    local server_ip=""
    server_ip="$(get_public_ip)"
    if [[ -z "$server_ip" || ! "$server_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        echo -e "${yellow}[-] 无法获取公网 IP，跳过证书申请${plain}"
        return 1
    fi
    echo -e "${green}[+] 证书目标 IP: ${server_ip}${plain}"

    # 清除该 IP 的 acme.sh 历史证书缓存目录，保证全新签发（不删 acme.sh 本体与账户注册）
    rm -rf "$HOME/.acme.sh/${server_ip}_ecc" 2>/dev/null || true

    # --- 智能释放 80 端口（systemd 停不掉时强制杀占用进程）---
    local occupied_service=""
    local freed_by_kill=0
    if systemctl is-active --quiet nginx 2>/dev/null || pgrep -x nginx >/dev/null 2>&1; then
        occupied_service="nginx"
    elif systemctl is-active --quiet apache2 2>/dev/null; then
        occupied_service="apache2"
    elif systemctl is-active --quiet httpd 2>/dev/null; then
        occupied_service="httpd"
    elif systemctl is-active --quiet caddy 2>/dev/null; then
        occupied_service="caddy"
    fi

    if [[ -n "$occupied_service" ]]; then
        echo -e "${yellow}[+] 检测到 ${occupied_service} 占用 80，正在临时停止...${plain}"
        systemctl stop "$occupied_service" >/dev/null 2>&1 || true
    fi

    # 僵尸/非 systemd 进程仍占 80 时强制清理
    if command -v ss >/dev/null 2>&1 && ss -tulpn 2>/dev/null | grep -qE ':80\s'; then
        echo -e "${yellow}[+] 80 端口仍被占用，强制释放...${plain}"
        fuser -k 80/tcp >/dev/null 2>&1 || true
        pkill -9 nginx >/dev/null 2>&1 || true
        pkill -9 apache2 >/dev/null 2>&1 || true
        pkill -9 httpd >/dev/null 2>&1 || true
        freed_by_kill=1
        sleep 1
    fi

    if command -v ss >/dev/null 2>&1 && ss -tulpn 2>/dev/null | grep -qE ':80\s'; then
        echo -e "${yellow}[-] 无法释放 80 端口，证书签发跳过，使用 HTTP 模式${plain}"
        return 1
    fi

    local cert_dir="/root/cert/ip"
    mkdir -p "$cert_dir"
    local log_file="/tmp/acme_ip_issue.log"
    rm -f "$log_file"

    # 续期专用 80 端口控制脚本：acme.sh pre/post-hook 引用，cron 续期时自动停/起占用 80 的服务
    cat > /usr/local/bin/acme-port80-ctl.sh <<'ACME_CTL'
#!/bin/bash
action="$1"
state="/var/run/acme-port80-ctl.state"
candidates="nginx apache2 httpd caddy"
case "$action" in
    stop)
        : > "$state"
        for svc in $candidates; do
            if systemctl is-active --quiet "$svc" 2>/dev/null; then
                echo "$svc" >> "$state"
                systemctl stop "$svc" >/dev/null 2>&1 || true
            fi
        done
        if command -v ss >/dev/null 2>&1 && ss -tulpn 2>/dev/null | grep -qE ':80\s'; then
            fuser -k 80/tcp >/dev/null 2>&1 || true
            sleep 1
        fi
        ;;
    start)
        while read -r svc; do
            [ -n "$svc" ] && systemctl start "$svc" >/dev/null 2>&1 || true
        done < "$state"
        rm -f "$state"
        ;;
esac
exit 0
ACME_CTL
    chmod +x /usr/local/bin/acme-port80-ctl.sh

    local issue_success=false
    # IP 证书需 shortlived；超时放宽，避免 LE 验证被 25s 掐断
    if timeout 180s "$acme" --issue --standalone -d "$server_ip" \
        --cert-profile shortlived --keylength ec-256 --force --insecure \
        --pre-hook "/usr/local/bin/acme-port80-ctl.sh stop" \
        --post-hook "/usr/local/bin/acme-port80-ctl.sh start" >"$log_file" 2>&1; then
        "$acme" --install-cert -d "$server_ip" --ecc \
            --key-file       "$cert_dir/privkey.pem" \
            --fullchain-file "$cert_dir/fullchain.pem" \
            --reloadcmd      "systemctl restart x-ui" >/dev/null 2>&1 || true

        # 显式安装续期 cron（acme.sh 首次未必自动装上；shortlived 每几天就需续一次）
        "$acme" --install-cronjob >/dev/null 2>&1 || true
        if ! crontab -l 2>/dev/null | grep -q 'acme.sh.*--cron'; then
            ( crontab -l 2>/dev/null | grep -vE 'acme.sh.*--cron' ; echo '0 0 * * * "/root/.acme.sh/acme.sh" --cron --home "/root/.acme.sh" > /dev/null' ) | crontab -
        fi

        /usr/local/x-ui/x-ui setting -webCert "$cert_dir/fullchain.pem" -webCertKey "$cert_dir/privkey.pem" >/dev/null 2>&1 || true
        systemctl restart x-ui >/dev/null 2>&1 || true
        sleep 1
        PANEL_SSL=true
        PANEL_CERT_FILE="$cert_dir/fullchain.pem"
        PANEL_KEY_FILE="$cert_dir/privkey.pem"
        echo ""
        echo -e "${cyan}${bold}************************************************${plain}"
        echo -e "${cyan}${bold}[✔] IP 证书签发并绑定成功（已启用 HTTPS）${plain}"
        echo -e "${cyan}    公钥/证书: ${PANEL_CERT_FILE}${plain}"
        echo -e "${cyan}    私钥文件: ${PANEL_KEY_FILE}${plain}"
        if [[ -f "$log_file" ]]; then
            local renew_hint
            renew_hint=$(grep -oE 'Next renewal time[^:]*: [^ ]+' "$log_file" | tail -n 1 | sed 's/.*: //' || true)
            if [[ -n "$renew_hint" ]]; then
                echo -e "${cyan}    下次续期约: ${renew_hint}${plain}"
            fi
        fi
        echo -e "${cyan}${bold}************************************************${plain}"
        echo ""
        issue_success=true
    else
        echo -e "${yellow}[-] 证书签发未完成，安全回退至标准 HTTP 模式${plain}"
        # 清除可能残留的旧证书绑定，确保面板真实回退 HTTP（否则旧绑定仍在，https 打不开、http 也连不上）
        /usr/local/x-ui/x-ui setting -webCert "" -webCertKey "" >/dev/null 2>&1 || true
        if [[ -f "$log_file" ]]; then
            if grep -qiE 'port 80 is already used|Please stop it first' "$log_file"; then
                echo -e "${yellow}    原因: 80 端口仍被占用，无法完成验证${plain}"
            elif grep -qiE 'timeout|timed out' "$log_file"; then
                echo -e "${yellow}    原因: 验证超时，请检查防火墙是否放行 80 端口${plain}"
            elif grep -qiE 'rateLimited|too many' "$log_file"; then
                echo -e "${yellow}    原因: 申请频率受限，请稍后再试${plain}"
            else
                echo -e "${yellow}    详细日志: ${log_file}${plain}"
            fi
        fi
    fi

    # --- 恢复原本占用 80 端口的服务 ---
    if [[ -n "$occupied_service" ]]; then
        echo -e "${yellow}[+] 正在恢复原 ${occupied_service} 服务...${plain}"
        systemctl start "$occupied_service" >/dev/null 2>&1 || true
    fi

    if [[ "$issue_success" == "true" ]]; then
        return 0
    else
        return 1
    fi
}

patch_xui_mirror_urls() {
    local primary="https://${PRIMARY_URL}"
    local backup="https://${BACKUP_URL}"
    local f
    for f in /usr/bin/x-ui /usr/local/x-ui/x-ui.sh; do
        if [[ ! -f "${f}" ]]; then
            continue
        fi
        sed -i "s|https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh|${primary}/x-ui.sh|g" "${f}"
        sed -i "s|https://raw.githubusercontent.com/mhsanaei/3x-ui/main/x-ui.sh|${primary}/x-ui.sh|g" "${f}"
        sed -i "s|https://github.com/MHSanaei/3x-ui/raw/main/x-ui.sh|${primary}/x-ui.sh|g" "${f}"
        sed -i "s|https://github.com/mhsanaei/3x-ui/raw/main/x-ui.sh|${primary}/x-ui.sh|g" "${f}"
        sed -i 's|bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/install.sh)|bash /root/x.sh|g' "${f}"
        sed -i 's|bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/update.sh)|bash /root/x.sh|g' "${f}"
        sed -i "s#http://${PRIMARY_URL}/x-ui.sh#${primary}/x-ui.sh#g" "${f}"
        sed -i "s#https://${PRIMARY_URL}/x-ui.sh#${primary}/x-ui.sh#g" "${f}"
    done
    echo -e "${yellow}[·] 已将面板「更新/快捷命令」下载地址改为加速源（仅加速，不是 Docker）${plain}"
}

# 根据证书文件/绑定状态决定面板协议
resolve_panel_protocol() {
    if [[ "${PANEL_SSL}" == "true" ]]; then
        echo "https"
        return
    fi
    if [[ -f "/root/cert/ip/fullchain.pem" && -f "/root/cert/ip/privkey.pem" ]]; then
        # 文件存在但已过期等同无效，不能据此宣称 https
        if openssl x509 -in "/root/cert/ip/fullchain.pem" -noout -checkend 0 >/dev/null 2>&1; then
            echo "https"
            return
        fi
    fi
    if /usr/local/x-ui/x-ui setting -show true 2>/dev/null | grep -qiE 'Panel is secure with SSL|hasCert|webCert.*/'; then
        echo "https"
        return
    fi
    echo "http"
}

# 安装末尾再次绑定证书，防止后续步骤覆盖
rebind_panel_cert_if_needed() {
    local cert="${PANEL_CERT_FILE:-/root/cert/ip/fullchain.pem}"
    local key="${PANEL_KEY_FILE:-/root/cert/ip/privkey.pem}"
    if [[ -f "$cert" && -f "$key" ]] && openssl x509 -in "$cert" -noout -checkend 0 >/dev/null 2>&1; then
        # 证书仍有效：绑定并维持 https
        /usr/local/x-ui/x-ui setting -webCert "$cert" -webCertKey "$key" >/dev/null 2>&1 || true
        PANEL_SSL=true
        PANEL_CERT_FILE="$cert"
        PANEL_KEY_FILE="$key"
    else
        # 无证书或已过期：清除绑定，保证面板真实 HTTP（否则面板死绑过期证书，http/https 都打不开）
        /usr/local/x-ui/x-ui setting -webCert "" -webCertKey "" >/dev/null 2>&1 || true
        PANEL_SSL=false
        PANEL_CERT_FILE=""
        PANEL_KEY_FILE=""
    fi
}

# 3x-ui 语言存在浏览器 cookie；英文浏览器会落到 en-US。
# 本函数改写前端默认逻辑，使首次打开（登录页/面板）默认简体中文。
force_panel_zh_cn() {
    local bin="/usr/local/x-ui/x-ui"
    if [[ ! -f "${bin}" ]]; then
        return 0
    fi
    if ! command -v python3 >/dev/null 2>&1; then
        echo -e "${yellow}[-] 未找到 python3，跳过面板默认中文补丁${plain}"
        return 0
    fi

    python3 - "${bin}" <<'PY'
import sys
from pathlib import Path

bin_path = Path(sys.argv[1])
data = bin_path.read_bytes()
original = data
bt = bytes([96])  # backtick

# 无 cookie 时忽略浏览器语言，强制 zh-CN（等长替换）
old1 = b"t=n.language||n.userLanguage||" + bt + bt
new1 = b"t=" + bt + b"zh-CN" + bt + b"||n.language||n.xxx||" + bt + bt
# 检测失败回落
old2 = b"F.setCookie(" + bt + b"lang" + bt + b"," + bt + b"en-US" + bt + b",365)"
new2 = b"F.setCookie(" + bt + b"lang" + bt + b"," + bt + b"zh-CN" + bt + b",365)"
# setLanguage 非法语言回落
old3 = b"e.isSupportLanguage(t)||(t=" + bt + b"en-US" + bt + b")"
new3 = b"e.isSupportLanguage(t)||(t=" + bt + b"zh-CN" + bt + b")"

replacements = [(old1, new1), (old2, new2), (old3, new3)]
changed = 0
for old, new in replacements:
    if len(old) != len(new):
        raise SystemExit("length mismatch %d vs %d" % (len(old), len(new)))
    cnt = data.count(old)
    if cnt:
        data = data.replace(old, new)
        changed += cnt
if data == original:
    raise SystemExit(0)
bin_path.write_bytes(data)
raise SystemExit(0)
PY
    local rc=$?
    if [[ $rc -eq 0 ]]; then
        echo -e "${green}[✔] 面板默认语言已设为简体中文（登录页/面板）${plain}"
    else
        echo -e "${yellow}[-] 面板中文补丁未完全成功，可手动在右上角切换简体中文${plain}"
    fi
}

config_after_install() {
    if [[ "${AUTO_INSTALL}" == "true" ]]; then
        local config_account=${DEFAULT_ACCOUNT}
        local config_password=${DEFAULT_PASSWORD}
        local config_port=${DEFAULT_PORT}
        
        if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then
            /usr/local/x-ui/x-ui setting -username "${config_account}" -password "${config_password}" >/dev/null 2>&1
        fi

        /usr/local/x-ui/x-ui setting -port "${config_port}" >/dev/null 2>&1
        /usr/local/x-ui/x-ui setting -listenIP "0.0.0.0" >/dev/null 2>&1 || true
        /usr/local/x-ui/x-ui setting -webBasePath "/" >/dev/null 2>&1

        ssl_cert_issue_for_ip_auto || true

        open_port "${config_port}"
        # 放行 80，便于证书续期验证
        open_port 80

        local protocol
        protocol="$(resolve_panel_protocol)"

        local panel_ip
        panel_ip=$(get_public_ip)
        [[ -z "${panel_ip}" ]] && panel_ip="服务器IP"

        echo ""
        echo -e "${bold}###############################################${plain}"
        echo -e "${bold}x-ui 已自动配置完成！${plain}"
        echo -e "用户名: ${cyan}${config_account}${plain}"
        echo -e "密码:   ${cyan}${config_password}${plain}"
        echo -e "端口:   ${cyan}${config_port}${plain}"
        echo -e "面板语言: 中文 (${DEFAULT_LANGUAGE})"
        if [[ "${protocol}" == "https" ]]; then
            echo -e "${cyan}${bold}面板地址: https://${panel_ip}:${config_port}/${plain}"
            echo -e "${cyan}证书公钥: ${PANEL_CERT_FILE:-/root/cert/ip/fullchain.pem}${plain}"
            echo -e "${cyan}证书私钥: ${PANEL_KEY_FILE:-/root/cert/ip/privkey.pem}${plain}"
        else
            echo -e "${yellow}面板地址: http://${panel_ip}:${config_port}/${plain}"
            echo -e "${yellow}(未绑定证书，当前为 HTTP)${plain}"
        fi
        echo -e "${bold}###############################################${plain}"
        echo ""
    fi
    
    /usr/local/x-ui/x-ui migrate >/dev/null 2>&1
}

# 拦截阿里云未备案 HTML，避免当成安装包
is_valid_download() {
    local filename=$1
    local min_bytes=${2:-1}
    if [[ ! -s "${filename}" ]]; then
        return 1
    fi
    local size
    size=$(wc -c < "${filename}" | tr -d ' ')
    if [[ "${size}" -lt "${min_bytes}" ]]; then
        return 1
    fi
    if head -c 256 "${filename}" | grep -qiE '<html|ICP Filing|beian-block|Non-compliance'; then
        return 1
    fi
    return 0
}

# 主源过慢/失败自动切备用；大文件用最低速率检测，避免 wget -q 假死
download_one() {
    local url=$1
    local filename=$2
    local label=$3
    local max_time=${4:-180}
    # 连续 15 秒低于 100KB/s 则放弃该源（约 80MB 包不会卡十几分钟）
    local speed_limit=${5:-102400}
    local speed_time=${6:-15}
    local min_bytes=${7:-1}

    echo -e "${yellow}[+] 正在从${label}下载: ${url}${plain}"
    rm -f "${filename}"

    if command -v curl >/dev/null 2>&1; then
        if curl -fL -k --connect-timeout 8 --retry 1 \
            --max-time "${max_time}" \
            --speed-limit "${speed_limit}" --speed-time "${speed_time}" \
            --progress-bar -o "${filename}" "${url}"; then
            if is_valid_download "${filename}" "${min_bytes}"; then
                echo -e "${green}[✔] ${label}下载成功 ($(du -h "${filename}" | awk '{print $1}'))${plain}"
                return 0
            fi
            echo -e "${yellow}[-] ${label}返回异常内容（可能是备案拦截页）${plain}"
        fi
    else
        if wget --timeout=15 --tries=2 --no-check-certificate \
            -O "${filename}" "${url}"; then
            if is_valid_download "${filename}" "${min_bytes}"; then
                echo -e "${green}[✔] ${label}下载成功 ($(du -h "${filename}" | awk '{print $1}'))${plain}"
                return 0
            fi
            echo -e "${yellow}[-] ${label}返回异常内容（可能是备案拦截页）${plain}"
        fi
    fi

    echo -e "${yellow}[-] ${label}下载失败或过慢${plain}"
    rm -f "${filename}"
    return 1
}

download_with_backup() {
    local filename=$1
    local primary=$2
    local backup=$3
    local max_time=${4:-180}
    local speed_limit=${5:-102400}
    local speed_time=${6:-15}
    local fallback=${7:-}
    local min_bytes=${8:-1}
    local fallback_label=${9:-官方源}

    if download_one "${primary}" "${filename}" "主源" "${max_time}" "${speed_limit}" "${speed_time}" "${min_bytes}"; then
        return 0
    fi
    echo -e "${yellow}[-] 切换备用源重试...${plain}"
    if download_one "${backup}" "${filename}" "备用源" "${max_time}" "${speed_limit}" "${speed_time}" "${min_bytes}"; then
        return 0
    fi
    if [[ -n "${fallback}" ]]; then
        echo -e "${yellow}[-] 切换${fallback_label}重试...${plain}"
        if download_one "${fallback}" "${filename}" "${fallback_label}" "${max_time}" "${speed_limit}" "${speed_time}" "${min_bytes}"; then
            return 0
        fi
    fi
    return 1
}

install_x-ui() {
    cd /usr/local/

    local arch_type
    arch_type=$(arch)
    # https 避开阿里云 HTTP 未备案 403
    local primary_xui_url="" backup_xui_url="" fallback_xui_url=""
    local primary_script_url="" backup_script_url="" fallback_script_url=""
    local fallback_label=""

    if [[ "${MIRROR_REGION}" == "mainland" ]]; then
        # 大陆版：https:域名 → http:大陆IP → https:ipan
        primary_xui_url="https://${PRIMARY_URL}/x-ui-linux-${arch_type}.tar.gz"
        backup_xui_url="http://${MIRROR_MAINLAND_IP}/3xui/x-ui-linux-${arch_type}.tar.gz"
        fallback_xui_url="https://${BACKUP_URL}/x-ui-linux-${arch_type}.tar.gz"
        primary_script_url="https://${PRIMARY_URL}/x-ui.sh"
        backup_script_url="http://${MIRROR_MAINLAND_IP}/3xui/x-ui.sh"
        fallback_script_url="https://${BACKUP_URL}/x-ui.sh"
        fallback_label="主下载地址"
    else
        # 海外版：https:域名 → https:大陆域名 → http:大陆IP
        primary_xui_url="https://${PRIMARY_URL}/x-ui-linux-${arch_type}.tar.gz"
        backup_xui_url="https://${BACKUP_URL}/x-ui-linux-${arch_type}.tar.gz"
        fallback_xui_url="http://${MIRROR_MAINLAND_IP}/3xui/x-ui-linux-${arch_type}.tar.gz"
        primary_script_url="https://${PRIMARY_URL}/x-ui.sh"
        backup_script_url="https://${BACKUP_URL}/x-ui.sh"
        fallback_script_url="http://${MIRROR_MAINLAND_IP}/3xui/x-ui.sh"
        fallback_label="大陆IP直连"
    fi

    # 大包：主源过慢约 15s 内自动切备用，再切最终源
    if ! download_with_backup "/usr/local/x-ui-linux-${arch_type}.tar.gz" "${primary_xui_url}" "${backup_xui_url}" 300 102400 15 "${fallback_xui_url}" 1048576 "${fallback_label}"; then
        echo -e "${red}下载 x-ui 失败，请检查网络 ${plain}"
        exit 1
    fi

    if [[ -e /usr/local/x-ui/ ]]; then
        systemctl stop x-ui >/dev/null 2>&1
        rm /usr/local/x-ui/ -rf
    fi

    tar zxvf x-ui-linux-${arch_type}.tar.gz >/dev/null 2>&1
    rm x-ui-linux-${arch_type}.tar.gz -f
    cd x-ui
    chmod +x x-ui

    chmod +x x-ui bin/xray-linux-${arch_type}

    local service_installed=false
    if [ -f "x-ui.service" ]; then
        cp -f x-ui.service /etc/systemd/system/x-ui.service
        service_installed=true
    elif [ -f "x-ui.service.debian" ]; then
        cp -f x-ui.service.debian /etc/systemd/system/x-ui.service
        service_installed=true
    fi

    if [ "$service_installed" = false ]; then
        echo -e "${red}未找到 x-ui.service 文件 ${plain}"
        exit 1
    fi
    chmod 644 /etc/systemd/system/x-ui.service
    systemctl daemon-reload
    
    if ! download_with_backup "/usr/local/x-ui/x-ui.sh" "${primary_script_url}" "${backup_script_url}" 60 1024 10 "${fallback_script_url}" 100 "${fallback_label}"; then
        echo -e "${red}下载 x-ui 脚本失败 ${plain}"
        exit 1
    fi
    
    chmod +x /usr/local/x-ui/x-ui.sh
    ln -sf /usr/local/x-ui/x-ui.sh /usr/bin/x-ui

    patch_xui_mirror_urls
    force_panel_zh_cn
    config_after_install

    systemctl daemon-reload
    systemctl enable x-ui >/dev/null 2>&1
    systemctl start x-ui >/dev/null 2>&1
    sleep 1
    
    /usr/local/x-ui/x-ui setting -webBasePath "/" >/dev/null 2>&1 || true
    /usr/local/x-ui/x-ui setting -port "${DEFAULT_PORT}" >/dev/null 2>&1 || true
    # 再补一次中文补丁（防止后续步骤覆盖二进制）
    force_panel_zh_cn
    # 证书可能被后续 setting/restart 冲掉，末尾强制再绑一次
    rebind_panel_cert_if_needed
    systemctl restart x-ui >/dev/null 2>&1
    sleep 1

    local final_ip protocol
    final_ip=$(get_public_ip)
    [[ -z "${final_ip}" ]] && final_ip="服务器IP"
    protocol="$(resolve_panel_protocol)"

    echo ""
    echo -e "${bold}x-ui 安装完成，运行正常！${plain}"
    if [[ "${protocol}" == "https" ]]; then
        echo -e "${cyan}${bold}请打开面板: https://${final_ip}:${DEFAULT_PORT}/${plain}"
        echo -e "${cyan}(已启用 SSL，请用 https 访问；浏览器可能提示自签/短周期证书属正常)${plain}"
    else
        echo -e "${yellow}请打开面板: http://${final_ip}:${DEFAULT_PORT}/${plain}"
        echo -e "${yellow}(当前未启用 SSL)${plain}"
    fi
    echo -e "面板默认语言: 简体中文（若仍是英文，请清除站点 cookie 或用无痕窗口打开）"
}

echo -e ""
echo -e "${green}------------------------------------------------${plain}"
echo -e "${green}漂泊的诗人  3xui${plain}"
echo -e "${green}------------------------------------------------${plain}"
echo -e ""
install_base
select_download_mirrors
install_x-ui