#!/bin/bash
# Copyright (C) 2026 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

LOGFILE="/var/log/xivo_configure_mds_$(date +'%Y%m%d_%H%M%S').log"

mkdir -p "$(dirname "$LOGFILE")"
exec > >(tee -a "$LOGFILE") 2>&1

XIVO_CUSTOM_ENV="/etc/docker/xivo/custom.env"
POSTFIX_DEFAULT_TEMPLATE="/usr/share/xivo-config/templates/mail/etc/postfix/main.cf"
POSTFIX_CUSTOM_TEMPLATE="/etc/xivo/custom-templates/mail/etc/postfix/main.cf"
AMI_CONF="/etc/asterisk/manager.d/02-xivocc.conf"
PG_VERSION=17
PG_HBA_FILE="/var/lib/postgresql/${PG_VERSION}/data/pg_hba.conf"

MDS_NAME=""
MDS_DISPLAY_NAME=""
MDS_VOIP_IP=""
MDS_DATA_IP=""
CC_VOIP_IP=""

usage() {
    cat <<-EOF
	Usage: ${0} -n <mds_name> -v <voip_ip> -d <data_ip> [-D <display_name>] [-c <cc_voip_ip>]
	Configures this XiVO main PBX to host a media server.
	Must be run on the XiVO main PBX, before installing the media server itself.
	EOF
}

check_args() {
    if [[ -z "$MDS_NAME" ]] || [[ -z "$MDS_VOIP_IP" ]] || [[ -z "$MDS_DATA_IP" ]]; then
        echo "Missing args."
        usage
        exit 1
    fi
    : "${MDS_DISPLAY_NAME:=$MDS_NAME}"
}

get_play_auth_token() {
    grep -oP -m 1 '^\s*PLAY_AUTH_TOKEN=\K.*' "$XIVO_CUSTOM_ENV"
}

configure_ami() {
    if [ -z "$CC_VOIP_IP" ]; then
        return
    fi
    echo -e "\e[1;32mAuthorizing the UC/CC server ${CC_VOIP_IP} on the XiVO AMI\e[0m"
    if [ ! -f "$AMI_CONF" ]; then
        echo -e "\e[1;31m${AMI_CONF} not found, skipping AMI configuration.\e[0m"
        return
    fi
    if grep -Eq "^permit=${CC_VOIP_IP}/" "$AMI_CONF"; then
        echo -e "\e[1;33mUC/CC server ${CC_VOIP_IP} already permitted on the AMI, skipping.\e[0m"
        return
    fi
    sed -i "/^deny=/a permit=${CC_VOIP_IP}/255.255.255.255" "$AMI_CONF"
    echo -e "\e[1;32mReloading asterisk manager\e[0m"
    asterisk -rx "manager reload"
}

define_media_server() {
    echo -e "\e[1;32mRegistering media server ${MDS_NAME} in config-mgt\e[0m"
    local status
    status=$(curl -sS -k -o /dev/null -w '%{http_code}' -X POST "https://localhost/configmgt/api/1.0/mediaserver/" \
        -H 'Content-Type: application/json' \
        -H 'Accept: application/json' \
        -H "X-Auth-Token: $(get_play_auth_token)" \
        -d "{\"name\":\"${MDS_NAME}\",\"display_name\":\"${MDS_DISPLAY_NAME}\",\"voip_ip\":\"${MDS_VOIP_IP}\",\"read_only\":false}")
    case "$status" in
        200|201) echo "Media server ${MDS_NAME} registered." ;;
        207)
            echo -e "\e[1;31mMedia server ${MDS_NAME} registered, but its provisioning template line was not created.\e[0m"
            echo -e "\e[1;31mCheck that provd is running, then create the template line from the webi.\e[0m"
            return 1
        ;;
        400|409) echo -e "\e[1;33mMedia server ${MDS_NAME} already registered, skipping.\e[0m" ;;
        *)
            echo -e "\e[1;31mFailed to register media server ${MDS_NAME} (HTTP ${status}).\e[0m"
            return 1
        ;;
    esac
}

add_mdsws_user_to_database() {
    echo -e "\e[1;32mSetting mdsws web service user\e[0m"
    local existing
    if ! existing=$(xivo-dcomp exec -T db psql -U asterisk -t -c \
        "select name from accesswebservice where name = 'mdsws'" asterisk)
    then
        echo -e "\e[1;31mMdsws user was not created, connection to database failed.\e[0m"
        return 1
    fi
    if [ -n "${existing// /}" ]; then
        echo -e "\e[1;33mMdsws user was already set.\e[0m"
        return 0
    fi
    local password
    password=$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32)
    if ! xivo-dcomp exec -T db psql -U asterisk -t -c \
        "insert into accesswebservice(name,login,passwd,acl) values('mdsws','mdsws','${password}','{confd.voicemails.*}')" asterisk
    then
        echo -e "\e[1;31mMdsws user was not created, insert into database failed.\e[0m"
        return 1
    fi
}

authorize_database_access() {
    echo -e "\e[1;32mAuthorizing media server ${MDS_NAME} to reach the XiVO database\e[0m"
    if [ ! -f "$PG_HBA_FILE" ]; then
        echo -e "\e[1;31m${PG_HBA_FILE} not found, skipping database authorization.\e[0m"
        return 1
    fi
    if grep -Eq "^host\s+asterisk\s+all\s+${MDS_DATA_IP}/32\s" "$PG_HBA_FILE"; then
        echo -e "\e[1;33mDatabase access for ${MDS_DATA_IP} already authorized, skipping.\e[0m"
        return 0
    fi
    echo "host    asterisk    all    ${MDS_DATA_IP}/32    md5" >> "$PG_HBA_FILE"
    echo -e "\e[1;32mReloading the database configuration\e[0m"
    xivo-dcomp reload db
}

configure_smtp_relay() {
    echo -e "\e[1;32mAllowing media server ${MDS_NAME} on the SMTP relay\e[0m"
    if [ ! -f "$POSTFIX_CUSTOM_TEMPLATE" ]; then
        if [ ! -f "$POSTFIX_DEFAULT_TEMPLATE" ]; then
            echo -e "\e[1;31mPostfix template not found, skipping SMTP relay configuration.\e[0m"
            return 1
        fi
        mkdir -p "$(dirname "$POSTFIX_CUSTOM_TEMPLATE")"
        cp "$POSTFIX_DEFAULT_TEMPLATE" "$POSTFIX_CUSTOM_TEMPLATE"
    fi
    if grep -qF "${MDS_DATA_IP}/32" "$POSTFIX_CUSTOM_TEMPLATE"; then
        echo -e "\e[1;33mSMTP relay already allows ${MDS_DATA_IP}, skipping.\e[0m"
        return 0
    fi
    if ! grep -qF "#XIVO_DOCKER_NET#" "$POSTFIX_CUSTOM_TEMPLATE"; then
        echo -e "\e[1;31mmynetworks marker not found in postfix template, add ${MDS_DATA_IP}/32 manually.\e[0m"
        return 1
    fi
    sed -i "/#XIVO_DOCKER_NET#/a\\                ${MDS_DATA_IP}/32" "$POSTFIX_CUSTOM_TEMPLATE"
    echo -e "\e[1;32mUpdating configuration\e[0m"
    xivo-update-config
}

main() {
    check_args

    local failed_steps=()
    configure_ami || failed_steps+=("AMI")
    define_media_server || failed_steps+=("media server registration")
    add_mdsws_user_to_database || failed_steps+=("mdsws user")
    authorize_database_access || failed_steps+=("database authorization")
    configure_smtp_relay || failed_steps+=("SMTP relay")

    if [ ${#failed_steps[@]} -ne 0 ]; then
        echo -e "\e[1;31mXiVO configuration for media server ${MDS_NAME} incomplete, review: ${failed_steps[*]}\e[0m"
        echo -e "\e[1;31mFix the reported errors before installing the media server.\e[0m"
        exit 1
    fi

    echo -e "\e[1;32mXiVO configuration for media server ${MDS_NAME} completed\e[0m"
    echo "You can now install the media server on ${MDS_NAME} (./mds-install.sh)."
}

while getopts n:v:d:D:c:h opt
do
    case ${opt} in
        n) MDS_NAME=${OPTARG};;
        v) MDS_VOIP_IP=${OPTARG};;
        d) MDS_DATA_IP=${OPTARG};;
        D) MDS_DISPLAY_NAME=${OPTARG};;
        c) CC_VOIP_IP=${OPTARG};;
        h) usage; exit 0;;
        '?')
            echo "${0} : option ${OPTARG} is not valid" >&2
            usage
            exit 1
        ;;
    esac
done

main
