#!/bin/sh

#fonts color
Green="\033[32m"
Yellow="\033[33m"
Red="\033[31m"
GreenBG="\033[42;37m"
YellowBG="\033[43;37m"
RedBG="\033[41;37m"
Font="\033[0m"

#notification information
OK="${Green}[OK]${Font}"
Warn="${Yellow}[警告]${Font}"
Error="${Red}[错误]${Font}"

cd "$(
    cd "$(dirname "$0")" || exit
    pwd
)" || exit

#================================================================
#================================================================

success() {
    echo -e "${OK} ${GreenBG}$1${Font}"
}

warning() {
    echo -e "${Warn} ${YellowBG}$1${Font}"
}

error() {
    echo -e "${Error} ${RedBG}$1${Font}"
}

info() {
    echo -e "$1"
}

env_get() {
    local key=$1
    local value=`cat $(dirname "$PWD")/.env | grep "^$key=" | awk -F '=' '{print $2}'`
    echo "$value"
}

env_set() {
    local key=$1
    local val=$2
    local exist=`cat $(dirname "$PWD")/.env | grep "^$key="`
    if [ -z "$exist" ]; then
        echo "$key=$val" >> $(dirname "$PWD")/.env
    else
        sed -i "/^${key}=/c\\${key}=${val}" $(dirname "$PWD")/.env
    fi
}

#================================================================
#================================================================

check() {
    while [ -z "$domain" ]; do
        read -rp "请输入你的域名: " domain
        # 判断域名是否合法
        if [ -z "$domain" ]; then
            error "域名不能为空"
        elif [ -z "$(echo "$domain" | grep -E '^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$')" ]; then
            error "域名格式不正确"
            domain=""
        fi
    done

    success "正在域名DNS解析IP..."
    local domain_ip=$(ping -c 1 "${domain}" 2>/dev/null | grep PING | cut -d "(" -f2 | cut -d ")" -f1)
    local local_ip=$(curl -sk ip.sb)
    info "域名DNS解析IP: ${domain_ip}"
    info "本机IP: ${local_ip}"

    sleep 2
    if [[ "$(echo "${local_ip}" | tr '.' '+' | bc)" == "$(echo "${domain_ip}" | tr '.' '+' | bc)" ]]; then
        success "域名DNS解析IP 与 本机IP 匹配"
        sleep 2
    else
        warning "域名DNS解析IP 与 本机IP 不匹配，是否继续操作？ [Y/n]"
        read -r continue_next
        [[ -z ${continue_next} ]] && continue_next="Y"
        case $continue_next in
        [yY][eE][sS] | [yY])
            success "继续操作"
            sleep 2
            ;;
        *)
            error "操作终止"
            exit 2
            ;;
        esac
    fi
}

install() {
    local sitePath="$(dirname "$PWD")/docker/nginx/site"
    local sslPath="$sitePath/ssl"
    if [[ -f "$sslPath/$domain.key" && -f "$sslPath/$domain.crt" ]]; then
        warning "$domain 证书文件已存在，是否删除并继续操作？ [Y/n]"
        read -r continue_install
        [[ -z ${continue_install} ]] && continue_install="Y"
        case $continue_install in
        [yY][eE][sS] | [yY])
            rm -f "$sslPath/$domain.key"
            rm -f "$sslPath/$domain.crt"
            success "继续操作"
            sleep 2
            ;;
        *)
            error "操作终止"
            exit 2
            ;;
        esac
    fi

    apk add --no-cache openssl socat
    curl https://get.acme.sh | sh
    if [[ 0 -ne $? ]]; then
        error "安装证书生成脚本失败"
        exit 1
    fi

    if /root/.acme.sh/acme.sh --issue -d "${domain}" -w "$(dirname "$PWD")/public" --standalone -k ec-256 --force --test; then
        success "SSL 证书测试签发成功，开始正式签发"
        rm -rf "/root/.acme.sh/${domain}_ecc"
        sleep 2
    else
        error "SSL 证书测试签发失败"
        rm -rf "root/.acme.sh/${domain}_ecc"
        exit 1
    fi

    if /root/.acme.sh/acme.sh --issue -d "${domain}" -w "$(dirname "$PWD")/public" --server letsencrypt --standalone -k ec-256 --force; then
        success "SSL 证书生成成功"
        sleep 2
        mkdir -p $sslPath
        if /root/.acme.sh/acme.sh --installcert -d "${domain}" --fullchainpath "${sslPath}/${domain}.crt" --keypath "${sslPath}/${domain}.key" --ecc --force; then
            success "SSL 证书配置成功"
            sleep 2
            cp -r /root/.acme.sh/${domain}_ecc/*.conf ${sslPath}/
        fi
    else
        error "SSL 证书生成失败"
        rm -rf "/root/.acme.sh/${domain}_ecc"
        exit 1
    fi

    env_set "APP_URL" "https://${domain}"

    cat >${sitePath}/ssl.conf <<EOF
server_name ${domain};
listen 443 ssl;
ssl_certificate /var/www/docker/nginx/site/ssl/${domain}.crt;
ssl_certificate_key /var/www/docker/nginx/site/ssl/${domain}.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
error_page 497  https://\$host\$request_uri;
EOF
}

UPDATE_LOG="$(dirname "$PWD")/docker/nginx/site/ssl/update.log"
SSL_PATH="$(dirname "$PWD")/docker/nginx/site/ssl"
upgrade_cert(){
    curl https://get.acme.sh | sh
    if [[ 0 -ne $? ]]; then
        echo "安装证书更新脚本失败"
        echo $(date)":   安装证书更新脚本失败" >> ${UPDATE_LOG}
        exit 1
    fi
    file=$1
    domain=$(basename "$file" .key)
    old_crt_md5=$(md5sum ${SSL_PATH}/${domain}.crt| awk '{print $1}')
    /root/.acme.sh/acme.sh --renew --standalone -d ${domain} --fullchainpath "${SSL_PATH}/${domain}.crt" --keypath "${SSL_PATH}/${domain}.key" --ecc --force
    new_crt_md5=$(md5sum ${SSL_PATH}/${domain}.crt| awk '{print $1}')
    if [ "${old_key_md5}" == "${new_key_md5}" ]; then
        echo "${domain} 证书更新脚本失败"
        echo $(date)":   ${domain} 证书更新失败" >> ${UPDATE_LOG}
        echo $(date)":   ${old_crt_md5} == ${new_crt_md5}" >> ${UPDATE_LOG}
    else
        echo "${domain} 证书更新脚本成功"
        echo $(date)":   ${domain} 证书更新成功" >> ${UPDATE_LOG}
    fi
}

check_expire(){
    apk add --no-cache openssl socat
    find ${SSL_PATH} -type f -name "*.key" | while read -r file; do
        CERT_PATH=$file
        expiry_date=$(openssl x509 -enddate -noout -in "$CERT_PATH" | cut -d= -f2)
        expiry_timestamp=$(date -d "$expiry_date" +%s)
        current_timestamp=$(date +%s)
        days_remaining=$(( (expiry_timestamp - current_timestamp) / 86400 ))
        echo "剩余时间${days_remaining}天" >> ${UPDATE_LOG}
        if [ "$days_remaining" -lt 30 ]; then
            upgrade_cert $file
        fi
    done
}
case "${1}" in
"install")
    check
    install
    ;;
"renew")
    check_expire
    ;;
*)
    echo "test"
    ;;
esac

