
# ffsync service setup
PYTHON_DIR="/var/packages/python314/target/bin"
PATH="${SYNOPKG_PKGDEST}/env/bin:${SYNOPKG_PKGDEST}/bin:${PYTHON_DIR}:${PATH}"

MYSQL="/usr/local/mariadb10/bin/mysql"
MYSQLDUMP="/usr/local/mariadb10/bin/mysqldump"
PYTHON="${SYNOPKG_PKGDEST}/env/bin/python3"
SYNCSERVER="${SYNOPKG_PKGDEST}/bin/syncserver"
DIESEL="${SYNOPKG_PKGDEST}/bin/diesel"
CFG_FILE="${SYNOPKG_PKGVAR}/local.toml"

# enhance logging
ENV="RUST_LOG=debug RUST_BACKTRACE=full"

SERVICE_COMMAND="env ${ENV} ${SYNCSERVER} --config=${CFG_FILE}"
SVC_BACKGROUND=y
SVC_WRITE_PID=y

DBUSER=ffsync
DBSERVER="localhost"
DBSOCKET="/run/mysqld/mysqld10.sock"

percent_encode ()
{
    string="$1"
    result=""
    len=$(echo "$string" | awk '{print length}')
    i=1
    while [ "$i" -le "$len" ]; do
        char=$(echo "$string" | cut -c "$i")
        if echo "$char" | grep -qE '[0-9a-zA-Z]'; then
            result="$result$char"
        else
            result="$result$(printf '%%%02X' "'$char")"
        fi
        i=$((i + 1))
    done
    echo "$result"
}

validate_preinst ()
{
    # Check database
    if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then
        if [ -n "${wizard_mysql_password_root}" ]; then
            if ! ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e quit > /dev/null 2>&1; then
                echo "Incorrect MariaDB root password"
                exit 1
            fi
            if ${MYSQL} -u root -p"${wizard_mysql_password_root}" mysql -e "SELECT User FROM user" | grep ^${DBUSER}$ > /dev/null 2>&1; then
                echo "MariaDB user ${DBUSER} already exists"
                exit 1
            fi
            if ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "SHOW DATABASES" | grep -E '^(syncstorage_rs|tokenserver_rs)$' > /dev/null 2>&1; then
                echo "MariaDB database(s) for ${DBUSER} already exist(s)"
                exit 1
            fi
        fi
    fi
}

service_postinst ()
{
    separator="===================================================="

    echo "Install Python virtual environment"
    install_python_virtualenv

    echo ${separator}
    echo "Install packages from wheelhouse"
    pip install --disable-pip-version-check --no-deps --no-input --no-index "${SYNOPKG_PKGDEST}/share/wheelhouse"/*.whl

    echo ${separator}
    echo "Install pure python packages from index"
    pip install --disable-pip-version-check --no-deps --no-input --requirement "${SYNOPKG_PKGDEST}/share/wheelhouse/requirements-pure.txt"


    if [ "${SYNOPKG_PKG_STATUS}" = "INSTALL" ]; then
        # Generate database password for database user
        DBPASS_RAW=$(tr -dc 'a-zA-Z0-9!@#$%^&*()_+{}<>?=' </dev/urandom | fold -w 10 | grep -E '[a-z]' | grep -E '[A-Z]' | grep -E '[0-9]' | grep -E '[!@#$%^&*()_+{}<>?=]' | head -n 1)
        DBPASS_ENC=$(percent_encode "$DBPASS_RAW")
    
        echo ${separator}
        echo "Set up the databases"
        # login as root sql user using whatever creds you set up for that
        # this sets up a user for sync storage and sets up the databases
        ${MYSQL} -u root -p"${wizard_mysql_password_root}" <<EOF
CREATE USER "${DBUSER}"@"localhost" IDENTIFIED BY "${DBPASS_RAW}";
CREATE DATABASE syncstorage_rs;
CREATE DATABASE tokenserver_rs;
GRANT ALL PRIVILEGES on syncstorage_rs.* to ${DBUSER}@localhost;
GRANT ALL PRIVILEGES on tokenserver_rs.* to ${DBUSER}@localhost;
EOF

        echo ${separator}
        echo "Run database migrations"

        echo "Run migrations for syncstorage_rs"
        ${DIESEL} --database-url "mysql://${DBUSER}:${DBPASS_ENC}@${DBSERVER}/syncstorage_rs" \
            migration --migration-dir "${SYNOPKG_PKGDEST}/syncstorage-mysql/migrations" run

        echo "Run migrations for tokenserver_rs"
        ${DIESEL} --database-url "mysql://${DBUSER}:${DBPASS_ENC}@${DBSERVER}/tokenserver_rs" \
            migration --migration-dir "${SYNOPKG_PKGDEST}/tokenserver-mysql/migrations" run

        echo ${separator}
        echo "Add sync endpoint to database"
        # Check if service already exists
        SYNC_SERVICE_ID=$(${MYSQL} -u ${DBUSER} -p"${DBPASS_RAW}" -N -B -r -e "SELECT id FROM tokenserver_rs.services WHERE service = 'sync-1.5'" 2>/dev/null || true)
        if [ -z "${SYNC_SERVICE_ID}" ]; then
            ${MYSQL} -u ${DBUSER} -p"${DBPASS_RAW}" <<EOF
USE tokenserver_rs
INSERT INTO services (service, pattern) VALUES
    ("sync-1.5", "{node}/1.5/{uid}");
EOF
            SYNC_SERVICE_ID=$(${MYSQL} -u ${DBUSER} -p"${DBPASS_RAW}" -N -B -r -e "SELECT id FROM tokenserver_rs.services WHERE service = 'sync-1.5'" 2>/dev/null)
        fi
        echo "Using service ID: ${SYNC_SERVICE_ID}"

        echo "Add syncserver node"
        ${MYSQL} -u ${DBUSER} -p"${DBPASS_RAW}" <<EOF
USE tokenserver_rs
INSERT INTO nodes (service, node, available, current_load, capacity, downed, backoff) VALUES
    (${SYNC_SERVICE_ID}, "${wizard_ffsync_public_url}", 1, 0, 4, 0, 0);
EOF

        echo ${separator}
        echo "Setup syncserver config file"

        MASTER_SECRET="$(tr -dc 'A-Z0-9' < /dev/urandom | head -c64)"
        METRICS_HASH_SECRET="$(tr -dc 'A-Z0-9' < /dev/urandom | head -c64)"

        # Perform replacements using sed with | as the delimiter
        sed -e "s|{{MASTER_SECRET}}|${MASTER_SECRET}|g"             \
            -e "s|{{TCP_PORT}}|${SERVICE_PORT}|g"                   \
            -e "s|{{SQL_USER}}|${DBUSER}|g"                         \
            -e "s|{{SQL_PASS}}|${DBPASS_ENC}|g"                     \
            -e "s|{{DB_SERVER}}|${DBSERVER}|g"                      \
            -e "s|{{DB_SOCKET}}|${DBSOCKET}|g"                      \
            -e "s|{{METRICS_HASH_SECRET}}|${METRICS_HASH_SECRET}|g" \
            -i "${CFG_FILE}"
    fi
}

service_postupgrade ()
{
    # Verify socket suffix when upgrading existing configs
    if [ ! -f "${CFG_FILE}" ]; then
        return
    fi

    echo "Verify database URLs for socket parameter"

    sync_before=0
    token_before=0
    if grep -q '^syncstorage\.database_url[[:space:]]*=.*\?socket=' "${CFG_FILE}"; then
        sync_before=1
    fi
    if grep -q '^tokenserver\.database_url[[:space:]]*=.*\?socket=' "${CFG_FILE}"; then
        token_before=1
    fi

    escaped_socket=$(printf '%s' "$DBSOCKET" | sed -e 's/[\/&|]/\\&/g')

    sed -i \
        -e "/^syncstorage\.database_url[[:space:]]*=/ { /\?socket=/! s|\"$|?socket=${escaped_socket}\"| }" \
        -e "/^tokenserver\.database_url[[:space:]]*=/ { /\?socket=/! s|\"$|?socket=${escaped_socket}\"| }" \
        "${CFG_FILE}"

    sync_after=0
    token_after=0
    if grep -q '^syncstorage\.database_url[[:space:]]*=.*\?socket=' "${CFG_FILE}"; then
        sync_after=1
    fi
    if grep -q '^tokenserver\.database_url[[:space:]]*=.*\?socket=' "${CFG_FILE}"; then
        token_after=1
    fi

    if [ "$sync_before" -eq 0 ] && [ "$sync_after" -eq 1 ]; then
        echo "Added socket parameter to syncstorage.database_url"
    fi
    if [ "$token_before" -eq 0 ] && [ "$token_after" -eq 1 ]; then
        echo "Added socket parameter to tokenserver.database_url"
    fi

    if [ "$sync_after" -eq 1 ] && [ "$token_after" -eq 1 ]; then
        echo "Database URLs now include socket parameter"
    else
        echo "Warning: unable to ensure socket parameter for both database URLs" >&2
    fi
}

validate_preuninst ()
{
    # Check database
    if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ] && ! ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e quit > /dev/null 2>&1; then
        echo "Incorrect MariaDB root password"
        exit 1
    fi
    # Check if database export path is specified
    if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ] && [ -n "${wizard_dbexport_path}" ]; then
        if [ ! -d "${wizard_dbexport_path}" ]; then
            # If the export path directory does not exist, create it
            mkdir -p "${wizard_dbexport_path}" || {
                # If mkdir fails, print an error message and exit
                echo "Error: Unable to create directory ${wizard_dbexport_path}. Check permissions."
                exit 1
            }
        elif [ ! -w "${wizard_dbexport_path}" ]; then
            # If the export path directory is not writable, print an error message and exit
            echo "Error: Unable to write to directory ${wizard_dbexport_path}. Check permissions."
            exit 1
        fi
        if [ -e "$wizard_dbexport_path/syncstorage_rs.sql" ] || [ -e "$wizard_dbexport_path/tokenserver_rs.sql" ]; then
            # If either syncstorage_rs.sql or tokenserver_rs.sql already exists, print an error message and exit
            echo "File syncstorage_rs.sql or tokenserver_rs.sql already exists in ${wizard_dbexport_path}. Please remove or choose a different location"
            exit 1
        fi
        # If everything is okay, perform database dumps
        ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" syncstorage_rs > "${wizard_dbexport_path}/syncstorage_rs.sql"
        ${MYSQLDUMP} -u root -p"${wizard_mysql_password_root}" tokenserver_rs > "${wizard_dbexport_path}/tokenserver_rs.sql"
    fi
}

service_postuninst ()
{
    # Export and remove database
    if [ "${SYNOPKG_PKG_STATUS}" = "UNINSTALL" ]; then
        ${MYSQL} -u root -p"${wizard_mysql_password_root}" -e "DROP DATABASE syncstorage_rs; DROP DATABASE tokenserver_rs; DROP USER '${DBUSER}'@'localhost';"
    fi
}
