#!/usr/bin/env bash
#
# Copyright (c) 2024 YunoHost Contributors
#
# This file is part of YunoHost (see https://yunohost.org)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

# Exit hook on subcommand error or unset variable
set -e

# Source YNH helpers
# shellcheck source=../../helpers/helpers
source /usr/share/yunohost/helpers

do_base_regen() {

    pending_dir=$1
    nginx_dir="${pending_dir}/etc/nginx"
    nginx_conf_dir="${nginx_dir}/conf.d"
    mkdir -p "$nginx_conf_dir"

    # install plain conf files
    cp acme-challenge.conf.inc "$nginx_conf_dir"
    cp global.conf "$nginx_conf_dir"
    cp ssowat.conf "$nginx_conf_dir"
    cp yunohost_http_errors.conf.inc "$nginx_conf_dir"
    cp yunohost_sso.conf.inc "$nginx_conf_dir"
    cp proxy_params_with_auth "$nginx_dir"
    cp proxy_params_no_auth "$nginx_dir"
    cp fastcgi_params_with_auth "$nginx_dir"
    cp fastcgi_params_no_auth "$nginx_dir"

    ynh_render_template "security.conf.inc" "${nginx_conf_dir}/security.conf.inc"
    ynh_render_template "yunohost_admin.conf" "${nginx_conf_dir}/yunohost_admin.conf"
    ynh_render_template "yunohost_admin.conf.inc" "${nginx_conf_dir}/yunohost_admin.conf.inc"
    ynh_render_template "yunohost_api.conf.inc" "${nginx_conf_dir}/yunohost_api.conf.inc"

    mkdir -p "$nginx_conf_dir/default.d/"
    cp "redirect_to_admin.conf" "$nginx_conf_dir/default.d/"
}

do_init_regen() {

    cd /usr/share/yunohost/conf/nginx

    export compatibility="intermediate"
    do_base_regen ""

    # probably run with init: just disable default site, restart NGINX and exit
    rm -f "${nginx_dir}/sites-enabled/default"

    # Restart nginx if conf looks good, otherwise display error and exit unhappy
    nginx -t 2> /dev/null || {
        nginx -t
        exit 1
    }
    systemctl restart nginx || {
        journalctl --no-pager --lines=10 -u nginx >&2
        exit 1
    }

    exit 0
}

do_pre_regen() {
    pending_dir=$1

    cd /usr/share/yunohost/conf/nginx

    nginx_dir="${pending_dir}/etc/nginx"
    nginx_conf_dir="${nginx_dir}/conf.d"
    mkdir -p "$nginx_conf_dir"

    export webadmin_allowlist_enabled="$(jq -r '.webadmin_allowlist_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
    if [ "$webadmin_allowlist_enabled" == "True" ]; then
        export webadmin_allowlist="$(jq -r '.webadmin_allowlist' <<< "$YNH_SETTINGS" | sed 's/^null$//g')"
    fi

    # Support different strategy for security configurations
    export redirect_to_https="$(jq -r '.nginx_redirect_to_https' <<< "$YNH_SETTINGS" | int_to_bool)"
    export compatibility="$(jq -r '.nginx_compatibility' <<< "$YNH_SETTINGS" | int_to_bool)"
    export experimental="$(jq -r '.security_experimental_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
    export tls_passthrough_enabled="$(jq -r '.tls_passthrough_enabled' <<< "$YNH_SETTINGS" | int_to_bool)"
    export tls_passthrough_list="$(jq -r '.tls_passthrough_list' <<< "$YNH_SETTINGS" | int_to_bool)"

    do_base_regen "${pending_dir}"

    local tls_passthrough_module="${pending_dir}/etc/nginx/modules-enabled/tls_passthrough.conf"
    mkdir -p "${pending_dir}/etc/nginx/modules-enabled/"

    if [[ "$tls_passthrough_enabled" == "True" ]]; then
        ynh_render_template "tls_passthrough.conf" "${tls_passthrough_module}"
        for tls_passthrough_domain_and_ip in ${tls_passthrough_list//,/ }; do
            export tls_passthrough_domain=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $1}')
            export tls_passthrough_ip=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $2}')
            export tls_passthrough_port=$(echo "$tls_passthrough_domain_and_ip" | awk -F';' '{print $3}')
            ynh_render_template "tls_passthrough_server.conf" "${nginx_conf_dir}/${tls_passthrough_domain}.forward80.conf"
        done
    else
        touch "${tls_passthrough_module}"
    fi

    # "Touch" every known .conf file for every domain,
    # meaning it should be removed by the regen conf
    # - For real 'existing' domains, this file will be overwritten with an actual conf right after using ynh_render_template
    # - For old domains, this will tell the regen conf that it is "to be deleted"
    ls -1 /etc/nginx/conf.d \
        | awk '/^[^\.]+\.[^\.]+.*\.conf$/ { print $1 }' \
        | xargs --replace={} touch "${nginx_conf_dir}/{}"

    # add domain conf files
    cert_status=$(yunohost domain cert status --json)
    for domain in $YNH_DOMAINS; do
        domain_conf_dir="${nginx_conf_dir}/${domain}.d"
        mkdir -p "$domain_conf_dir"
        mail_autoconfig_dir="${pending_dir}/var/www/.well-known/${domain}/autoconfig/mail/"
        mkdir -p "$mail_autoconfig_dir"

        # NGINX server configuration
        export domain
        export domain_cert_ca=$(echo "$cert_status" \
            | jq ".certificates.\"$domain\".CA_type" \
            | tr -d '"')
        if tr ' ' '\n' <<< "$YNH_DOMAINS_WITH_MAIL_IN_AND_OUT" | grep -q "^$domain$"; then
            export mail_enabled="True"
        else
            export mail_enabled="False"
        fi

        ynh_render_template "server.tpl.conf" "${nginx_conf_dir}/${domain}.conf"
        if [ $mail_enabled == "True" ]; then
            ynh_render_template "autoconfig.tpl.xml" "${mail_autoconfig_dir}/config-v1.1.xml"
        fi

        touch "${domain_conf_dir}/yunohost_local.conf" # Clean legacy conf files

    done

    # Legacy file to remove, but we can't really remove it because it may be included by app confs...
    echo "# The old yunohost panel/tile/button doesn't exists anymore" > "$nginx_conf_dir"/yunohost_panel.conf.inc

    # remove old mail-autoconfig files
    autoconfig_files=$(ls -1 /var/www/.well-known/*/autoconfig/mail/config-v1.1.xml 2> /dev/null || true)
    for file in $autoconfig_files; do
        domain=$(basename "$(readlink -f "$(dirname "$file")/../..")")
        [[ $YNH_DOMAINS =~ $domain ]] \
            || (mkdir -p "$(dirname "${pending_dir}/${file}")" && touch "${pending_dir}/${file}")
    done

    # disable default site
    mkdir -p "${nginx_dir}/sites-enabled"
    touch "${nginx_dir}/sites-enabled/default"
}

do_post_regen() {
    regen_conf_files=$1

    # Make sure fastcgi / PHP uses the YNH_USER auth header instead of $remote_user from the Authorization header
    # shellcheck disable=SC2016
    sed -i 's/$remote_user;/$http_ynh_user if_not_empty;/g' /etc/nginx/fastcgi_params

    # Hotfix CVE-2026-42945
    # shellcheck disable=SC2016
    if ! grep -qE 'fastcgi_param\s+HTTP_HOST\s+\$host;' /etc/nginx/fastcgi_params 2> /dev/null; then
        # shellcheck disable=SC2016
        echo 'fastcgi_param  HTTP_HOST        $host;' >> /etc/nginx/fastcgi_params
    fi

    if ls -l /etc/nginx/conf.d/*.d/*.conf; then
        chown root:root /etc/nginx/conf.d/*.d/*.conf
        chmod 644 /etc/nginx/conf.d/*.d/*.conf
    fi

    [ -z "$regen_conf_files" ] && exit 0

    # create NGINX conf directories for domains
    for domain in $YNH_DOMAINS; do
        mkdir -p "/etc/nginx/conf.d/${domain}.d"
    done

    if ! nginx -t 2> /dev/null; then
        # Print issues to console and exit
        nginx -t
        exit 1
    fi

    # Only reload nginx if it's already running
    if pgrep nginx; then
        if ! systemctl reload nginx; then
            journalctl --no-pager --lines=10 -u nginx >&2
            exit 1
        fi
    fi
}

"do_$1_regen" "$(echo "${*:2}" | xargs)"
