#!/usr/bin/env	bash
# author: Edison Y
# PATH 设置

export PATH=/sbin:/bin:/usr/sbin:/usr/bin

export packagepath=$PWD

export logpath=/tmp

# 定义错误退出码
readonly EXIT_SUCCESS=0
readonly EXIT_FAILURE=1
readonly EXIT_INVALID_PARAM=2
readonly EXIT_NO_ROOT=3
readonly EXIT_DISK_FULL=4
readonly EXIT_PORT_USED=5

# 定义颜色变量
red='\033[0;31m'
yellow='\033[1;33m'
blue='\033[0;34m'
green='\033[0;32m'
pink='\E[1;35m'
NC='\033[0m' # No Color

# 全局变量声明
declare -g DBPATH=""
declare -g DB_USER="postgres"
declare -g DB_GROUP="postgres"
declare -g DB_PASSWORD=""

# 彩色文字输出函数
log_message() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] $*" >> "$logpath/install.log"
}

echoColor()
{
    # 循环读取参数
    for ((i=1; i<=$#; i+=2)); do
        color=${!i}
        content=$(($i + 1))
        echo -e -n "${!color}${!content}${NC} "
    done
    echo;
}

printDHR() 
{
	echoColor pink "Start" blue "deploying" red "DHR"	yellow "services" pink ">>>>>>"
	sleep 1
	echoColor red "   ___   " yellow "  _  _  " green "  ___  "
	echoColor red "  |   \  " yellow " | || | " green " | _ \ "
	echoColor red "  | |) | " yellow " | __ | " green " |   / "
	echoColor red "  |___/  " yellow " |_||_| " green " |_|_\ "
	sleep 1
	echoColor pink "Shell" green "script"  red "disigned" yellow "by" blue "EdisonY"
}

printDHR

# 前置环境检查
prerequisites_check() {
    echoColor blue "开始前置环境检查......"
    
    # 检查 root 权限
    if [ "$(id -u)" -ne 0 ]; then
        echoColor red "错误：需要 root 权限运行"
        exit $EXIT_NO_ROOT
    fi
    echoColor green "✓ root 权限检查通过"
    
    # 检查必要命令是否存在
    for cmd in tar sed chown su; do
        if ! command -v $cmd &> /dev/null; then
            echoColor red "错误：缺少必要命令 $cmd"
            exit $EXIT_FAILURE
        fi
    done
    echoColor green "✓ 必要命令检查通过"
    
    # 如果已设置 DBPATH，检查磁盘空间
    if [ -n "$DBPATH" ] && [ -d "$DBPATH" ]; then
        local available_space=$(df -P "$DBPATH" | awk 'NR==2 {print $4}')
        if [ "$available_space" -lt 104857600 ]; then
            echoColor red "错误：磁盘空间不足 100GB (可用：${available_space}KB)"
            exit $EXIT_DISK_FULL
        fi
        echoColor green "✓ 磁盘空间检查通过 (${available_space}KB 可用)"
    fi
    
    echoColor green "前置环境检查完成"
    sleep 1
}

#三个服务进程状态判断函数
pidCheck() {
	Tomcat="dhr.war"
	PGSQL="postgres"
	MongoDB="mongod"
	#这里判断传入的参数是否不等于1个
	if [ $# -ne 1 ];then
		echo "Usage $0 content {tomcat|postgres|mongod}"
		exit 1
	fi

	case "$1" in
	tomcat|TOMCAT)
			count=`ps -ef | grep $Tomcat | grep -v grep | wc -l`
			if [[ $count == 0 ]];then
				echoColor green "$Tomcat process not exist"
				return 1
			else
				echoColor red "$Tomcat process exist"
			fi
			;;
	postgres|POSTGRES)
			count=`ps -ef | grep $PGSQL | grep -v grep | wc -l`
			if [[ $count == 0 ]];then
				echoColor green "$PGSQL process not exist"
				return 1
			else
				echoColor red "$PGSQL process exist"
			fi
			;;
	mongod|MONGOD)
			count=`ps -ef | grep $MongoDB | grep -v grep | wc -l`
			if [[ $count == 0 ]];then
				echoColor green "$MongoDB process not exist"
				return 1
			else
				echoColor red "$MongoDB process exist"
			fi
			;;
			*)
			echo -e "请输入指定的服务名称：{tomcat|postgres|mongod}"
	esac
}

# 创建postgres 用户和组（改进日志和密码）
create_user_and_group() {
    generate_password
    
    echoColor blue "开始创建postgres 用户和组......"
    log_message "Creating postgres user and group"
    
    # 创建用户组
    if ! getent group "$DB_GROUP" > /dev/null 2>&1; then
        groupadd "$DB_GROUP" >> "$logpath/install.log" 2>&1 && \
        echoColor green "用户组 $DB_GROUP 创建成功"
        log_message "Group $DB_GROUP created successfully"
    else
        echoColor yellow "用户组 $DB_GROUP 已存在"
        log_message "Group $DB_GROUP already exists"
    fi
    
    # 创建用户
    if ! id "$DB_USER" > /dev/null 2>&1; then
        useradd -g "$DB_GROUP" -r -m -s /bin/bash "$DB_USER" >> "$logpath/install.log" 2>&1 && \
        echo "$DB_PASSWORD" | passwd --stdin "$DB_USER" >> "$logpath/install.log" 2>&1 && \
        echoColor green "用户 $DB_USER 创建完成"
        echoColor yellow "默认密码：$DB_PASSWORD"
        log_message "User $DB_USER created successfully"
    else
        echoColor yellow "用户 $DB_USER 已存在"
        log_message "User $DB_USER already exists"
    fi
    
    sleep 2
}


# 生成随机密码
generate_password() {
    if command -v openssl &> /dev/null; then
        DB_PASSWORD=$(openssl rand -base64 12)
    else
        # 备用方案：使用 /dev/urandom
        DB_PASSWORD=$(head -c 12 /dev/urandom | base64 | cut -c1-12)
    fi
    log_message "Generated PostgreSQL password: $DB_PASSWORD"
}

# 输入数据库路径
input_db_path() {
    echo "请输入数据库服务安装目录:"
    read -r DBPATH
    log_message "User input DB path: $DBPATH"
}

# 确认数据库路径（使用循环替代递归）
ensure_db_path() {
    while true; do
        echo "请确认数据库服务安装目录 (y/n)"
        echo "数据库是否安装到：$DBPATH"
        read -r choose
        case "$choose" in
            Y|y)
                echo "数据库服务将被安装到$DBPATH"
                echo "$DBPATH" > /tmp/dbpath.txt
                return 0
                ;;
            N|n)
                echo "请重新输入数据库服务安装路径"
                input_db_path
                ;;
            *)
                echo "请输入正确的选项 (y/n)"
                ;;
        esac
    done
}

# 判断输入的路径是否为绝对路径（使用循环替代递归）
check_absolute_path() {
    while [[ $DBPATH != /* ]]; do
        echo "请输入绝对路径，例如/usr/local"
        input_db_path
        ensure_db_path
    done
}

#修改 postgresql15 预置脚本路径变量（安全替换特殊字符）
sed_pgdb_path() {
    local escaped_dbpath=$(printf '%s\n' "$DBPATH" | sed 's/[&/\\]/\\&/g')
    
    sed -i "s#/usr/local#${escaped_dbpath}#g" "$DBPATH/ehr/postgresql15/startpostgresql.sh"
    sed -i "s#/usr/local#${escaped_dbpath}#g" "$DBPATH/ehr/postgresql15/stoppostgresql.sh"
    sed -i "s#/usr/local#${escaped_dbpath}#g" "$DBPATH/ehr/postgresql15/postgresql_data_bak.sh"
    
    log_message "Updated PostgreSQL scripts with path: $DBPATH"
}

#判断服务器操作系统版本创建 postgresql15 依赖的软链接
detectOSandCreateSoftLink() {
	if [ -f /etc/os-release ]; then
		. /etc/os-release
		OS=$NAME
	else
		OS=$(uname -s)
	fi

	# 检查 PostgreSQL libpq.so.5 库文件是否存在
	if [ ! -f "$DBPATH/ehr/postgresql15/lib/libpq.so.5" ]; then
		echoColor red "错误：找不到 $DBPATH/ehr/postgresql15/lib/libpq.so.5 文件"
		return 1
	fi

	case "$OS" in
		Ubuntu|Debian*|Linux\ Mint)
			echoColor green "检测到 Debian/Ubuntu 系列系统，创建软链接到 /usr/lib 目录"
			ln -sf $DBPATH/ehr/postgresql15/lib/libpq.so.5 /usr/lib/libpq.so.5
			;;
		CentOS\ Linux|Rocky\ Linux|AlmaLinux|Fedora|Kylin|UOS|openEuler|Anolis\ OS|Red\ Hat*)
			echoColor green "检测到 RedHat/CentOS 系列系统，创建软链接到 /usr/lib64 目录"
			ln -sf $dbpDBPATHath/ehr/postgresql15/lib/libpq.so.5 /usr/lib64/libpq.so.5
			;;
		SUSE\ Linux\ Enterprise\ Server*|openSUSE*)
			echoColor green "检测到 SUSE/openSUSE 系列系统，创建软链接到 /usr/lib64 目录"
			ln -sf $DBPATH/ehr/postgresql15/lib/libpq.so.5 /usr/lib64/libpq.so.5
			;;
		*)
			echoColor yellow "未识别的操作系统：$OS，尝试使用默认路径"
			# 尝试根据系统架构判断使用 lib 还是 lib64
			if [ -d /usr/lib64 ]; then
				ln -sf $DBPATH/ehr/postgresql15/lib/libpq.so.5 /usr/lib64/libpq.so.5
				echoColor blue "已创建软链接到 /usr/lib64 目录"
			else
				ln -sf $DBPATH/ehr/postgresql15/lib/libpq.so.5 /usr/lib/libpq.so.5
				echoColor blue "已创建软链接到 /usr/lib 目录"
			fi
			;;
	esac

	# 验证软链接是否创建成功
	if [ $? -eq 0 ]; then
		echoColor green "PostgreSQL libpq.so.5 软链接创建成功"
	else
		echoColor red "PostgreSQL libpq.so.5 软链接创建失败"
		return 1
	fi
}


# 检查服务器 CPU 架构并安装 PostgreSQL（完整流程）
check_cpu_arch_and_install_pg() {
    echoColor green "开始检查 CPU 架构......"
    
    # 获取 CPU 架构
    local cpu_arch=$(uname -m)
    
    echoColor blue "检测到 CPU 架构：$cpu_arch"
    
    case "$cpu_arch" in
        x86_64|i386|i686)
            echoColor blue "开始安装 PostgreSQL (x86 架构)"
            log_message "Installing PostgreSQL for x86_64"
            
            tar xf "$packagepath"/postgresql*.tar.gz -C "$DBPATH/ehr" || {
                echoColor red "错误：PostgreSQL 解压失败"
                log_message "ERROR: Failed to extract PostgreSQL"
                exit $EXIT_FAILURE
            }

			sed_pgdb_path
            
            chown -R postgres:postgres "$DBPATH/ehr/postgresql15" >> "$logpath/install.log"

			ulimit -n 65535 -u 65535
            
			su - postgres -c "/bin/bash $DBPATH/ehr/postgresql15/startpostgresql.sh" >> "$logpath/install.log"

			# 根据操作系统创建软链接
			detectOSandCreateSoftLink
            
            # 检查 PostgreSQL 是否正常启动
            sleep 5
            pg_count=$(ps -ef | grep postgres | grep postgresql15 | grep -v grep | wc -l)
            if [ "$pg_count" -eq 0 ]; then
                echoColor red "错误：PostgreSQL 未能正常启动"
                echoColor yellow "正在查看日志文件：$DBPATH/ehr/postgresql15/logfile"
                echoColor red "========== 日志内容开始 =========="
                if [ -f "$DBPATH/ehr/postgresql15/logfile" ]; then
                    cat "$DBPATH/ehr/postgresql15/logfile"
                else
                    echoColor red "日志文件不存在：$DBPATH/ehr/postgresql15/logfile"
                fi
                echoColor red "========== 日志内容结束 =========="
                log_message "ERROR: PostgreSQL failed to start. Check logfile for details"
                exit $EXIT_FAILURE
            fi
            
            echoColor green "已成功安装并启动 PostgreSQL，安装路径为 $DBPATH/ehr/postgresql15"
            log_message "PostgreSQL installed and started successfully"
            ;;
            
        aarch64|armv7l|armv6l)
            echoColor blue "检测到 ARM 架构 ($cpu_arch)"
            log_message "ARM architecture detected: $cpu_arch"
            
            # 检查安装包是否为 aarch 版本
            if ls "$packagepath"/*postgresql*aarch* 1> /dev/null 2>&1; then
                echoColor green "检测到适用于 ARM 架构的 PostgreSQL 安装包"
                log_message "Found ARM-compatible PostgreSQL package"
                
                tar xf "$packagepath"/*postgresql*aarch*.tar.gz -C "$DBPATH/ehr" || {
                    echoColor red "错误：PostgreSQL 解压失败"
                    log_message "ERROR: Failed to extract PostgreSQL ARM package"
                    exit $EXIT_FAILURE
                }

				sed_pgdb_path
                
                chown -R postgres:postgres "$DBPATH/ehr/postgresql15" >> "$logpath/install.log"

				ulimit -n 65535 -u 65535

                su - postgres -c "/bin/bash $DBPATH/ehr/postgresql15/startpostgresql.sh" >> "$logpath/install.log"

				# 根据操作系统创建软链接
				detectOSandCreateSoftLink
                
                # 检查 PostgreSQL 是否正常启动
                sleep 5
                pg_count=$(ps -ef | grep postgres | grep postgresql15 | grep -v grep | wc -l)
                if [ "$pg_count" -eq 0 ]; then
                    echoColor red "错误：PostgreSQL 未能正常启动"
                    echoColor yellow "正在查看日志文件：$DBPATH/ehr/postgresql15/logfile"
                    echoColor red "========== 日志内容开始 =========="
                    if [ -f "$DBPATH/ehr/postgresql15/logfile" ]; then
                        cat "$DBPATH/ehr/postgresql15/logfile"
                    else
                        echoColor red "日志文件不存在：$DBPATH/ehr/postgresql15/logfile"
                    fi
                    echoColor red "========== 日志内容结束 =========="
                    log_message "ERROR: PostgreSQL failed to start. Check logfile for details"
                    exit $EXIT_FAILURE
                fi
                
                echoColor green "已成功安装并启动 PostgreSQL (ARM 版本)，安装路径为 $DBPATH/ehr/postgresql15"
                log_message "PostgreSQL ARM version installed and started successfully"
            else
                echoColor red "错误：未找到适用于 ARM 架构的 PostgreSQL 安装包"
                echoColor yellow "提示：请确保安装包文件名包含 'postgresql' 和 'aarch' 关键字"
                log_message "ERROR: No ARM-compatible PostgreSQL package found"
                exit $EXIT_FAILURE
            fi
            ;;
            
        *)
            echoColor red "错误：未识别的 CPU 架构：$cpu_arch"
            echoColor yellow "提示：本系统仅支持 x86/x64 和 ARM 架构服务器"
            log_message "ERROR: Unsupported CPU architecture: $cpu_arch"
            exit $EXIT_FAILURE
            ;;
    esac
    
    sleep 1
}

# 服务是否安装判断（统一返回值）
is_installed() {
	local service_name="$1"

	if [ $# -ne 1 ]; then
		echo "Usage $0 content {tomcat|postgres|mongod}"
		return $EXIT_INVALID_PARAM
	fi
	
	case "$service_name" in	
		mongod|MONGOD)
			if [ -f "$DBPATH/ehr/mongodb8/bin/mongod" ] || [ -f "$DBPATH/ehr/mongodb6/bin/mongod" ]; then
				echoColor red "mongodb 已安装"
				return $EXIT_SUCCESS
			else
				echoColor green "mongodb 未安装"
				return $EXIT_FAILURE
			fi
			;;
		postgres|POSTGRES)	
			if [ -f "$DBPATH/ehr/postgresql15/bin/psql" ]; then
				echoColor red "postgresql 已安装"
				return $EXIT_SUCCESS
			else
				echoColor green "postgresql 未安装"
				return $EXIT_FAILURE
			fi
			;;
		tomcat|TOMCAT)
			if [ -f "/usr/local/dhr/dhr.war" ]; then
				echoColor red "tomcat 已安装"
				return $EXIT_SUCCESS
			else
				echoColor green "tomcat 未安装"
				return $EXIT_FAILURE
			fi
			;;
		*)
        		echo "请输入指定的服务名称：{tomcat|postgres|mongod}"
			return $EXIT_INVALID_PARAM
			;;
	esac
}

############################################################################

# 主流程开始
prerequisites_check

if is_installed postgres; then
	echoColor red "PostgreSQL 已存在，跳过安装"
	exit $EXIT_SUCCESS
else
	# 创建postgres 用户和组
	create_user_and_group

	# 创建数据库安装路径并更新依赖脚本
	if [ -f /tmp/dbpath.txt ]; then
		echoColor yellow "存在 path 文件，跳过变量赋值"
		DBPATH=$(cat /tmp/dbpath.txt)
	else
		input_db_path
		ensure_db_path
		check_absolute_path
	fi

	# 判断输入的路径结尾是否以/结束，如果是，向前截取一位
	if [ -f /tmp/dbpath.txt ]; then
		content=$(cat /tmp/dbpath.txt)
		last_char=${content: -1}
		if [ "$last_char" = "/" ]; then
			echo "The content ends with /"
			content=${content%?}
			echo "$content" > /tmp/dbpath.txt
		else
			echo "The content does not end with /"
		fi
	else
		echo "/tmp/dbpath.txt does not exist"
	fi

	# 持久化 DBPATH 变量值
	export DBPATH=$(cat /tmp/dbpath.txt)

	mkdir -p "$DBPATH/ehr"
	#chmod -R 755 "$DBPATH/ehr"
	
	# 修改文件描述符限制，增加到启动脚本执行ulimit -n 65535 -u 65535 需要root权限su - postgres -C 执行启动脚本才会生效，如果是使用postgres用户会使用默认限制，所以需要写入limits.conf中
    if ! grep -q "postgres soft nofile 65535" /etc/security/limits.conf 2>/dev/null; then
	    echo "postgres soft nofile 65535" >> /etc/security/limits.conf
	    echo "postgres hard nofile 65535" >> /etc/security/limits.conf
        echoColor green "已更新文件描述符限制"
    fi

	# 检查 CPU 架构并安装 PostgreSQL
	check_cpu_arch_and_install_pg
	
	echoColor green "PostgreSQL 安装完成！"
	log_message "PostgreSQL installation completed successfully"
fi
