#!/bin/bash

if [ $# -eq 0 ]; then
    echo "-----> Error, at least one argument is required : 'en' or 'cn'."
    exit 1
fi
if [[ "$1" != "en" && "$1" != "cn" ]]; then
    echo "-----> Error, invalid argument : $1. Only 'en' or 'cn' is allowed."
    exit 1
fi

# If there are any errors in the following script, it will be terminated immediately
set -e

# =================================
# Environment and version detection
# =================================

if ! command -v gcc >/dev/null 2>&1; then
    echo "-----> Gcc is not installed. Please install gcc and related resources first."
    exit 1
fi
if ! command -v g++ >/dev/null 2>&1; then
    echo "-----> G++ is not installed. Please install g++ and related resources first."
    exit 1
fi

CUDA_MIN_VERSION="12.2"
CUDA_VERSION=$(nvcc --version 2>/dev/null | grep "release" | awk '{print $6}' | cut -d',' -f1)
if [ -z "$CUDA_VERSION" ] || [ "$(printf '%s\n' "$CUDA_MIN_VERSION" "$CUDA_VERSION" | sort -V | head -n1)" != "$CUDA_MIN_VERSION" ]; then
    echo "-----> CUDA is not installed or the version is lower than $CUDA_MIN_VERSION"
    exit 1
fi

if ! command -v python >/dev/null 2>&1; then
    if command -v python3 >/dev/null 2>&1; then
        echo "-----> Python3 is available but python is not, please map python to python3 first."
        exit 1
    else
        echo "-----> Python is not installed. Please install python and related resources first."
        exit 1
    fi
fi

PYTHON_VERSION=$(python3 --version 2>/dev/null | awk '{print $2}')
PYTHON_MAJOR_MINOR=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)
case "$PYTHON_MAJOR_MINOR" in
    3.10|3.11|3.12)
        echo ""
        ;;
    *)
        echo "-----> Python3 version should be 3.10-3.12 (Current: $PYTHON_VERSION)"
        exit 1
        ;;
esac

# ============================
# Directory structure creation
# ============================

if [[ $(basename "$PWD") = "TeliChatSecRun" ]]; then
    cd ..
elif [[ ! -e "./TeliChatSecRun" ]]; then
    mkdir TeliChatSecRun
    echo "-----> Created directory : ./TeliChatSecRun"
else
    echo "-----> Directory already exists : ./TeliChatSecRun"
fi

DIRS=(
    "object" "c" "conf" "my_module" "result" 
    "record" "download" "model" "info" 
    "ichatdef" "inspectdef"
    "model/bge-m3" 
    "model/bge-reranker-v2-m3" 
)

for dir in "${DIRS[@]}"; do
    if [[ ! -e "./TeliChatSecRun/$dir" ]]; then
        mkdir -p "./TeliChatSecRun/$dir"
        echo "-----> Created directory : ./TeliChatSecRun/$dir"
    else
        echo "-----> Directory already exists : ./TeliChatSecRun/$dir"
    fi
done

# The following should be installed in the parent directory of TeliChatSecRun unless there is special processing

# ============================================
# System detection and dependency installation
# ============================================

# 1. Dynamically determine whether sudo is required
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ]; then
    if ! command -v sudo >/dev/null 2>&1; then
        echo "-----> Error: This script requires root privileges. Please install 'sudo' or run as root."
        exit 1
    fi
    SUDO_CMD="sudo "
fi

# 2. Detect operating system distribution
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
    # 如果 ID_LIKE 不存在，将 OS 赋给 LIKE 以防万一
    LIKE=${ID_LIKE:-$ID}
elif [ -f /etc/redhat-release ]; then
    # 兼容极其老旧的 CentOS/RHEL 系统
    OS="centos"
    LIKE="rhel"
else
    echo "-----> Cannot detect OS distribution. Assuming Debian-based."
    OS="debian"
    LIKE="debian"
fi

echo "-----> Detected OS: $OS (Like: $LIKE)"

# 3. Define installation command and package name variables
PKG_UNZIP="unzip"
PKG_ZIP="zip"
PKG_GRAPHVIZ="graphviz"
if [[ "$OS" =~ (debian|ubuntu|kali|linuxmint) ]] || [[ "$LIKE" =~ (debian|ubuntu) ]]; then
    # Debian/Ubuntu series
    CMD_UPDATE="${SUDO_CMD}apt-get update"
    CMD_INSTALL="${SUDO_CMD}apt-get install -y"
    PKG_ALSA_DEV="libasound2-dev"
elif [[ "$OS" =~ (centos|rhel|almalinux|rocky|amzn) ]] || [[ "$LIKE" =~ (rhel|fedora|centos) ]]; then
    # CentOS/RHEL/Fedora/Amazon Linux series
    # 优先使用 dnf (较新的 RHEL/CentOS/Fedora)，否则退化使用 yum
    if command -v dnf >/dev/null 2>&1; then
        PM_CMD="dnf"
    else
        PM_CMD="yum"
    fi
    CMD_UPDATE="${SUDO_CMD}${PM_CMD} check-update"
    CMD_INSTALL="${SUDO_CMD}${PM_CMD} install -y"
    PKG_ALSA_DEV="alsa-lib-devel"
    # EPEL 仅在 RHEL/CentOS/Alma/Rocky 上需要，Fedora 或 Amazon Linux 不需要
    if [[ ! "$OS" =~ (fedora|amzn) ]]; then
        echo "-----> Checking/Installing EPEL release for RHEL-based systems..."
        $CMD_INSTALL epel-release || true
    fi
elif [[ "$OS" == "alpine" ]] || [[ "$LIKE" =~ (alpine) ]]; then
    # Alpine Linux series (常用容器)
    CMD_UPDATE="${SUDO_CMD}apk update"
    CMD_INSTALL="${SUDO_CMD}apk add"
    PKG_ALSA_DEV="alsa-lib-dev"
elif [[ "$OS" =~ (arch|manjaro|endeavouros) ]] || [[ "$LIKE" =~ (arch) ]]; then
    # Arch Linux series
    CMD_UPDATE="${SUDO_CMD}pacman -Sy"
    CMD_INSTALL="${SUDO_CMD}pacman -S --noconfirm"
    PKG_ALSA_DEV="alsa-lib"
elif [[ "$OS" =~ (opensuse|sles|suse) ]] || [[ "$LIKE" =~ (suse) ]]; then
    # SUSE Linux series
    CMD_UPDATE="${SUDO_CMD}zypper refresh"
    CMD_INSTALL="${SUDO_CMD}zypper install -y"
    PKG_ALSA_DEV="alsa-devel"
else
    echo "-----> Unsupported OS family: $OS (Like: $LIKE)"
    exit 1
fi

# 4. Perform installation
echo "-----> Updating package lists..."
$CMD_UPDATE || true 
echo "-----> Installing system packages..."
$CMD_INSTALL $PKG_UNZIP $PKG_ZIP $PKG_GRAPHVIZ

# 5. 校验安装结果
for pkg in unzip zip dot; do
    # dot 是 graphviz 的核心命令
    if ! command -v $pkg >/dev/null 2>&1; then
        echo "-----> Warning: Failed to install or locate '$pkg'."
		exit 1
    fi
done

echo "-----> Dependency installation completed."

# ==================
# PJSIP installation
# ==================

if [ ! -f /usr/local/lib/libpj.so ] && [ ! -f /usr/local/lib/libpj.a ]; then
    echo "-----> Installing PJSIP 2.14.1"
    cd ./TeliChatSecRun/c
    PJSIP_URL="https://github.com/pjsip/pjproject/archive/refs/tags/2.14.1.tar.gz"
    URLS=(
        "$PJSIP_URL"
        "https://mirror.ghproxy.com/$PJSIP_URL"
        "https://ghp.ci/$PJSIP_URL"
        "https://ghproxy.net/$PJSIP_URL"
    )
    for url in "${URLS[@]}"; do
        echo "-----> Trying: $url"
        if wget --timeout=15 --tries=2 -O 2.14.1.tar.gz "$url"; then
            if tar -tf 2.14.1.tar.gz >/dev/null 2>&1; then
                echo "-----> Download PJSIP 2.14.1.tar.gz success"
                break
            else
                echo "-----> Invalid 2.14.1.tar.gz"
                rm -f 2.14.1.tar.gz
            fi
        fi
    done
    if [ ! -f 2.14.1.tar.gz ]; then
        echo "-----> Download PJSIP 2.14.1.tar.gz failed"
        exit 1
    fi
    # ----- Install compilation dependencies
    $CMD_INSTALL make $PKG_ALSA_DEV 
    # ----- Compile and install
    rm -rf pjproject-2.14.1
    tar -xvf 2.14.1.tar.gz
    cd pjproject-2.14.1
    chmod +x configure
    chmod +x aconfigure
    ./configure --enable-shared --disable-video --disable-opencore-amr CFLAGS="-O2 -fPIC"
    make dep
    make
    sudo make install
    cd ..
    rm -rf pjproject-2.14.1
    cd ..
    cd ..
    # PWD is parent directory of TeliChatSecRun
    echo "-----> Installed PJSIP 2.14.1"
else
    echo "-----> PJSIP already installed, skipped"
fi

# ============================
# Python packages installation
# ============================

echo "-----> Installing Python packages..."

LOCATION=$(curl -s ipinfo.io/country)
if [ "$LOCATION" = "CN" ]; then
    export PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"
fi
mkdir -p ./pip_tmp
python -m pip uninstall -y torchvision
TMPDIR="$PWD/pip_tmp" python -m pip install --timeout 1000 --no-cache-dir \
    transformers==4.57.1 torch==2.9.0 torchaudio==2.9.0 openai==2.8.1 numpy==1.26.4 cos-python-sdk-v5==1.9.38 FlagEmbedding==1.3.5 \
    websocket-client==1.9.0 zerorpc==0.6.3 tencentcloud-sdk-python==3.1.1 jieba==0.42.1 nvidia-ml-py3==7.352.0 pywebio==1.8.4 \
    "fastapi[all]"==0.121.3 python-multipart==0.0.20 cn2an==0.5.23 sentence-transformers==5.1.2 scikit-learn==1.7.2 numerizer==0.2.4 \
    "volcengine-python-sdk[ark]"==4.0.35 protobuf==6.33.1 faiss-gpu-cu12==1.12.0 "httpx[socks]"==0.28.1 websockets==15.0.1 \
    graphviz==0.21 varname==0.15.1 typeguard==4.4.4 rapidfuzz==3.14.5 typing_extensions==4.15.0 python-docx==1.2.0 
rm -rf ./pip_tmp


# ==================
# Deploy application
# ==================

zip_file="TeliChatSecRun.zip"

if [ -f "$zip_file" ]; then
    echo "-----> Updating applicaton files ..."
    unzip -o "$zip_file"
else
    echo "-----> Error: File $zip_file does not exist"
    exit 1
fi

# =======================
# Handle conf/public.conf
# =======================

# 根据 install.sh 的运行参数是 en 还是 cn，决定下面两个变量的值

if [ "$1" = "cn" ]; then
    LANG="cn"
    LLM_PROVIDER="doubao:doubao-seed-2.0"
elif [ "$1" = "en" ]; then
    LANG="en"
    LLM_PROVIDER="gemini:gemini-3.1"
else
    echo "-----> Error, invalid argument : $1. Only 'en' or 'cn' is allowed."
    exit 1
fi
CONF_FILE="./TeliChatSecRun/conf/public.conf"
if [ ! -f "$CONF_FILE" ]; then
    cat > "$CONF_FILE" << EOL
LANG="$LANG"
LLM_PROVIDER="$LLM_PROVIDER"
USER_LIST=""
USER_LIST='{"user_name":"firstuser", "ichat":"firstapp", "api_inst_seq_set":"0", "pwd_ak_seq":0, "ext_params":""}'
CALLEE_API_INSTANCE_LIST=""
CALLEE_API_INSTANCE_LIST="0|api_instance is running with web_instance|http://127.0.0.1:8000"
EOL
    echo "-----> Created default configuration file : $CONF_FILE"
else
    echo "-----> Configuration file already exists : $CONF_FILE"
fi

# ==========================
# Huggingface model download
# ==========================

MODEL_LIST=(
    "BAAI/bge-m3:./TeliChatSecRun/model/bge-m3"
    "BAAI/bge-reranker-v2-m3:./TeliChatSecRun/model/bge-reranker-v2-m3"
)

python -m pip install huggingface_hub==0.36.2 -i https://pypi.tuna.tsinghua.edu.cn/simple

if command -v curl &> /dev/null; then
    # LOCATION=$(curl -s ipinfo.io/country)
    # if [ "$LOCATION" = "CN" ]; then
    if curl -I --connect-timeout 5 https://huggingface.co >/dev/null 2>&1; then
        export HF_ENDPOINT="https://huggingface.co"
    else
        export HF_ENDPOINT="https://hf-mirror.com"
    fi
else
    export HF_ENDPOINT="https://huggingface.co"
fi

for item in "${MODEL_LIST[@]}"; do
    REPO_ID="${item%%:*}"
    LOCAL_DIR="${item##*:}"
    # # Check whether the target directory exists and is not empty (indicating that it may have been downloaded)
    # if [ -d "$LOCAL_DIR" ] && [ -n "$(ls -A "$LOCAL_DIR" 2>/dev/null)" ]; then
    #     echo "-----> Directory $LOCAL_DIR already exists and is not empty, skip downloading $REPO_ID."
    #     continue
    # fi
    echo "-----> Downloading: $REPO_ID -> $LOCAL_DIR"
    HF_HUB_DISABLE_UPDATE_CHECK=1 hf download "$REPO_ID" --local-dir "$LOCAL_DIR" --exclude "*.DS_Store" --exclude ".gitattributes" --exclude "*.md" --exclude "*.pdf" --exclude "*.png" --exclude "*.jpg"
    echo "-----> Downloaded: $REPO_ID -> $LOCAL_DIR"
done

# =======================================================================
echo "                                        "
echo "-----> 'install.sh' has finished executing."
