#!/usr/bin/env bash
set -euo pipefail

SOURCE_DIR="${SOURCE_DIR:-/workspace/install/sources}"
BUILD_DIR="${BUILD_DIR:-/workspace/install/build}"
CPU_COUNT="${CPU_COUNT:-$(nproc)}"

require_source() {
    if [ ! -f "$SOURCE_DIR/$1" ]; then
        echo "Missing source asset: $SOURCE_DIR/$1" >&2
        exit 1
    fi
}

if [ "$(id -u)" -ne 0 ]; then
    echo "Run as root on the Sifangda application server." >&2
    exit 1
fi

for asset in \
    php-7.3.33.github.tar.gz \
    php-7.4.33.github.tar.gz \
    php-7.3-openssl3.0.patch \
    php-7.4-openssl3.0.patch \
    php-7.3-icu70.patch \
    phpredis-5.3.5.tar.gz \
    nginx-1.26.3.tar.gz \
    redis-5.0.14.tar.gz \
    supervisor-4.2.5-py2.py3-none-any.whl
do
    require_source "$asset"
done

mkdir -p "$BUILD_DIR"
if ! getent group www >/dev/null 2>&1; then
    groupadd --system www
fi
if ! id www >/dev/null 2>&1; then
    useradd --system --gid www --home-dir /nonexistent --shell /sbin/nologin www
fi

build_php() {
    local version="$1"
    local prefix="/usr/local/php${version%.*}"
    local archive="$SOURCE_DIR/php-$version.github.tar.gz"
    local source="$BUILD_DIR/php-src-php-$version"
    local build_log="$BUILD_DIR/php-$version-build.log"
    local -a configure_args

    if [ -x "$prefix/bin/php" ] && [ -s "$prefix/bin/php" ] && \
        "$prefix/bin/php" -r "exit(PHP_VERSION === '$version' ? 0 : 1);"; then
        echo "PHP $version already installed at $prefix; skipping build."
        return
    fi
    if [ -e "$prefix/bin/php" ]; then
        echo "Existing PHP CLI is empty, non-executable, or has the wrong version; rebuilding PHP $version." >&2
    fi

    if [ ! -d "$source" ]; then
        tar -xzf "$archive" -C "$BUILD_DIR"
    fi
    cd "$source"

    if [ ! -f .sfd-openssl3-patched ]; then
        patch -p1 < "$SOURCE_DIR/php-${version%.*}-openssl3.0.patch"
        touch .sfd-openssl3-patched
    fi
    if [ "$version" = "7.3.33" ] && [ ! -f .sfd-icu70-patched ]; then
        patch -p1 < "$SOURCE_DIR/php-7.3-icu70.patch"
        touch .sfd-icu70-patched
    fi

    if [ ! -x configure ]; then
        ./buildconf --force
    fi

    configure_args=(
        "--prefix=$prefix"
        "--with-config-file-path=$prefix/etc"
        "--with-config-file-scan-dir=$prefix/etc/php.d"
        "--enable-fpm"
        "--with-fpm-user=www"
        "--with-fpm-group=www"
        "--with-fpm-systemd"
        "--enable-cli"
        "--enable-mysqlnd"
        "--with-mysqli=mysqlnd"
        "--with-pdo-mysql=mysqlnd"
        "--with-openssl"
        "--with-zlib"
        "--with-bz2"
        "--with-curl"
        "--with-gettext"
        "--with-gmp"
        "--with-readline"
        "--with-xsl"
        "--enable-bcmath"
        "--enable-calendar"
        "--enable-exif"
        "--enable-ftp"
        "--enable-intl"
        "--enable-mbstring"
        "--enable-opcache"
        "--enable-pcntl"
        "--enable-shmop"
        "--enable-soap"
        "--enable-sockets"
        "--enable-sysvmsg"
        "--enable-sysvsem"
        "--enable-sysvshm"
        "--without-pear"
    )

    if [ "$version" = "7.3.33" ]; then
        configure_args+=(
            "--enable-zip"
            "--with-gd"
            "--with-jpeg-dir=/usr"
            "--with-png-dir=/usr"
            "--with-freetype-dir=/usr"
            "--with-webp-dir=/usr"
            "--with-xpm-dir=/usr"
        )
    else
        configure_args+=(
            "--with-zip"
            "--enable-gd"
            "--with-jpeg"
            "--with-freetype"
            "--with-webp"
            "--with-xpm"
        )
    fi

    ./configure "${configure_args[@]}" 2>&1 | tee "$build_log"
    make -j"$CPU_COUNT" 2>&1 | tee -a "$build_log"
    make install 2>&1 | tee -a "$build_log"

    mkdir -p "$prefix/etc/php.d" "$prefix/etc/php-fpm.d"
    install -m 0644 php.ini-production "$prefix/etc/php.ini"
    if [ -f "$prefix/etc/php-fpm.conf.default" ]; then
        install -m 0644 "$prefix/etc/php-fpm.conf.default" "$prefix/etc/php-fpm.conf"
    fi
    if [ -f "$prefix/etc/php-fpm.d/www.conf.default" ]; then
        install -m 0644 "$prefix/etc/php-fpm.d/www.conf.default" "$prefix/etc/php-fpm.d/www.conf"
    fi

    sed -i \
        -e 's#^;pid = run/php-fpm.pid#pid = run/php-fpm.pid#' \
        -e 's#^;error_log = log/php-fpm.log#error_log = log/php-fpm.log#' \
        "$prefix/etc/php-fpm.conf"
    sed -i \
        -e 's#^user = nobody#user = www#' \
        -e 's#^group = nobody#group = www#' \
        -e 's#^;\\?listen.owner = .*#listen.owner = www#' \
        -e 's#^;\\?listen.group = .*#listen.group = www#' \
        -e 's#^;listen.mode = 0660#listen.mode = 0660#' \
        "$prefix/etc/php-fpm.d/www.conf"

    if [ "$version" = "7.3.33" ]; then
        sed -i 's#^listen = 127.0.0.1:9000#listen = /tmp/php-cgi.sock#' "$prefix/etc/php-fpm.d/www.conf"
    else
        sed -i 's#^listen = 127.0.0.1:9000#listen = /tmp/php-cgi7.4.sock#' "$prefix/etc/php-fpm.d/www.conf"
    fi

    "$prefix/bin/php" -v
    test -s "$prefix/bin/php"
    "$prefix/bin/php" -r "exit(PHP_VERSION === '$version' ? 0 : 1);"
}

build_phpzip73() {
    local prefix="/usr/local/php7.3"
    local source_tree="$BUILD_DIR/php-src-php-7.3.33/ext/zip"
    local source="$BUILD_DIR/phpzip-php7.3"

    if "$prefix/bin/php" -m | grep -qx zip; then
        echo "PHP 7.3 zip extension already installed."
        return
    fi
    if [ ! -d "$source_tree" ]; then
        echo "PHP 7.3 source tree not found: $source_tree" >&2
        exit 1
    fi

    rm -rf "$source"
    mkdir -p "$source"
    cp -a "$source_tree/." "$source/"
    cd "$source"
    "$prefix/bin/phpize"
    ./configure --with-php-config="$prefix/bin/php-config"
    make -j"$CPU_COUNT"
    make install
    printf '%s\n' 'extension=zip.so' > "$prefix/etc/php.d/20-zip.ini"
    "$prefix/bin/php" -m | grep -x zip
}

build_phpredis() {
    local version="$1"
    local prefix="/usr/local/php${version%.*}"
    local source="$BUILD_DIR/phpredis-5.3.5-php${version%.*}"

    if "$prefix/bin/php" -m | grep -qx redis; then
        echo "PHP ${version%.*} redis extension already installed."
        return
    fi

    if [ ! -d "$source" ]; then
        mkdir -p "$source"
        tar -xzf "$SOURCE_DIR/phpredis-5.3.5.tar.gz" -C "$source" --strip-components=1
    fi
    cd "$source"
    "$prefix/bin/phpize"
    ./configure --with-php-config="$prefix/bin/php-config"
    make -j"$CPU_COUNT"
    make install
    printf '%s\n' 'extension=redis.so' > "$prefix/etc/php.d/20-redis.ini"
    "$prefix/bin/php" -m | grep -x redis
}

build_nginx() {
    local source="$BUILD_DIR/nginx-1.26.3"

    if [ -x /usr/local/nginx/sbin/nginx ]; then
        echo "Nginx already installed; skipping build."
        return
    fi
    if [ ! -d "$source" ]; then
        tar -xzf "$SOURCE_DIR/nginx-1.26.3.tar.gz" -C "$BUILD_DIR"
    fi
    cd "$source"
    ./configure \
        --prefix=/usr/local/nginx \
        --user=www \
        --group=www \
        --with-file-aio \
        --with-threads \
        --with-http_ssl_module \
        --with-http_v2_module \
        --with-http_realip_module \
        --with-http_stub_status_module \
        --with-http_gzip_static_module \
        --with-http_sub_module \
        --with-pcre-jit
    make -j"$CPU_COUNT"
    make install
    /usr/local/nginx/sbin/nginx -v
}

build_redis() {
    local source="$BUILD_DIR/redis-5.0.14"

    if ! getent group redis >/dev/null 2>&1; then
        groupadd --system redis
    fi
    if ! id redis >/dev/null 2>&1; then
        useradd --system --gid redis --home-dir /workspace/redis --shell /sbin/nologin redis
    fi
    if command -v redis-server >/dev/null 2>&1; then
        echo "Redis already installed; skipping build."
        return
    fi
    if [ ! -d "$source" ]; then
        tar -xzf "$SOURCE_DIR/redis-5.0.14.tar.gz" -C "$BUILD_DIR"
    fi
    cd "$source"
    make -j"$CPU_COUNT" MALLOC=libc
    make install
    redis-server --version
}

install_supervisor() {
    if command -v supervisord >/dev/null 2>&1; then
        echo "Supervisor already installed."
        return
    fi
    python3 -m pip install --no-index "$SOURCE_DIR/supervisor-4.2.5-py2.py3-none-any.whl"
    supervisord --version
}

build_php 7.3.33
build_php 7.4.33
build_phpzip73
build_phpredis 7.3.33
build_phpredis 7.4.33
build_nginx
build_redis
install_supervisor

echo "Sifangda application runtime installation completed."
