#!/usr/bin/env bash
# LibCyber CLI Installer
# Usage: curl -fsSL https://getcyber.sh | bash
#
# Installs or upgrades cyber CLI + engine.
# - Fresh install: downloads, installs, prompts for setup wizard.
# - Upgrade: stops engine, replaces binaries, restarts engine.

set -euo pipefail

APP_NAME="cyber"
ENGINE_NAME="cyber-engine"
INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/cyber"
BASE_URL="${CYBER_DOWNLOAD_URL:-https://getcyber.sh}"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'

LANG_CODE="en"

# --- i18n ---

declare -A MSG_ZH=(
    [select_lang]="请选择语言 / Please select language"
    [input_prompt]="请输入选项 (1 或 2)"
    [platform]="系统平台"
    [version]="版本"
    [downloading]="正在下载"
    [download_ok]="下载完成"
    [download_fail]="下载失败，请检查网络连接。"
    [extracting]="正在解压..."
    [installing]="正在安装..."
    [bin_not_found]="安装包中未找到程序"
    [stopping_engine]="正在停止引擎..."
    [stopping_service]="正在停止服务..."
    [creating_dirs]="创建配置目录..."
    [install_ok]="安装完成！"
    [upgrade_ok]="升级完成！"
    [restarting_engine]="正在重启引擎..."
    [engine_restarted]="引擎已重启"
    [detected_existing]="检测到已安装版本"
    [upgrading_to]="正在升级到"
    [fresh_install]="全新安装"
    [run_hint]="运行以下命令进入初始化向导："
    [wizard_steps]="向导将引导你完成以下步骤："
    [step_login]="登录 LibCyber 账号"
    [step_nodes]="下载节点配置"
    [step_service]="安装 systemd 开机自启服务"
    [step_start]="启动代理引擎"
    [cli_hint]="也可以使用命令行模式："
    [require_root]="此安装程序需要 root 权限。请使用: sudo bash"
    [require_cmd]="缺少必要命令"
    [unsupported_os]="不支持的操作系统"
    [unsupported_arch]="不支持的系统架构"
    [version_fail]="无法获取最新版本，使用默认版本"
    [already_latest]="已经是最新版本"
    [config_preserved]="配置文件已保留"
    [installing_geodata]="安装引擎数据文件..."
)

declare -A MSG_EN=(
    [select_lang]="Please select language / 请选择语言"
    [input_prompt]="Enter your choice (1 or 2)"
    [platform]="Platform"
    [version]="Version"
    [downloading]="Downloading"
    [download_ok]="Download complete"
    [download_fail]="Download failed. Check your network connection."
    [extracting]="Extracting..."
    [installing]="Installing..."
    [bin_not_found]="Binary not found in package"
    [stopping_engine]="Stopping engine..."
    [stopping_service]="Stopping service..."
    [creating_dirs]="Creating config directories..."
    [install_ok]="Installation complete!"
    [upgrade_ok]="Upgrade complete!"
    [restarting_engine]="Restarting engine..."
    [engine_restarted]="Engine restarted"
    [detected_existing]="Existing installation detected"
    [upgrading_to]="Upgrading to"
    [fresh_install]="Fresh install"
    [run_hint]="Run the following command to start the setup wizard:"
    [wizard_steps]="The wizard will guide you through:"
    [step_login]="Login to your LibCyber account"
    [step_nodes]="Download node configuration"
    [step_service]="Install systemd service for auto-start"
    [step_start]="Start the proxy engine"
    [cli_hint]="Or use CLI mode:"
    [require_root]="This installer requires root. Run with: sudo bash"
    [require_cmd]="Required command not found"
    [unsupported_os]="Unsupported OS"
    [unsupported_arch]="Unsupported architecture"
    [version_fail]="Could not detect latest version, using default"
    [already_latest]="Already on the latest version"
    [config_preserved]="Configuration preserved"
    [installing_geodata]="Installing engine data files..."
)

msg() {
    local key="$1"
    if [ "$LANG_CODE" = "zh" ]; then
        echo "${MSG_ZH[$key]:-$key}"
    else
        echo "${MSG_EN[$key]:-$key}"
    fi
}

info()  { echo -e "${BLUE}[INFO]${NC}  $*"; }
ok()    { echo -e "${GREEN}[OK]${NC}    $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
fail()  { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }

# --- Language selection ---

select_language() {
    echo ""
    echo -e "${BLUE}╭──────────────────────────────────────╮${NC}"
    echo -e "${BLUE}│      LibCyber CLI Installer          │${NC}"
    echo -e "${BLUE}╰──────────────────────────────────────╯${NC}"
    echo ""
    echo -e "  $(msg select_lang)"
    echo ""
    echo -e "  ${BOLD}1)${NC} 中文 (Chinese)"
    echo -e "  ${BOLD}2)${NC} English"
    echo ""

    local choice=""
    while true; do
        echo -ne "  $(msg input_prompt): "
        read -r choice < /dev/tty 2>/dev/null || choice="1"
        case "$choice" in
            1|zh|ZH|中文|"")  LANG_CODE="zh"; break ;;
            2|en|EN|English|english) LANG_CODE="en"; break ;;
            *) echo -e "  ${YELLOW}Invalid. Enter 1 or 2.${NC}" ;;
        esac
    done
    echo ""
}

# --- System detection ---

detect_os() {
    case "$(uname -s)" in
        Linux*)  echo "linux" ;;
        Darwin*) echo "darwin" ;;
        *)       fail "$(msg unsupported_os): $(uname -s)" ;;
    esac
}

detect_arch() {
    case "$(uname -m)" in
        x86_64|amd64)  echo "amd64" ;;
        aarch64|arm64) echo "arm64" ;;
        *)             fail "$(msg unsupported_arch): $(uname -m)" ;;
    esac
}

check_requirements() {
    for cmd in curl tar; do
        command -v "$cmd" &>/dev/null || fail "$(msg require_cmd): $cmd"
    done
}

check_root() {
    [ "$(id -u)" -eq 0 ] || fail "$(msg require_root)"
}

# Detect existing installation and get current version
detect_existing() {
    EXISTING_VERSION=""
    IS_UPGRADE=false

    if [ -x "${INSTALL_DIR}/${APP_NAME}" ]; then
        EXISTING_VERSION=$("${INSTALL_DIR}/${APP_NAME}" version 2>/dev/null \
            | head -1 | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown")
        IS_UPGRADE=true
        info "$(msg detected_existing): ${EXISTING_VERSION}"
    else
        info "$(msg fresh_install)"
    fi
}

# Stop running engine and systemd service
stop_existing() {
    if [ "$IS_UPGRADE" != "true" ]; then
        return
    fi

    # Stop systemd service first
    if command -v systemctl &>/dev/null; then
        if systemctl is-active --quiet cyber 2>/dev/null; then
            info "$(msg stopping_service)"
            systemctl stop cyber 2>/dev/null || true
        fi
    fi

    # Stop engine process directly (in case it runs without systemd)
    if pgrep -f "$ENGINE_NAME" >/dev/null 2>&1; then
        info "$(msg stopping_engine)"
        pkill -f "$ENGINE_NAME" 2>/dev/null || true
        sleep 1
    fi
}

# Restart engine after upgrade
restart_existing() {
    if [ "$IS_UPGRADE" != "true" ]; then
        return
    fi

    # Prefer systemd if the service is installed
    if command -v systemctl &>/dev/null; then
        if systemctl is-enabled --quiet cyber 2>/dev/null; then
            info "$(msg restarting_engine)"
            systemctl start cyber 2>/dev/null || true
            ok "$(msg engine_restarted)"
            return
        fi
    fi

    # Otherwise try starting directly (if engine was running before)
    if [ -x "${INSTALL_DIR}/${ENGINE_NAME}" ] && [ -f "${CONFIG_DIR}/engine/config.yaml" ]; then
        info "$(msg restarting_engine)"
        nohup "${INSTALL_DIR}/${ENGINE_NAME}" -d "${CONFIG_DIR}/engine" -f "${CONFIG_DIR}/engine/config.yaml" \
            > /var/log/cyber/engine.log 2>&1 &
        ok "$(msg engine_restarted) (PID: $!)"
    fi
}

# --- Main ---

main() {
    select_language
    check_requirements
    check_root

    local os arch
    os=$(detect_os)
    arch=$(detect_arch)
    info "$(msg platform): ${os}/${arch}"

    # Detect existing installation
    detect_existing

    # Fetch latest version
    local version
    version=$(curl -fsSL "${BASE_URL}/version" 2>/dev/null || echo "")
    if [ -z "$version" ]; then
        warn "$(msg version_fail) v2.0.0"
        version="2.0.0"
    fi

    if [ "$IS_UPGRADE" = "true" ]; then
        info "$(msg upgrading_to) v${version}  (${EXISTING_VERSION} → v${version})"
    else
        info "$(msg version): v${version}"
    fi

    # Download
    local package_name="${APP_NAME}-${os}-${arch}.tar.gz"
    local download_url="${BASE_URL}/download/${package_name}"

    info "$(msg downloading) ${package_name}..."

    TMP_DIR=$(mktemp -d)
    trap 'rm -rf "$TMP_DIR"' EXIT

    if ! curl -fSL --progress-bar -o "${TMP_DIR}/${package_name}" "$download_url"; then
        fail "$(msg download_fail)"
    fi
    ok "$(msg download_ok)"

    # Extract
    info "$(msg extracting)"
    tar xzf "${TMP_DIR}/${package_name}" -C "$TMP_DIR"

    local cyber_bin="" engine_bin=""
    # Find binaries — use -executable (GNU find) or fall back to name-only match
    cyber_bin=$(find "$TMP_DIR" -name "$APP_NAME" -type f \( -executable -o -perm /111 \) 2>/dev/null | head -1)
    if [ -z "$cyber_bin" ]; then
        cyber_bin=$(find "$TMP_DIR" -name "$APP_NAME" -type f 2>/dev/null | head -1)
    fi
    engine_bin=$(find "$TMP_DIR" -name "$ENGINE_NAME" -type f \( -executable -o -perm /111 \) 2>/dev/null | head -1)
    if [ -z "$engine_bin" ]; then
        engine_bin=$(find "$TMP_DIR" -name "$ENGINE_NAME" -type f 2>/dev/null | head -1)
    fi

    [ -n "$cyber_bin" ] || fail "$(msg bin_not_found): $APP_NAME"
    [ -n "$engine_bin" ] || fail "$(msg bin_not_found): $ENGINE_NAME"

    # Stop existing engine/service before replacing binaries
    stop_existing

    # Install (overwrite existing)
    info "$(msg installing)"
    install -m 755 "$cyber_bin" "${INSTALL_DIR}/${APP_NAME}"
    ok "${INSTALL_DIR}/${APP_NAME}"
    install -m 755 "$engine_bin" "${INSTALL_DIR}/${ENGINE_NAME}"
    ok "${INSTALL_DIR}/${ENGINE_NAME}"

    # Create config dirs (idempotent)
    mkdir -p "${CONFIG_DIR}/engine" 2>/dev/null || true
    mkdir -p "/var/lib/cyber/engine" 2>/dev/null || true
    mkdir -p "/var/log/cyber" 2>/dev/null || true
    chmod 700 "${CONFIG_DIR}" 2>/dev/null || true

    # Install engine data files (geodata + cache)
    local engine_data_installed=false
    for datafile in geoip.metadb geosite.dat cache.db; do
        local src="$TMP_DIR/$datafile"
        if [ -f "$src" ]; then
            # Preserve runtime cache on upgrade
            if [ "$datafile" = "cache.db" ] && [ -f "${CONFIG_DIR}/engine/${datafile}" ]; then
                continue
            fi
            if [ "$engine_data_installed" = "false" ]; then
                info "$(msg installing_geodata)"
                engine_data_installed=true
            fi
            install -m 644 "$src" "${CONFIG_DIR}/engine/${datafile}"
            ok "  ${CONFIG_DIR}/engine/${datafile}"
        fi
    done

    # Save language preference (only on fresh install)
    if [ ! -f "${CONFIG_DIR}/config.json" ]; then
        echo "{\"language\": \"${LANG_CODE}\"}" > "${CONFIG_DIR}/config.json"
        chmod 600 "${CONFIG_DIR}/config.json"
    fi

    # --- Result ---
    echo ""
    if [ "$IS_UPGRADE" = "true" ]; then
        # Upgrade: restart engine, show short message
        restart_existing

        echo -e "${GREEN}╭──────────────────────────────────────╮${NC}"
        echo -e "${GREEN}│    $(msg upgrade_ok)                         │${NC}"
        echo -e "${GREEN}╰──────────────────────────────────────╯${NC}"
        echo ""
        echo -e "  ${EXISTING_VERSION} → ${GREEN}v${version}${NC}"
        echo -e "  $(msg config_preserved)"
        echo ""
    else
        # Fresh install: show wizard instructions
        echo -e "${GREEN}╭──────────────────────────────────────╮${NC}"
        echo -e "${GREEN}│    $(msg install_ok)                         │${NC}"
        echo -e "${GREEN}╰──────────────────────────────────────╯${NC}"
        echo ""
        echo -e "  $(msg run_hint)"
        echo ""
        echo -e "    ${BLUE}cyber${NC}"
        echo ""
        echo -e "  $(msg wizard_steps)"
        echo -e "    1. $(msg step_login)"
        echo -e "    2. $(msg step_nodes)"
        echo -e "    3. $(msg step_service)"
        echo -e "    4. $(msg step_start)"
        echo ""
        echo -e "  $(msg cli_hint)"
        echo -e "    ${BLUE}printf '%s\\n' 'yourpassword' | cyber login -u your@email.com --password-stdin${NC}"
        echo ""
    fi
}

main "$@"
